Apuntes
Programación Orientada a Objetos
Ing. Jorge J. Prado Delgadillo
Curso Programación Orientada a Objeto
Profesor : Ing. Jorge J. Prado D. Docente UNI
CONTENIDO
CAPITULO I: EL PARADIGMA ORIENTADO A OBJETOS
1.1 Introducción, surgimiento y desarrollo del paradigma Orientado a Objetos
1.2 Clases y Objetos
1.3 Encapsulamiento
1.4 Herencia
1.5 Polimorfismo
1.6 Sobrecarga de Operadores y Funciones
1.7. Resumen del capitulo
1.7 Ejercicios de la unidad
CAPITULO II: METODOLOGIAS DE ANÁLISIS Y DISEÑO ORIENTADO A
OBJETOS
2.1 Comparación y evaluación de las metodologías de Análisis y Diseño Orientadas a
Objetos (Metodología OMT por Rumbaugh, Análisis y Diseño Orientado a Objetos por
Graddy Booch, etc).
2.1.1 Análisis Orientado a Objetos
2.1.2 Simbología y Notación del Diseño Orientado a Objetos
2.2 Construcción de modelos utilizando alguna de las metodologías estudiadas.
CAPITULO III : LENGUAJES ORIENTADOS A OBJETOS
3.1 Comparación y evaluación de los Lenguajes Orientados a Objetos (Visual Basic, Eiffel,
Smalltalk, C++, Java, etc.).
3.2 Aplicación de un Lenguaje Orientado a Objetos. Visual Basic
3.2.1 Sintaxis General del Lenguaje
3.2.2 Desarrollo e implementación de programas usando el Lenguaje
Orientado a Objetos
CAPITULO IV : INTRODUCCION A LAS BASES DE DATOS ORIENTADAS A
OBJETOS
4.1 Bases de Datos Orientadas a Objetos
4.2 Interfaces Gráficas del usuario Orientadas a Objetos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 2
CAPITULO I: EL PARADIGMA ORIENTADO A OBJETO
1.1.- INTRODUCCIÓN, SURGIMIENTOS Y DESARROLLO DEL
PARADIGMA ORIENTADO A OBJETO
1.1.1.- Introducción
ESTRUCTURADO
LOGICO
Paradigmas
FUNCIONAL
ORIENTADO A OBJETO
El Paradigma Estructurado:
El primero de los paradigmas utilizados en el desarrollo de la ciencias de computación, este
paradigma se aplica desde los albores del desarrollo de la computación ya que permitía dar
respuesta a las limitaciones de hardware que había en ese entonces, puesto que permitía entre
otras características la realización secuencia de las instrucciones o comandos para el
computador, el desarrollo secuencial de las mismas, la elaboración en bloque de instrucciones
de los programas, lo que permitía seccionar la solución informática y aplicarlas a las
necesidades de aplicación en los computadores de ese entonces.
Este paradigma duro lo suficiente hasta que las compañías y
empresas tuvieron una explosión de sus actividades y pasaron de
ser locales a ser regionales y nacionales, aumentado su grado de
complejidad y manejo de información, este se agudizo cuando las
necesidades pasaron las fronteras de los países y las empresas
nacionales se trasformaron en compañías internacionales.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 3
La ciencia de la computación tenía que
buscar otra alternativa, y con la
aparición de nuevos productos
electrónicos (El chip de las maquinas
computadoras) que permitía enormes
velocidades de proceso y la increíble
mejora de unidades de
almacenamientos internas y externas,
así como la creación de grandes
corporaciones multinacionales, se
tenía que trabajar en nuevo
paradigma que respondiera a esta
nuevas situaciones.
Programación imperativa
La programación imperativa, en contraposición a la programación declarativa es un
paradigma de programación que describe la programación en términos del estado del
programa y sentencias que cambian dicho estado. Los programas imperativos son un
conjunto de instrucciones que le indican al computador cómo realizar una tarea.
La implementación de hardware de la mayoría de computadores es imperativa; prácticamente
todo el hardware de los computadores está diseñado para ejecutar código de máquina, que es
nativo al computador, escrito en una forma imperativa. Esto se debe a que el hardware de los
computadores implementa el paradigma de las Máquinas de Turing. Desde esta perspectiva
de bajo nivel, el estilo del programa está definido por los contenidos de la memoria, y las
sentencias son instrucciones en el lenguaje de máquina nativo del computador (por ejemplo
el lenguaje ensamblador).
Los lenguajes imperativos de alto nivel usan variables y sentencias más complejas, pero aún
siguen el mismo paradigma. Las recetas y las listas de revisión de procesos, a pesar de no ser
programas de computadora, son también conceptos familiares similares en estilo a la
programación imperativa; cada paso es una instrucción, y el mundo físico guarda el estado
(Zoom).
Los primeros lenguajes imperativos fueron los lenguajes de máquina de los computadores
originales. En estos lenguajes, las instrucciones fueron muy simples, lo cual hizo la
implementación de hardware fácil, pero obstruyendo la creación de programas complejos.
Fortran, cuyo desarrollo fue iniciado en 1954 por John Backus en IBM, fue el primer gran
lenguaje de programación en superar los obstáculos presentados por el código de máquina en
la creación de programas complejos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 4
Algunos lenguajes imperativos empezaron a surgir tales como:
ASP , BASIC, C, C# , C++, Fortran, Pascal, Java, Perl , PHP, Lua
El Paradigma lógico
El paradigma lógico está orientado a la inteligencia artificial, es difícil estimar un tiempo
exacto en la historia de la computación cuando nace este paradigma, lo que vale destacar es
que su forma de afrontar los problemas es por medio de esquemas heurísticos, es decir
tomando en cuenta esquemas definidos de búsquedas y toma de decisiones a partir de una o
varias funciones de evaluación.
En 1972, en la universidad de Marsella, Francia, y otros científicos en Edimburgo trabajaron
con un lenguaje llamado Prolog, el cual tomo auge cuando el gobierno japonés lo designo
como lenguaje oficial de desarrollos de computadoras de quinta generación.
La programación lógica consiste en la aplicación del corpus de conocimiento sobre lógica
para el diseño de lenguajes de programación; no debe confundirse con la disciplina de la
lógica computacional.
La programación lógica comprende dos paradigmas de programación: la programación
declarativa y la programación funcional. La programación declarativa gira en torno al
concepto de predicado, o relación entre elementos. La programación funcional se basa en el
concepto de función (que no es más que una evolución de los predicados), de corte más
matemático.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 5
Historia
Históricamente, los ordenadores se han programado utilizando lenguajes muy cercanos a las
peculiaridades de la propia máquina: operaciones aritméticas simples, instrucciones de
acceso a memoria, etc. Un programa escrito de esta manera puede ocultar totalmente su
propósito a la comprensión de un ser humano, incluso uno entrenado. Hoy día, estos
lenguajes pertenecientes al paradigma de la Programación imperativa han evolucionado de
manera que ya no son tan crípticos.
En cambio, la lógica matemática es la manera más sencilla,
para el intelecto humano, de expresar formalmente
problemas complejos y de resolverlos mediante la aplicación
de reglas, hipótesis y teoremas. De ahí que el concepto de
"programación lógica" resulte atractivo en diversos campos
donde la programación tradicional es un fracaso
Campos de aplicación
La programación lógica encuentra su hábitat natural en aplicaciones de inteligencia artificial
o relacionadas:
Sistemas expertos, donde un sistema de información imita las recomendaciones de un
experto sobre algún dominio de conocimiento.
Demostración automática de teoremas, donde un programa genera nuevos teoremas
sobre una teoría existente.
Reconocimiento de lenguaje natural, donde un programa es capaz de comprender
(con limitaciones) la información contenida en una expresión lingüística humana.
Etc.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 6
La programación lógica también se
utiliza en aplicaciones más
"mundanas" pero de manera muy
limitada, ya que la programación
tradicional es más adecuada a tareas
de propósito general.
Fundamentos
La mayoría de los lenguajes de programación lógica se basan en la teoría lógica de primer
orden, aunque también incorporan algunos comportamientos de orden superior. En este
sentido, destacan los lenguajes funcionales, ya que se basan en el cálculo lambda, que es la
única teoría lógica de orden superior que es demostradamente computable (hasta el
momento).
En qué consiste (ejemplo)
La programación lógica permite formalizar hechos del mundo real, por ejemplo:
las aves vuelan
los pingüinos no vuelan
"pichurri" es un ave
"sandokan" es un perro
"alegría" es un ave
y también reglas o restricciones:
Una mascota vuela si es un ave y no es un pingüino
Ante dicho "programa" es posible establecer hipótesis que no son más que preguntas o
incógnitas, por ejemplo:
¿ "pichurri" vuela ?
¿ qué mascotas vuelan ?....
Gracias a que la lógica de primer orden es computable, el ordenador será capaz de verificar
la hipótesis, es decir, responder a las incógnitas:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 7
Es cierto que "pichurri" vuela.
"pichurri" y "alegría" vuelan.
Obsérvese que el programa lógico no
solamente es capaz de responder si una
determinada hipótesis es verdadera o
falsa. También es capaz de determinar
qué valores de la incógnita hacen cierta la
hipótesis.
Este ejemplo es claramente académico. Sin embargo, consideremos el siguiente ejemplo: el
sistema de control de semáforos de una ciudad.
El estado de cada uno de los semáforos (verde, rojo o ámbar) constituye los hechos del mundo
real. El programa en sí consiste en unas pocas reglas de sentido común: determinados
semáforos no pueden permanecer simultáneamente en verde, un semáforo solamente puede
transitar de verde a ámbar y de ámbar a rojo, etc. La hipótesis es el estado en el que deberían
estar cada uno de los semáforos en el siguiente instante de tiempo.
Éste es un ejemplo imposible de resolver mediante programación tradicional, ya que la lógica
subyacente al comportamiento de los semáforos en su conjunto queda enmascarada por
simples órdenes imperativas del tipo "cambiar color de tal o cual semáforo".
El paradigma funcional
El objetivo del paradigma funcional es conseguir lenguajes expresivos y matemáticamente
elegantes, en los que no sea necesario bajar al nivel de la máquina para describir el proceso
llevado a cabo por el programa, y evitando el concepto de estado del cómputo. La secuencia
de computaciones llevadas a cabo por el programa se regiría única y exclusivamente por la
reescritura de definiciones más amplias a otras cada vez más concretas y definidas, usando
lo que se denominan definiciones dirigidas.
Todo esto con el objetivo de familiarizar a los estudiantes con un lenguaje elegante en el
cual se pueda manejar más fácilmente y así los programas sean menos extensos y complejos.
Otro de los objetivos primordiales de dicho paradigma es buscar satisfacer las necesidades
del usuario con respecto a operaciones matemáticas y convertirse en un lenguaje más
expresivo.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 8
Historia
Sus orígenes provienen del Cálculo Lambda (o λ-cálculo), una teoría matemática elaborada
por Alonso Church como apoyo a sus estudios sobre Computabilidad. Un lenguaje funcional
es, a grandes rasgos, un azúcar sintáctico del Cálculo Lambda.
Cálculo Lambda
Los orígenes teóricos del modelo funcional se remontan a la década del 30, mas precisamente
al año 1934, cuando Alonso Church introdujo un modelo matemático de computación
llamado lambda calculo.
A pesar de que en esta época las computadoras aun no existían el lambda cálculo se puede
considerar como el primer lenguaje funcional de la historia y sus fundamentos fueron la base
de toda la teoría de la programación funcional y de los lenguajes funcionales desarrollados
posteriormente. Se puede decir que los lenguajes funcionales modernos son versiones de
lambda cálculo con numerosas ayudas sintácticas.
Características
Los programas escritos en un lenguaje funcional están constituidos únicamente por
definiciones de funciones, entendiendo éstas no como subprogramas clásicos de un lenguaje
imperativo, sino como funciones puramente matemáticas, en las que se verifican ciertas
propiedades como la transparencia referencial (el significado de una expresión depende
únicamente del significado de sus sub expresiones), y por tanto, la carencia total de efectos
laterales.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 9
Otras características propias de estos lenguajes son la
no existencia de asignaciones de variables y la falta de
construcciones estructuradas como la secuencia o la
iteración (lo que obliga en la práctica a que todas las
repeticiones de instrucciones se lleven a cabo por
medio de funciones recursivas).
Existen dos grandes categorías de lenguajes funcionales: los funcionales puros y los híbridos.
La diferencia entre ambos estriba en que los lenguajes funcionales híbridos son menos
dogmáticos que los puros, al admitir conceptos tomados de los lenguajes procedimentales,
como las secuencias de instrucciones o la asignación de variables.
En contraste, los lenguajes funcionales puros tienen una mayor potencia expresiva,
conservando a la vez su transparencia referencial, algo que no se cumple siempre con un
lenguaje funcional híbrido.
Entre los lenguajes funcionales puros, cabe destacar a Haskell y Miranda. Los lenguajes
funcionales híbridos más conocidos son Lisp, Scheme, Ocaml y Standard ML (estos dos
últimos, descendientes del lenguaje ML).
La programación funcional, es un modelo basado en la evaluación de funciones matemáticas,
entendidas como mecanismos para aplicar ciertas operaciones sobre algunos valores o
argumentos, para obtener un resultado o valor de la función para tales argumentos.
Sin embargo, tanto argumentos como resultado de una función, pueden ser otra función, o
incluso la misma, tal como una forma de recursividad, que constituye una poderosa
herramienta de la programación funcional
Lenguajes Funcionales
Los matemáticos desde hace un buen tiempo están resolviendo problemas usando el concepto
de función. Una función convierte ciertos datos en resultados. Si supiéramos cómo evaluar
una función, usando la computadora, podríamos resolver automáticamente muchos
problemas.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 10
El lenguaje funcional más antiguo, y seguramente el más popular hasta la fecha, es LISP,
diseñado por McCarthy [1] en la segunda mitad de los años 50. Su área de aplicación es
principalmente la Inteligencia Artificial. En la década de los 80 hubo una nueva ola de interés
por los lenguajes funcionales, añadiendo la tipificación y algunos conceptos modernos de
modularización y polimorfismo, como es el caso del lenguaje ML.
Programar en un lenguaje funcional significa construir funciones a partir de las ya existentes.
Por lo tanto es importante conocer y comprender bien las funciones que conforman la base
del lenguaje, así como las que ya fueron definidas previamente. De esta manera se pueden ir
construyendo aplicaciones cada vez más complejas.
Scheme
Scheme es un lenguaje funcional, derivado de LISP. Scheme es un lenguaje compacto con
un alto grado de abstracción, por lo cual resulta adecuado para cursos introductorios de
computación, donde el énfasis está en la metodología de resolución de problemas. Scheme
permite resolver problemas complejos con programas cortos y elegantes. De este modo, el
lenguaje se convierte en un aliado para resolver problemas, no un problema más que resolver.
Los paradigmas lógicos, funcional y orientados a objetos interactúan en el desarrollo de
soluciones computarizadas, realizando software de alta calidad y productividad en todos los
campos de la ciencia y de la sociedad.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 11
El Paradigma Orientado a Objeto POO
Podemos afirmar, que es la tónica del momento,
este paradigma de la ciencia de la computación ha
logrado en pocos años, de los 80s a la fecha
mantenerse en la cima de las aplicaciones
tecnológicas de computación.
Como un proceso natural de desarrollo a partir de los principios de la programación
estructurada, continua la programación orientada a objeto como un complemento y mejora
sustancial de la estructurada, esto ha generado múltiples usos en el campo científico, por lo
que podemos afirmar, que el paradigma orientado a objeto es la medula espinal del desarrollo
del software en la actualidad.
Es gracias a la programación orientada a objeto que la computación abrió
sus puertas al acceso de todas las personas e instituciones, existen otras
razones que también ayudaron a lo mismo, este paradigma vino a simplificar
el manejo de programas, aunque no necesariamente el trabajo del
desarrollador de aplicaciones, el programa sufrió una verdadera revolución
en su concepción de elaboración, todo en beneficio del usuario final del
mismo.
La programación orientada a objeto fue la respuesta a la gran complejidad de las
organizaciones modernas, que requerían de mecanismos rápidos de adaptación y manejo de
las personas dentro de las empresas y de sus procesos de trabajos, sean estos productivos, de
servicios o de cualquier otra índole.
En principio podemos afirmar que la programación orientada a objeto es que un sistema de
software se observa como un conjunto de secuencia de transformaciones a lo largo de la
aplicación, permitiendo la adecuación constante de estas transformaciones a través de la vida
del software, permitiendo una vida más larga y una utilidad de mayor relevancia.
En lo referente a este curso, abarca un estudio sobre el paradigma de programación orientado
a objeto, su metodología de análisis y diseño en el paradigma en cuestión. También
estudiaremos un lenguaje de programación de uso muy popular en el mercado y de fácil
acceso para crear aplicaciones basadas en objetos y orientadas a objetos, este lenguaje es el
Visual Basic, creado por la empresa MICROSOFT; y al final haremos una breve introducción
a las bases de datos orientadas a objetos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 12
1.1.2.- Surgimiento y desarrollo del Paradigma Orientado a Objeto.
Dos desarrolladores de lenguaje a inicios de los años 60 del siglo XX , Krysteen Nygaaard
y Ole-Johan Dhal crearon el lenguaje SIMULA en el Norwegian Computer Center (NCC),
el uso de este lenguaje era para modelar simulaciones de procesos industriales y científicos
y de sistemas en general.
Al aplicar el lenguaje los usuarios observaron que se podía utilizar en otras situaciones
diferentes a las de simulación de sistemas y empezaron a implementarlo en áreas diferentes
a las propuestas originalmente; el lenguaje fue perfeccionándose en los años siguientes , y
en la versión de SIMULA- 67 toma el concepto de Objeto, esta idea de estructura era
utilizada por el lenguaje ALGOL-60 .
La principal características de los “objetos” de SIMULA-67 es que tenían vida
propia y se intercomunicaban entre si durante el desarrollo de los procesos, a las
operaciones se les llamaron métodos; y también se introdujo la noción de clases ,
que servía para describir la estructura y comportamiento de un conjunto de
objetos
Entre las principales características del lenguaje de SIMULA-67 podemos observar :
1.- Usa el concepto de encapsulamiento y objeto estructura donde se agrupan atributos de
datos y acciones (métodos y procedimiento) que procesan datos.
IMPORTANTE
2.- Clases utilizadas como plantillas o patrones de objetos
3.- Herencia acción de agrupar propiedades comunes en varias clases
4.-Polimorfismo: Clases con interfaces idénticas y propiedades que se puedan intercambiar
Estas características, que son propias del paradigma orientado a objeto las analizaremos con
más detalles posteriormente.
SIMULA -67 genera Smalltalk (1980), que se puede considerar como el primer lenguaje
propiamente orientado a objeto, su creador Alan Kay de Xerox Parc aplico todas las
características del paradigma y las implemento en su trabajo. A partir de entonces se han
desarrollado una gran cantidad de lenguajes orientados a objetos (LOO), algunos lenguaje
son :
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 13
Smalltalk -80
C ++
Actor
Objective- C
CLOS
Object Pascal
Object Cobol
Java
Eiffel
Lenguajes Visuales basados en objetos y orientados a objetos
Java es un nuevo lenguaje de propósito general, propio para escribir programas en
Internet, este lenguaje es totalmente orientado a Objeto y puede considerarse como una
excelente mejora de C++.
Podemos afirmar que el paradigma orientado a objeto reina en las metodologías actuales y
pasaran varios años para que resulte un nuevo paradigma para que la reemplace totalmente.
La programación orientada a objeto vino para quedarse y mejorar nuestras vidas.
OBJETOS
CLASES
CARACTERISTICAS ENCAPSULACION
DEL PARADIGMA
ORIENTADO A OBJETO POLIMORFISMO
HERENCIA
Java es un lenguaje moderno derivado de C y
C++, por lo que guarda y utiliza todas las
características de estos lenguajes de
programación, adicionándoles el uso de las
características del paradigma orientado a
objeto
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 14
1.2.- Objetos y Clases
1.2.1.- Objetos
Lo que hace al paradigma orientado a objeto muy interesante es la facilidad de reflejar
sucesos del mundo real mediante estructuras de objetos, podemos afirmar que el mundo real
está lleno de objetos, el televisor que utilizamos, el celular para comunicarnos, el semáforo
que controla el transito, la contraseña para ingresar al servicio del cajero automático, el
formato que llenamos en una aplicación, los seres humanos, la tierra , el Sistema Solar, la
galaxia ,todo está formado por objetos. Vivimos e interactuamos con objetos desde que
nacemos.
La principal característica de los objetos, desde el punto de vista de computación,
es que contiene información, es decir datos que los caracterizan de una forma
particular y también realizan acciones (procedimiento o funciones) para
interactuar con otros objetos.
Los ejemplos dados anteriormente, el televisor, celular, etc. Como sabemos comparten
características comunes, es decir por ejemplo todos los televisores se apagan, encienden
cambian de canal, nivelan el sonido…, ahora cada televisor podrá funcionar de manera
específica, los automóviles se trasladan aun con diferentes mecanismos de conducción
gasolina, diesel, gas, etc.
Cada objeto es una instancia de una clase, lo que lo ubica en dicho conjunto de objetos de
dicha clase, esta clase, como lo vimos anteriormente contiene datos y métodos que la
identifican plenamente del resto del mundo de los objetos.
Definición de objeto
Un objeto es una abstracción de cosas (entidades) del mundo real talque todas las
cosas del mundo real, llamadas instancias, tienen las mismas características y
además todas las instancias siguen las mismas reglas.
ATRIBUTOS
Partes de
Un objeto
OPERACIONES
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 15
Cada objeto consta de estados (atributos) y operaciones o comportamientos
(llamados métodos los cuales son invocados por mensaje)
Desde el punto de vista informático, los objetos son tipos abstractos de datos (tipos que
encapsulan datos y funciones que operan sobre esos datos)
Ahora surge la pregunta ¿Cómo podemos
identificar los objetos en el mundo real?, ¿Cómo
podemos deducir los objetos dentro del dominio
de la definición del problema?, después de una
intensa observación y descripción del problema
análisis gramatical del enunciado o descripción,
los objetos según Shlaer, Mellor y Coad/Yourdon
pueden caer dentro de las categorías:
Cosas tangibles (camión, bicicleta, batería, motor, libro)
Roles o papeles jugados o representados por personas (gerentes, operarios, usuarios cliente)
Organizaciones o instituciones (Empresas división, departamento, equipo)
Procesos u acciones que representan un suceso (evento) u ocurrencias, tales como llamada
a un servicio, juego, acción determinada, pueden ser física o real.
Interacciones Generalmente implican un contrato, o transacción y relacionan dos o más
objetos del problema en cuestión
Especificaciones muestran aplicaciones o plantillas de artículos, productos industriales
Lugares oficinas, sala de estudio, aula, muelle de embarque.
Cuando hemos determinados los posibles objetos pasamos a identificar los posibles
atributos y las operaciones sobre ellos
Los ATRIBUTOS describen la abstracción de características individuales que poseen
todos los objetos.
Ejemplos :
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 16
Objeto: Empleado :
Atributos: Nombre
Dirección
Ubicación
Nombre del departamento
Nivel de estudio
Objeto: Película
Atributos: Nombre
Director
Genero
Duración
Color
Objeto: Alumno
Atributos : Nombre Objeto: Alumno
Número de carné Juan Pérez
Ubicación 1678-4589
Carrera Ing. Computación
Fecha de ingreso 12/12/2011
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 17
Actividad de aprendizaje del alumno:
Realice un análisis de situaciones cosas u procesos que usted conozca y
represéntelos como objetos, al menos unos cinco, coméntelo con su grupo de
clase.
Las OPERACIONES O METODOS u
acciones cambian el comportamiento
del objeto referente a su
comportamiento original de alguna
forma, es decir pueden cambiar valores
de algunos de sus atributos, las
: operaciones podemos clasificarlas en
tres grupos
Operaciones o métodos que manipulan los datos de forma específica
Ejemplo Agregar, modificar, eliminar, Visualizar, Mover, Desplazar, etc.
Operaciones o métodos que realizan un cálculo o proceso específico ejemplo:
Calcular_distancia, mover, cerrar, Ejecutar_descuento,
Operaciones o métodos de comprobación (o monitoreo) un objeto frente a la ocurrencia
de un evento. Ejemplo: Verificar_edad, comprobar_id
También podemos preguntarnos ¿Cuánto dura un objeto? Los objetos son entidades por lo
que pueden ser creados o instanciados, por lo general a través de constructores como en
Java, Visual Basic, C++ o inicializadores
Veamos los ejemplos anteriores con algunas posibles operaciones
Objeto: Empleado :
Operaciones o Métodos:
Atributos: Nombre Agregar_empleado
Eliminar_empleado
Dirección
Calcular_salario
Ubicación
Calcular_deducciones
Nombre del departamento
Nivel de estudio
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 18
Objeto: Película
Atributos: Nombre Operaciones o Métodos:
Director Agregar_pelicula
Genero Eliminar_pelicula
Duración Modificar_pelicula
Color
Objeto: Alumno
Atributos : Nombre Operaciones o Métodos:
Número de carné Agregar_alumno
Ubicación Eliminar_alumno
Carrera Verificar_notas
Fecha de ingreso
Actividad de aprendizaje del alumno:
Realice un análisis de situaciones cosas u procesos que usted conozca y
represéntelos como objetos, al menos unos cinco, de forma completa sus
posibles atributos y operaciones, coméntelos con sus compañeros de clase
Comunicación entre objetos: Mensajes.
Un mensaje es una solicitud de un objeto a otro objeto al cual se le solicita
ejecutar uno de sus métodos, por convenio el objeto que envía la solicitud se le
llama emisor y el objeto que recibe la solicitud se denomina receptor.
Los mensajes pueden venir de:
a.- El exterior, ejemplo un ratón,
teclado, impresora.
b.- Otro objeto, el objeto A solicita
información al objeto B.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 19
Los objetos necesitan de los mensajes para interactuar con el exterior, es
su forma básica de comunicación
Aquí tenemos un ejemplo gráfico:
Objeto A
mensajes Objeto B
Datos Datos
Objeto C
Datos
Objeto D
Datos
Un mensaje consta de:
Identidad del receptor
El método que se debe ejecutar
Información especial necesaria a veces para realizar el método invocado
Cuando un objeto está inactivo – durmiendo - y recibe un mensaje se hace activo. El mensaje
enviado por otros objetos o fuentes tiene asociado un método que se activara cuando un
receptor recibe un mensaje.
1.2.- Clases
Otro elemento básico del paradigma orientado a objeto es el concepto de clases; La clase es
una estructura de lenguaje para definir tipos abstractos de datos en lenguajes de programación
orientados a objetos (POO), su aparición es desde 1967 en el lenguaje SIMULA y la define
como una entidad que declara conjuntos de objetos similares.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 20
Las clases son modelos o plantillas para objetos
|
Podemos afirmar que las clases son como los tipos ( ¿Qué es un tipo de dato? ) en un
lenguaje tradicional de programación con la salvedad que el usuario puede definir nuevos
tipos en un lenguaje orientado a objetos
Las clases son una descripción abstracta, ideal de un grupo de objetos,
cada uno de los cuales se diferencia por un estado especifico y es capaz
de realizar una serie de operaciones.
Gráficamente podemos representar una clase como un rectángulo.
Clase A
Ejemplo de clases:
1.- Madonna, Michael Jackson, Prince pertenecen a la clase “cantantes de rock”
2.- Los alumnos de segundo año de Ingeniería en computación de la UNI, pertenecen a la
clase “Estudiantes de Ingeniería en computación de segundo año de la UNI”
3.- Carlos Andrés Pérez, Violeta Barrios, Bill Clinton, pertenecen a la clase “Ex presidentes
de América”
Actividad de aprendizaje: Analice con su grupo de clase y asigne el nombre
posible de la clase de las descripciones siguientes, rellene los espacios
1.- Todos los clientes activos de un banco perteneces a una clase______________.
2.- Los perros pertenecen a la clase de los ____________ .
3.- Los vuelos de aerolíneas de la empresa XYZ pertenecen a una clase: ____________
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 21
4.- Los monitores de los computadores pertenecen a una clase._______________
5.- Los procesadores de los computadores pertenecen a una clase._________________
6.- Los alimentos que consumimos pertenecen a una clase._________________
7.- La tierra pertenece a la clase denominada “planetas”.
11.- Todos los automóviles pertenecen a la clase de ________________
12.- El proceso de matricula pertenece a una clase llamada _______________
Las clases deben contener datos, es decir, atributos que son propios de la clase y con los
cuales podemos realizar procedimientos (métodos) para obtener resultados esperados.
Los datos pueden ser de tipo público, los cuales interactúan con el mundo exterior y los datos
privados que son utilizados solamente por la clase, veamos algunos ejemplos de clase con
sus posibles propiedades y funciones o comportamiento:
Publico – interactúan con las otras clases
DATOS
Privado – interactúa solo dentro de la clase
Ejemplos de clases
Clases Posibles atributos Posibles comportamiento
Ser humano Piel Comer
Cabello Caminar
Extremidades Correr
Color de la piel Jugar
Automóvil Color Encender
Tipo de Chasis Apagar
Numero de puertas Correr
Número de Asientos Trasladar
Tipo de tablero Cargar
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 22
Otros ejemplos de clases:
Clase Posibles atributos Posible Comportamiento
Bicicleta Modelo Frenar
Velocidades Cambiar velocidades
color
Naranja Dulzura Pelar
Color Pudrirse
tipo Exprimir
Edificio Temperatura Abrir
Número de pisos Cerrar
Número de habitaciones Calefacción
Estudiante Nombre Cambiar clases
Dirección Matricular
Numero de Carne Graduar
Año de estudio Inscribir materias
Debemos tener en mente que lo que programamos son las clases y no los objetos, es
decir las abstracciones de datos, esta se realiza de diversas formas en los lenguajes
orientados a objetos.
Ejemplos de codificación de una clase en diversos lenguajes:
El lenguaje de programación Java tiene una forma para declarar una clase, analicemos el
siguiente ejemplo: (No se preocupe por la codificación, esta se analizara en detalle en una
unidad de estudio posterior)
Import [Link].*;
Class Primero {
Public static [Link] (String args[] ) throws IOException
{
[Link] (“Este es una aplicación en Java.\n”);
[Link] (“Esta es una clase llamada para realizar
impresiones.\n”);
} // Fin del main
} // Fin de la clase
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 23
Ejemplo de Clase en Visual Basic, Visual Basic tiene clases visuales tales como TextBox,
Label, form, etc y clases no visuales que pueden ser definidas por el usuario.
VISUALES – Formatos presentados por el lenguaje
CLASES EN
VISUAL
BASIC NO VISUALES- Elaborados por el programados según criterio
propio
Para definir una clase en Visual Basic este soporta su creación en la generación de modulo
de clases, esto permite la definición genérica de objetos, veamos el siguiente ejemplo:
Modelo de la definición en el modulo de clase de la clase CCliente
‘ Variables de miembro privado
Private [Link] As sTring Declaración de datos privados
Private [Link] As String
‘Observemos que todos los procedimientos property son public de manera
‘ predeterminada
Property Get nombre() as string
‘ Devuelve el valor actual de la variable miembro
Nombre = [Link]
Forma de escribir
End property
comentarios en Visual
Basic
Property Let Nombre (ByVal nuevoValor As string)
‘provoca error si se intenta una asignación de un valor no valido
If nuevoValor = “” then [Link] 5 ‘Procedimiento no valido
[Link] = nuevoValor
End property
Forma de declarar
Function NombreCompleto() as string funciones en Visual Basic
NombreCompleto = Nombre & “ “ & Apellido
End Function
En C++ las clases se definen y se ejecutan, pero debe existir un procedimiento main() para
iniciar el programa y las llamadas de funciones , veamos el formato para definición de clase
en C++
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 24
// definición de clase (localizado en clasenombre.h )
class clasenombre
{
lista de variable miembro
lista de funciones miembro (usualmente prototipos o encabezados miembros
};
Nota : Observe el punto y coma después del cierre de llaves
Ejemplo especifico de clase en C++ :
// Clase luz
{
private:
int status // Luz esta en On(1) o en Off(0)
public:
luz() ; // constructor por defecto
luz ( int statusIn); // constructor para especificar estado
int cambio(); // Cambiar el estado
void printStatus(); // imprimir o visualizar le estado actual
};
Nota : // Sirve para presidir comentarios en C++ o Java
1.3 Encapsulamiento o Encapsulación
El concepto de Encapsulamiento es el siguiente, cuando tomamos el control remoto de un
televisor, este aparato podemos utilizarlo para muchas funciones y solo sabemos que
funciona!, ¿Cómo funciona ?, ¿Cómo guarda los datos que le programamos? No lo
sabemos pero obtenemos la respuesta que esperamos, el control remoto del televisor es
como una caja negra, no sabemos que contiene ni como ejecuta,. Solo sabemos el resultado.
El Encapsulamiento – a veces llamado también Ocultamiento de la información
es la idea de empacar juntas en una unidad de programación una colección de
miembros de datos y sus funciones (operaciones )bien definidas.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 25
Debemos saber que encapsulación es el significado de empacar datos y/o operaciones dentro
de una sola unidad (clase) de programación bien definida.
MUY
IMPORTANTE
Con el ocultamiento de la información logramos establecer una relación de vinculación entre
las operaciones y sus datos , la unidad – es decir la clase- , tiene una interfaz por medio del
acceso de sus datos miembros públicos , y la sección privada proporciona información que
se accesa solamente desde la clase, solo las operaciones miembros definidas en la clase
funcionan sobre los miembros de la clase privada, de esta forma , la sección privada de una
clase proporciona el ocultamiento de la información.
Sin Encapsulamiento ni ocultamiento de la información, no tenemos relación de vinculación,
esto no garantiza seguridad y que eventos ajenos a la clase puedan alterar el contenido y
proceso de la misma, además logra que las operaciones definidas sean las únicas que se
realizan en la clase, esto permite seguridad a la hora de realizar aplicaciones en el mundo
real.
En lenguajes que no tienen la propiedad de encapsulación los datos y las funciones que las
operan se determinan de manera separada, después se colocan juntas en un archivo de código
y se ejecutan, esta situación puede permitir algunas veces, irregularidades que conllevan a
resultados no deseados en el desarrollo de las aplicaciones
Como en el paradigma
estructurado…
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 26
CLASE Métodos Privados
Métodos públicos
Variables de instancias
privadas
El encapsulamiento presenta la seguridad, los métodos públicos protegen los
datos privados.
Actividad de aprendizaje Analice en grupo,
con sus compañeros, lea cuidadosamente los
dos enunciados que siguen y diseñe una clase
en cada caso.
a) Una clase cuadrado que consiste en la altura y el la longitud con funciones para
inicializar los miembros privados, calcular el perímetro del cuadrado y el área del
mismo.
¿Existe otra forma de diseño alterna a la propuesta?, justifique su respuesta
b) Una clase estado de cuenta de cliente que utiliza el monto depositado, la taza de
interés y el tiempo de ahorro, calcular el monto final a retornar cuando se venza el
período.
Con sus compañeros de grupo escriba por lo menos dos diseños alternos de la
clase
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 27
1.4 Herencia
Una característica muy importante del paradigma orientado a objeto además de los vistos
anteriormente es la de herencia.
La Herencia es la capacidad de permitir a los objetos ser construidos a partir de
otros objetos
La idea de herencia parte de la experiencia de la vida real las clases básicas o fundamentales
se dividen en subclases, por ejemplo los seres humanos se dividen en varones y mujeres,
los animales se dividen en mamíferos, insectos, peces, etc., la clase automóvil se puede
dividir en automóviles de lujo, de carrera, anfibios, de carga …
La herencia se utiliza con el fin de la
reutilización del código original utilizado en la
clase fundamental y variarlo en una subclase
especifica.
El principio de la división se basa en la jerarquía compartiendo características comunes, por
decir, todos los seres humanos, tienen extremidades, color de piel, respiramos, caminamos,
corremos.
La herencia es una jerarquía de clases (Superclases - Clases derivadas)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 28
La herencia parte de una clase fundamental llamada base o superclase y basado en la
jerarquía de clases derivamos unas subclases llamadas clases derivadas. las nuevas clases,
las clases derivadas, pueden heredar el código y los datos de su clase base , a esto le añadimos
su propio código especial y datos de ella, en la clase derivada podemos cambiar los datos
heredados para beneficio propia de la subclase.
Las clases mantienen relaciones con otras
clases, diferente a las relaciones con las
clases derivadas, las clases existentes en la
aplicación expresan las características
exactas de su clase y estas sirven como una
plantilla o modulo, entonces las clases
derivadas heredan características de la clase
base, y pueden agregar sus propias
características.
En muchos lenguajes una subclase también puede ser una superclase de otra clase, la clase
automotores puedes ser una superclase de la clase motocicleta, camión y auto, camión puede
ser superclase de las clases derivadas camión de combate y camión de carga, y así
sucesivamente.
Algunos lenguajes de programación permiten que una superclase o clase base sea una clase
abstracta con métodos posiblemente indefinidos, entonces cada subclase puede definir el
método como se requiera. (Esto se conoce como polimorfismo, que lo estudiaremos mas
adelante)
Una clase abstracta sirve como una sección de métodos y atributos compartidos para las
subclases del nivel inmediatamente inferior. Estas no tienen instancias directamente y su
función principal es agrupar otras clases y capturar información que es común al grupo, la
clase abstracta es un ”contenedor”, las subclases de clases abstractas que corresponden a
objetos del mundo real pueden tener instancias.
Una clase abstracta es una clase que sirve de base común, pero esta no tendrá instancias
Podemos identificar dos tipos de herencias en las clases, herencia simple y herencia múltiple
En la herencia simple o herencia jerárquica, una clase u objeto hereda solo una subclase, es
decir una subclase puede heredar datos y métodos de una única clase base, también puede
modificar – agregar o quitar – comportamientos de la clase base, algunos lenguajes de
programación orientado a objetos solo permiten este tipo de herencia.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 29
En la herencia múltiple o herencia de malla, una subclase puede tener mas de un ascendiente
inmediato, es decir, puede heredar de mas de un clase base (súper clase), esta herencia
puede ser reemplazada por medio de la herencia simple y a veces es mejor utilizar este tipo
de herencia, C++ permite la herencia múltiple, Smalltalk, no permite la herencia múltiple
pero Eiffel si.
Podemos afirmar que por lo general todo lo que hacemos con la herencia múltiple se puede
realizar con la herencia simple.
Clase cliente de Banco
Cuenta de ahorro Cuenta de cheques
Cuenta en córdobas Cuenta en dólares
La clase cliente de Banco es la clase base o superclase, la cual deriva en las clases cuenta
de ahorro y de cheques (Clases derivadas) y estas a la vez son superclases de otras
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 30
1.5 Polimorfismo
Esta propiedad de la programación orientada a objeto , en su esencia es, el uso de un nombre
o símbolo para representar o significar mas de una acción o método, por ejemplo los
operadores aritméticos son un clásico ejemplo de esta característica , el operador + se utiliza
para sumar valores numéricos, pero también se utiliza para concatenar cadenas de caracteres
.
Se denomina polimorfismo (del griego polymorphos = muchas formas), cuando un operador
existente en el lenguaje tales como +, = ,*, tienen la posibilidad de operar sobre diversos tipos
de datos ( enteros , dobles, caracteres) , entonces decimos que esta sobrecargado.
La ventaja del uso del polimorfismo y la sobrecarga de los operadores o métodos de las
clases, es que permite que los nuevos tipos de datos sean manipulados de manera similar.
Podemos afirmar que el polimorfismo supone que un mismo mensaje puede
producir acciones o resultados totalmente diferentes cuando estos actúan sobre
objetos diferentes.
El polimorfismo se lleva a cabo usando funciones virtuales o funciones sobrecargadas,
estas funciones tienen características muy propias para su elaboración.
Las funciones sobrecargadas se llaman usando enlace estático
Las funciones virtuales se llaman usando enlaces dinámicos.
Un enlace se refiere al tiempo real cuando se anexa o se une el código a una función dada.
1.6 Sobrecarga de Operadores y Funciones
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 31
La sobrecarga es la capacidad de utilizar el mismo nombre de operación para funciones
similares que tienen un comportamiento diferente cuando se aplicas a clases diferentes. Esto
lleva por consiguiente que los nombres de las operaciones se puedan sobrecargar .
Si los nombres de una operación se utilizan para nuevas definiciones en clases de una
jerarquía, la operación a nivel inferior anula la operación a nivel superior. Analicemos el
siguiente ejemplo de una sobrecarga en las clases y sus derivadas.
La sobrecarga se presenta cuando los métodos tienen el mismo nombre, pero se
aplica a datos distintos, lo que sucede entonces es que el compilador puede
determinar que operador utilizar en tiempo de compilación y así manejar la
función correcta.
Analicemos un ejemplo de sobrecarga:
En Java por ejemplo únicamente presenta un sobrecarga en el operador + con cadenas de
caracteres y otros tipos de datos primitivos (int, double…), por lo que podemos utilizar
operaciones del tipo:
Int x = 12;
“Valor de x es: “ + x;
Cuando el compilador Java se encuentra con esa operación no realiza suma aritmética sino
que convierte el valor entero 12 en la cadena “12” y concatena o une con la cadena operando
de la izquierda.
En trabajo colaborativo con sus compañeros realice los siguientes ejercicios y designen un
secretario relator para que explique cualquiera de los ejercicios delante de toda la clase de
acuerdo a lo orientado por el profesor.
La sobrecarga de operaciones no es propia solo de
los lenguajes orientados a objetos, el lenguaje C,
Pascal y otros del paradigma estructurado
soportan la sobrecarga de operaciones, la
sobrecarga se aplica solamente a las operaciones,
pero, puede extenderse esta propiedad a los
atributos y relaciones específicas del modelo de
estudio
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 32
Resumen del Capitulo
En Conclusion:
El paradigma orientado a objeto es de
amplia utilización en el desarrollo de
aplicaciones de computación y otras
tecnologías, desarrollado desde los años
60 del siglo XX, toma su máximo
desarrollo a partir de los años 80’s con la
aparición de Smalltalk y otros paquetes
con características orientadas a objeto.
El paradigma orientado a objeto tiene sus propias características que lo definen como tal entre
las principales tenemos:
Objeto es algo real que se puede manejar
en un programa, el objeto lo debemos
definir por una clase determinada para
poder usar esta. Los objetos son
instancias de la clase que lo define
Clase es una interfaz modelo o plantilla que define el comportamiento de un conjunto de
objetos que presentan características similares tanto en la definición de sus datos miembros
como de sus posibles comportamientos (métodos o funciones de la clase)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 33
Encapsulación Es la
capacidad de trabajar con los
datos y métodos (o
procedimientos)
considerándolo como una
unidad, el Encapsulamiento
permite a las funciones de la
clase trabajar solo con los datos
privados de ellas, evitando el
ingreso de datos intrusos
externos a la clase, esta
característica ofrece robustez a
la programación orientada a
objeto.
Polimorfismo es la propiedad que
permite el uso del mismo método o
función trabajar con valores de datos
distintos, el compilador se encarga de
asignar la operación correspondiente
correcta.
Herencia es la propiedad de la programación orientada a objeto que permite a una clase
llamada base o superclase heredar datos y métodos a otras llamadas derivadas o subclases,
esto permite reutilizar el código creado en la creación de las mismas varias veces
Mensajes los objetos forman parte de un conjunto complejo de acciones y eventos que se
presentan a lo largo de un problema de la vida real, con la interacción de los objetos, lo que
se logra a través de mensajes, los programadores consiguen una funcionalidad de alto nivel
y un comportamiento más complejo.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 34
Ejercicios de reforzamiento de la unidad
En trabajo colaborativo con sus
compañeros realice los siguientes
ejercicios y designen un secretario
relator para que explique
cualquiera de los ejercicios delante
de toda la clase de acuerdo a lo
orientado por el profesor.
1.- Describa y justifique los objetos que obtiene de cada uno de los enunciados:
1.1.- Los habitantes de Managua y sus direcciones de habitación
1.2.- los clientes de un banco, con préstamos hipotecarios
1.3.- los alumnos de primer ingreso de una universidad
1.4.- Los empleados de una empresa y su puesto de trabajo
1.5.- Las presentaciones de películas en salas de cine.
2.- Defina los objetos en los siguientes sistemas:
2.1.- Un celular
2.2.- Un sistema de registro de estudiantes
2.3.- Un sistema de suscripción a una revista
2.4.- Un sistema de control de mercadería en una tienda
2.5.- Un control de clases recibidas en un semestre
3.- Realice un trabajo de auto estudio y análisis con su grupo de clase sobre lo siguiente:
3.1.- ¿Qué diferencia existe entre un objeto y una clase?, Investigue que es una instanciación
y explíquelo con un ejemplo
3.2.- Explique el polimorfismo de manera grafica con un ejemplo específico, ¿Cuál es su
ventaja, que optimiza?
3.3.- ¿Cuáles son las ventajas de la encapsulación en los objetos? Realice un cuadro de esas
ventajas
3.4.- ¿Cuáles son las dos secciones principales que forman la estructura de una clase?
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 35
4.- Realice los siguientes trabajos y exprese su opinión sobre ello en clase expositiva
4.1.- ¿Cómo implementamos la herencia en un lenguaje como java?, escriba un ejemplo y
explíquelo brevemente.
4.2.- Algunos lenguajes de programación orientados a objetos utilizan los eventos, en qué
consisten? De un ejemplo especifico en VISUAL BASIC y preséntelo en la clase de
presentación
4.3.- Una ventana de un programa de computadora se puede considerar como un objeto de
una clase ventana, ¿Qué datos y operaciones deben ser parte de este objeto? ¿Por qué razón,
explique?
4.4.- ¿Una clase es una interfaz Si o No, por qué? Investigar y presentar sus anotaciones
resumidas en un documento.
5.- Definir una clase EMPLEADO que represente a los empleados de una empresa, si
tenemos la información disponible para cada empleado que es:
Nombre del empleado
Puesto de trabajo
Salario bruto por hora
Estos tienen entre otras responsabilidades:
Inicializar un nombre de empleado a blanco
Designar salario bruto a 0.00
Determinar el salario
¿Cuál información dada puede ser atributo? Cuáles pueden ser operaciones, diseñe un
algoritmo para la operación determinar salario, explique porque considera correcta esa
operación algorítmica?
6.- Escriba una clase de nombre CALENDARIO que conste de unos ochos o más
campos de atributos y que contengan la fecha y por los métodos u operaciones tenemos:
a) Construir una fecha dados el día, mes y año
b) Determinar si la fecha es valida
c) Retornar la siguiente fecha a una fecha determinada
d) Devolver el nombre del día de la semana correspondiente a una fecha dada
e) Devolver el nombre del mes correspondiente a una fecha dada.
Realice un algoritmo por cada método u operación dada en el ejercicio. Prepare la respuesta
y preséntela con sus compañeros
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 36
II UNIDAD
Sistemas de información
El analista en su desempeño realiza diferentes tipos de sistemas de información,
todo con el objetivo de satisfacer las demandas y/o necesidades de cada nivel de
una institución o empresa en la cual realiza su trabajo.
¿Qué es un
analista de
sistema?
En las instituciones se presentan muchos sistemas de información, pero podemos
nombrar las categorías que mas se presentan:
Sistemas de carácter transaccional:
Estos sistemas procesan grandes cantidades de información, que se utilizan como
insumo para generar una gran cantidad de información valiosa para los ejecutivos y
responsables de la toma de decisiones en los niveles superiores.
Podemos decir que una transacción representa un evento o situación que se
realiza muchas veces en la empresa , por ejemplo revisar el saldo de los clientes,
los pagos realizados por los mismos, los pedidos que solicitan los clientes, etc,.
Entre las transacciones más comunes podemos encontrar los sistemas de:
Pedido de mercaderías
Compra de artículos insumos en la empresa
Facturación a clientes
Pago de nomina a empleados
Deposito de cheques u otras transacciones en el banco.
La principal característica de los sistemas transaccionales incluye actividades
repetitivas de cálculos de operaciones, organización y clasificación de la
información, almacenamiento de una forma segura y de fácil acceso a las
personas autorizadas para ello.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 37
Estos procedimientos facilitan la mecánica de cada transacción, su secuencia en la
realización y los pasos a dar cuando existan excepciones de las mismas. Estos
sistemas so de carácter operativo y existen en todas las empresas, además son los
primeros en ser automatizados, pues como lo manifestamos anteriormente sirve de
insumo para sistemas de mayor jerarquía, por otro lado dicha automatización
permite mejorar las actividades rutinarias de la empresa.
Los sistemas transaccionales permiten el almacenamiento de la información en las
bases de datos de las empresas, para un mejor manejo y utilización de los mismos.
Actividad de reforzamiento de estudio
Pregunta de análisis para el grupo de trabajo
1.-¿Todas las instituciones tienen sistemas transaccionales? Justifique su
respuesta
2.- ¿Cual es la principal característica de los sistemas transaccionales?
Sistemas de información gerencial:
También conocidos como sistemas de información administrativa, ya que permite
ayudar a los administradores en la toma de decisiones de manera científica y
estructurada, lo que permite resolver los problemas a nivel intermedio de la
empresa.
Estos sistemas permiten organizar, estructurar y filtrar los datos de los
sistemas transaccionales para la emisión de reportes en forma periódica a las
autoridades competentes, los cuales tomaran las medidas pertinentes para
optimizar la situación.
Estos reporte, a manera de ejemplo, podrían ser :
Reporte de pagos de clientes por sucursal
Reporte de ventas de X productos, por sucursal, por fecha.
Reporte de saldos de clientes
Reporte de porcentajes ganados por vendedor en cada sucursal
Reporte de impuesto a pagar en el mes.
Esta información el gerente podrá observar el comportamiento de la unidad y tomar
las acciones que considere conveniente para su mejora. Es decir que política tomar
con respecto al producto X de acuerdo al informe presentado sobre el mismo.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 38
Estos sistemas suelen ser realizados después de la implantación de los
sistemas transaccionales, estos depuran, filtran y organizan datos de acuerdo a
las necesidades de los ejecutivos de los datos de los sistemas transaccionales.
Relación entre tipos de
sistemas
Estos sistemas ofrecen una gran variedad de reportes y sirven de apoyo a la toma
de decisiones a nivel intermedio de la organización, además facilitan el trabajo al
tomar decisiones sobre datos reales actualizados en el sistema.
Cada área necesita un sistema gerencial especifico acorde a las necesidades
propias de dicha sección y en busca de obtener resultados rápidos y
correctos.
(Inventario, Finanzas, Recursos Humanos, Producción, etc.)
Actividades de reforzamiento de estudio
Con su grupo de estudio analice las posibles ventajas del uso de los sistemas
de información gerencial en contraste con las desventajas de no usarlos en
una empresa o institución.
Sistemas de soporte a las decisiones:
La principal características de estos sistemas es que sirven de apoyo a la toma de
decisiones de los niveles intermedios y altos de la organización. Estos sistemas
son intensivos en cálculos y escasos en entradas y salidas de información.
La principal características de ellos es de ser interactivos y muy amigables,
de una manera muy gráficos y/o visuales, suelen estar dirigidos a los usuarios
finales, en muchas ocasiones suelen ser desarrollados directamente con la
participación del usuario
Sistemas estratégicos:
Las empresas realizan uso de estos sistemas para obtener ventajas competitivas
con otras empresas del mismo tipo en el mercado, Su principal funciones lograr
ventajas que los competidores no los posean, sirven para apoyar situaciones de
la empresa tales como:
Mejora de productos y servicios que oferta la empresa.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 39
Reducción de costos por medio de alternativas viables de realización de los mismos
Innovación de productos y procesos.
Sistemas expertos:
Llamados también sistemas basados en el conocimiento, la inteligencia artificial es
el campo principal de los sistemas expertos.
Estos sistemas mejoran la calidad y eficiencia en los procesos de las tomas
de decisiones porque tienen muy poca dependencia de las personas, estos
sistemas permiten deducir por medios lógicos y heurísticos cual es la mejor
estrategia o solución a determinados problemas de tipo especifico planteado al
sistema.
Actividades de reforzamiento de estudio
Con su grupo de estudio analice las posibles ventajas del uso de los sistemas
de descritos arriba en contraste con las desventajas de no usarlos en una
empresa o institución. Exprese su opinión en un cuadro comparativo de
ventajas y desventajas de cada sistema de información.
INTRODUCCION AL ANALISIS Y DISEÑO DE SISTEMAS
Conceptos de Análisis y Diseño Estructurado.
Diseño de arriba – abajo:
Existen varias formas de buscar la solución a un problema desde el punto de vista
computacional, una de las formas mas usadas es por medio del paradigma
estructurado, el cual consiste en descomponer un problema en sus unidades
componentes y después analizar dichas unidades, si es necesario, que una unidad
se descomponga en nuevos componentes, pues lo hacemos y analizamos los
nuevos, y así sucesivamente.
El diseño de arriba –abajo proporciona este método para descomponer un
problema dado en sus unidades componentes o módulos. Este diseño recibe otros
nombres tales como diseño estructurado, diseño compuesto, etc. Todas estas
metodologías describen la descomposición del problema en sus funciones más
importantes, la subdivisión de esas funciones en subdivisiones y así
sucesivamente
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 40
Al aplicar este método, nos permite registrar los niveles de complejidad asociados
con cada solución, y además descubrir los requerimientos operacionales de los
procesos en cada sub unidad.
Cuando realizamos este tipo de análisis, el análisis estructurado, logramos evitar
soluciones ilógicas y soluciones relacionadas con solo una parte del problema
planteado. El dominio que aplica la solución se llama abajo –arriba. Porque este
método permite analizar un nivel a la vez con toda rigurosidad, permitiendo asegurar
todas las operaciones necesarias para satisfacer la solución.
Este método se puede visualizar por medio de graficas, llamadas diagramas de
estructuras, los cuales son parecidos a los organigramas de las empresas, con la
diferencia que estos presentan módulos en que han sido divididos. Estos módulos
mantienen algunas reglas muy importantes que se deben de cumplir:
1.- Cada modulo debe ser independiente de los demás módulos.
2.- La responsabilidad operacional de cada modulo debe
ser definida concisamente.
3.- Cada modulo debe ofrecer solo un punto de entrada.
Estas reglas permiten mantener una uniformidad en cuanto al flujo de los procesos
y de permitir navegar por el diagrama de estructura solamente por las relaciones
establecidas en cada modulo, además permite tratar cada uno de ellos como una
entidad independiente, logrando atacar sus necesidades hasta solventarlas.
El método arriba – abajo dominó los análisis de problemas informáticos hasta
los años 80`s, cuando la metodología orientada a objetos se desarrollo como
una alternativa nueva para solucionar problemas que la metodología
estructurada no lo hacia.
Ejemplo de diagrama de estructura:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 41
Proceso de nomina
de empleados
Leer datos de Procesar Emitir
empleados Pagos Reporte
Actividades de reforzamiento de estudio
1.- Realice un esquema resumen de media página con sus propias palabras
sobre el diseño estructurado
2.- ¿Por qué el diseño estructurado fue el primero en utilizarse en la ciencia
de la computación, explique sus razones?
3.- ¿Quiénes y en que periodo de tiempo se utilizo el diseño estructurado?¿
Se sigue utilizando?, Justifique su repuesta.
4.- Realice con sus compañeros de clases un debate sobre la importancia
actual del diseño estructurado.
5.- investigue y exponga en clase un modelo de sistema de información que
utilice el diseño estructurado.
Conceptos básicos de Análisis y Diseño Orientado a
Objeto (ADOO)
El análisis orientado a objeto es parte del paradigma orientado a objeto donde se
trata de resolver problemas en computación aplicando la metodología Orientada a
Objeto, esta metodología analiza la situación pensando en los procesos en algo
similar a la organización de un grupo de individuos, como un equipo, club o
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 42
asociación, puesto que cuando ocurre un evento en el equipo, este lo realiza un
miembro del grupo, el cual se responsabiliza de dicha acción. No existen acciones
–eventos- de por si, alguien o algo debe de responsabilizarse de ello.
El análisis orientado a objetos se basa en la solución del problema a partir
de objetos, es decir que la implementación del software será a partir de
comportamiento específicos de los objetos. Además los objetos tienen
procesos dinámicos en el análisis, estos pueden generar nuevos objetos,
crear nuevas relaciones entre los objetos, ser destruidos.
Es como analizar una estructura compleja , que se va armando por partes ,
sub partes, sub sub partes, etc.
En este tipo de análisis nos preocupamos por las acciones, llamadas eventos que
ocurren al interactuar los agentes (Objetos), cuanto mas definimos los posibles
eventos, cuando mejor los relacionamos en función de dar una solución real, en
tiempo, segura y completa del problema , el software será la solución al problema
lo mas ajustada a la realidad del mismo.
El análisis de los sistemas en el paradigma orientado a objetos, se realiza al definir
los objetos que actúan en el sistema, así como los eventos que interactúan
con ellos. La creación y manipulación de los objetos permite la reutilización del
software , y en caso necesario, construir nuevas clases , cuando modelamos el
problema de la empresa o institución los analistas deben identificar los tipos de
objetos y las operaciones necesarias para que los objetos se comporten de
determinada manera.
En el análisis orientado a objeto, la acción se inicia mediante la transmisión de
un mensaje a un agente, un objeto, responsable de la acción, este mensaje
tiene la petición de una acción y se acompaña de cualquier información, argumento,
que ayude para llevar a cabo esta solicitud. El receptor (otro objeto) es el agente al
cual se le envié el mensaje, si el objeto que atiende el mensaje, acepta la
responsabilidad de llevar a cabo una acción indicada en respuesta al mensaje, este
objeto ejecutara algún método para satisfacer la solicitud.
Volveremos sobre el análisis orientado a objetos en breve, pasaremos a estudiar un
poco sobre los sistemas de información que se presentan en las instituciones y
empresas del mundo real, el ingeniero de computación debe mantener una visión y
estrategia firme de las características que se presentan en los distintos entornos
donde se desarrollara.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 43
Ejemplo de diagrama de flujo de objetos:
Diseño de equipo para clientes de la empresa XYZ S.A.
Adquirir materiales Materiales de clientes
de construcción producción
Producir tarjetas de Tarjetas de Ensamblar Ensamblar
circuitos impresos circuitos computadora computadora
impresos s
Diseño de
Producir hardware
diseño
Actividades de reforzamiento de estudio
1.- ¿Cuál es la base de un análisis de sistema orientado a objeto?, explique
brevemente.
2.- Explique al menos tres eventos que se pueden presentar en un análisis de
sistema orientado a objeto de un proceso de matrícula de estudiante.
Justifique.
3.- ¿Qué interactúan en un análisis orientado a objetos, a través de que lo
hacen?
ANALISIS ORIENTADO A OBJETOS (AOO)
Debemos mantener presente que el análisis de los sistemas no cambia, aunque
cambien las herramientas de programación lo que cambia es el modelo que
enfoca dicho análisis.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 44
Así sabemos que en un análisis de sistema en el entorno de un problema enfocado
en dirección de un análisis estructurado, el analista, o los analistas utilizan un
Diagrama de Flujo de Datos (DFD) para construir su modelo. Cuando utilizamos el
análisis orientado a objetos utilizamos otras herramientas para llevar adelante el
modelo del sistema, utilizamos objetos, relaciones entre ellos y no solo datos.
Capas del Análisis orientado a Objetos (AOO):
Coad Yourdon aplica las siguientes capas como herramientas en el modelaje
orientado a objetos, estas cinco capas son:
1.- Capa de Clase y Objeto Esta capa identifica los objetos que interactúan en el
sistema, estos pueden ser cosas reales : papeles, eventos, transacciones o
especificaciones, como siguiente paso es identificar las clases y representarlas,
además podemos definir clases abstractas , es decir clase que no tengan ningún
objeto o instancia, pero no al contrario, es decir todo objeto debe tener una clase
que lo represente.
2.- Capa de estructura Esta capa indica las relaciones y las posibles herencias
entre las clases y objetos del sistema
3.- Capa de atributos Esta capa define los atributos de cada objeto para poder
manejarlos eficientemente dentro del sistema de estudio
4.- Capa de Servicios Esta capa no indica los mensajes y comportamiento del
objeto
5.- Capas de Tema Esta capa divide al modelo del sistema en unidades para facilitar
su estudio e implementación de los mismos.
Metodologías de Análisis y Diseño Orientados a
Objetos
El Paradigma orientado a Objetos busca el modelaje del mundo real y plasmarlo en
aplicaciones computacionales, este paradigma presenta, gracias a sus
características de encapsulación, herencia, polimorfismo, entre otras, herramientas
muy poderosas para la creación de aplicaciones.
En este segmento estudiaremos una breve introducción al modelado de objetos y
sus relaciones fundamentales, aplicaremos el concepto de herencia en las
relaciones de clases y su gran facilidad para reflejar situaciones que se presentan
en el mundo real.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 45
Si pensamos construir un sistema orientado a objeto, el primer paso es definir la
creación de clases (objetos) que representan el problema a resolver. La forma en
que se relacionan las clases y su funcionamiento interno de los atributos y métodos,
de las formas de comunicación mediante los mensajes, la forma de definirlas las
clases si se requieren abstractas o no, en que tipo de eventos actúan.
Como objetivo fundamental de un análisis del problema orientado a objeto (AOO)
es la definición de todas las clases que son relevante para el mismo, sus atributos
y operaciones, las relaciones y demás elementos que determinan el ámbito del
problema..
Analizaremos los tipos de relaciones que se pueden presentar en las clases
resultantes de un análisis con este tipo de enfoque
2.1. Relaciones de Clases
Cuando modelamos objetos, las clases al igual que los objetos tienen diferentes
formas de relacionarse entre ellas, con el propósito de lograr los objetivos
propuestos de la aplicación de estudio.
Según Booch existen en las relaciones de clases las siguientes formas:
Generalización/Especialización (es un)
Agregación (Todo-parte/Tiene un)
Asociación
Uso
Instanciación (Plantilla)
Metaclase
Abordemos un poco sobre ellas
2.1.1.- Generalización/Especialización (es un / is –a)
Un forma eficiente de organizar las clases es por medio de estructuras jerárquicas,
la herencia es un relación entre clases, donde sabemos, que comparten atributos
y/o métodos definidos en una (herencia simple) o mas clases (herencia múltiple).
Sabemos que se denomina superclase a la clase base que hereda una o mas
clases denominadas subclases.
Una subclase heredara atributos y comportamientos de una superclase de orden
jerárquico mayor. Gráficamente podemos verlo así:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 46
computador
desktop laptop
Teclado monitor
Grafico Subclases de la clase computador.
Jerarquías de generalización/especialización:
Cuando trabajamos con clases en el modelo, las reunimos con características
comunes en una clase especial llamada superclase, una superclase representa un
generalización de las subclases, de manera inversa una subclase representa una
especialización de una superclase.
Una manera importante en el análisis de un modelado de objetos es definir clases
que son muy generales y partir de ellas empezamos a especializar las clases
(subclases) que si tienen acción en el campo de definición del problema. A estas
clases que no existen les llámanos clases abstractas y su propiedad
fundamental es que no pueden crear instancias de ellas. Podemos afirmar por lo
tanto que la generalización es una abstracción de un conjunto de objetos de
propiedades similares representadas mediante un objeto genérico.
factura
credito contado
especial normal
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 47
Ejemplo de relación generalización de la clase abstracta factura
Cuenta cliente
Cuenta corriente prestamos Depositos
Generalización metodología OMT.
La relación de generalización se representa por un triángulo en la metodología OMT.
2.1.2 Agregación (Todo-parte/Tiene un)
Una agregación es una relación que representa a los objetos compuestos, es decir
un objeto que se compone a su vez de otros objetos , podemos tener como ejemplo
una persona se compones de sistemas biológicos: Óseo, muscular, endocrinico,
etc.. un edificio se compone de puertas, piso , ventabas, paredes, que a su vez son
también objetos
Cuando realizamos un análisis del mundo real, el problema se presenta de una
forma compleja, es decir, modelo compuesto de muchos objetos, que también
representan modelos a integrar a la solución, la agregación es un concepto que se
utiliza para expresar tipos de relaciones entre objetos parte-de (part-of) o tiene-
un (has-a), el nuevo objeto resultante es un objeto que se forma de múltiples
objetos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 48
automovil
PUERTAS RUEDAS LUCES
NEUMATICOS RADIO
Nota : Ejemplo de agregación (metodología OMT)
2.1.3 Asociación
Una Asociación es una conexión entre clases, es decir un enlace que define los
papeles o roles que juegan los objetos entre si, establecen su dependencia entre
los objetos de dos clases y su cardinalidad (multiciplidad), es decir cuántas
instancias de cada clase pueden estar aplicadas en una asociación.
Una asociación representa una dependencia bidireccional, a menos que se explique
una única dirección.
Por ejemplo una sala de cine exhibe una película y una película es exhibida en una
sala de cine, el objeto película se relaciona con el objeto sala de cine por medio de
la relación exhibe.
CINE PELICULA
Una relación de asociación se describe con frases tales como “ es miembro de “
“tiene un “, “ trabaja para “, etc.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 49
posee
persona vehiculo
1 0..n
Notación Grafica en la metodología Booch’93 podemos afirmar que una persona
puede tener 0 o mas vehículos, el carácter ● indica el origen de la relación tiene-un
Las opciones de cardinalidad en una relación tiene-un están :
1 exactamente 1
N Número ilimitado
0..N Cero o mas
1..N Uno o mas
3..8 Rango especifico
1..4, 7 Rango especificado o numero exacto
UML (Unified Modeling Lenguaje )
UML podemos considerarlo como lo mas representativo de los métodos de análisis
y diseño orientados a objetos que aparecieron a finales de los ochenta y primeros
años de los noventa, expertos tales como Coad/Yourdon, Shlaer y Mellor, Booch,
OMT, Jacobson. Han realizado grandes aportes al análisis del modelado de datos.
El UML define una notación y un metamodelo, la notación es la parte medular que
se presenta en los modelos, es la sintaxis del lenguaje de modelado, un metamodelo
es un modelo que representa al método orientado a objetos y lo define con rigor ,
es por lo general un diagrama de clases que define la notación.
Cuando realizamos un modelado orientado a objetos, las clases y los objetos con
sus respectivas relaciones son la parte fundamental del modelado. El modelo de
clase y objetos nos muestra el sistema que tratamos de describir. Cuando logramos
el modelo del sistema el siguiente paso es programar orientado a objetos, el análisis
orientado a objetos trata de crear modelos de dominios de interés de la aplicación,
es decir, que se pueda representar por medio de programas orientados a objetos.
Diagramas de clases:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 50
Un diagrama de clases es un tipo de modelo estático, podemos afirmar que un
modelo de diagrama de clases presenta una forma estática de un sistema en
términos de clases y sus relaciones
Persona
Atributos
Nombre relevantes Persona
Dirección
Edad
Notación reducida
Leer() Operaciones
Establecer_limite() Funciones
. Metodos
.
Notación de una clase
En un análisis orientado a objetos la creación de clases es un proceso altamente
creativo, fundamentalmente debemos tener un completo conocimiento del dominio
del problema.
Ejemplo de AOO: Utilización de tarjetas CRC
Fichas o tarjetas CRC (clase, responsabilidad, colaborador)
El uso de fichas para representar las clases individuales es una técnica, de las
muchas que existen, que se utiliza para asignar responsabilidades a cada acción,
esta fichas se conocen como Tarjetas CRC (Beck 89) , una tarjeta CRC esta
dividida en tres partes
Clase : Nombre en la esquina superior izquierda que es de la clase que esta
definida, la selección de nombres de clases es de suma importancia , puesto que
con los nombres de las clases se crea el vocabulario con el que se formulara
el diseño.
Responsabilidades : Están descritas debajo del nombre de la clase, estas
describen el problema que se va a resolver , estas frases deben ser cortas, que
expresen un verbo activo, deben describir que se debe hacer y evitar los detalles
de cómo se deben hacer.
Colaboradores: Los objetos necesitan de la colaboración de otros objetos,
cuando solicitan una acción por medio de mensajes, casi todos los objetos guardan
relación con otro objeto del sistema. La clase colaboradora se escribe en la parte
derecha de la ficha CRC.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 51
Ejemplo de tarjeta o ficha CRC:
Modelo de un cajero automático
VerificadorDeDatos Colaboradores
Muestre mensaje de bienvenida, espere VerificadorNIP
tarjeta
VerificadorDeActividad
Pida al VerificadorNIP que compruebe
datos
Llame al SelectorDeActividad
Devuelva Tarjeta al usuario
La clase VerificadorDeDatos tiene cuatro responsabilidades que se detallan en la
tarjeta y dos clases colaboradoras que se relacionan con ella para satisfacer sus
responsabilidades, la creación de clase por medio de tarjetas CRC u otro método
donde se expresen claramente las clases y sus relaciones permiten crear análisis y
diseños robustos que dan respuesta a los problemas planteados en el sistema.
Otro método de AOO: Clases y su relación con los objetos.
Como sabemos la clase es una representación abstracta que describe a un conjunto
de objetos, estos objetos tienen en común una misma estructura (de datos) y un
mismo comportamiento (las mismas funciones), en otras palabras son la misma
cosa y hacen lo mismo.
En la fase de diseño de una programa o aplicación, el elemento fundamental son
determinar las clases; porque un conjunto de objetos iguales, debe ser representado
en forma abstracta por una clase, esta clase es la que vamos a programar en un
lenguaje de programación orientado a objeto (LOO) .
Diseño del programa.
Para diseñar un programa, se elabora o diseña el algoritmo que soluciona el
problema de tres partes:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 52
Primero se diseña el diagrama de clases
Segundo se diseña la lógica de las clases en pseudocódigo
Tercero se realiza la prueba con el lenguaje OO.
Como determinar las clases en los problemas de programación
Cuando hemos identificado los objetos del problema se procede a diseñar el
diagrama de clases, como dijimos los objetos serán las clases del problema, es decir
su plantilla o abstracción de objeto o clase, es recomendable dibujar la clase con
representación de algunos objetos, que en este diseño serán instancias de la clase
Observemos el siguiente ejemplo de una clase y algunas de sus instancias:
CLIENTE
Nombre
Dirección
….
ObjetoCliente ObjetoCliente ObjetoCliente
Nombre Juan Nombre Pedro Nombre María
Explicación
Se diseña la clase CLIENTE, de la cual se genera una instancia, que es el objeto
que representa al cliente Juan, otra instancia que genera al cliente Pedro, y así
sucesivamente.
Para diseñar una estructura de clase, se debe hacer dos cosas:
1.- Definir los datos que 2.- Definir los métodos u
representaran a los objetos de la operaciones que implementaran las
clase acciones de los objetos.
Los datos son de dos tipos Los métodos son de dos tipos
A.- el tipo de dato que entrara como A.- son los métodos que colocan o
materia prima, es decir que se establecen (setter) valores a los
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 53
deberán leer a través de un datos del objeto, ya sea a través de
dispositivo de entrada leerlos o mediante cálculos.
B.- El tipo de dato que se deben B.- Los métodos que acceden u
generar mediante cálculos u obtienen (getter) los valores de los
operaciones en los métodos datos para utilizarlos, ya sea para
realizar cálculos o darles salida.
Cómo identificar los métodos en una clase
Cuando realice el análisis del problema se buscan los verbos. Por lo general estos
son métodos u operaciones de la clase, por ejemplo: LeerLosDatos, ImprimirSalario,
VerificarId, etc. CalcularSalario, EncontrarIva
MUY IMPORTANTE:
Para establecer los valores de cada uno de los datos de un objeto, se
debe definir un método del objeto (Clase) que permita colocar (setter)
el valor a cada dato, ya sea que lo lea o que lo calcule
De igual forma para dar salida al valor de un dato se requiere un
método de acceder (getter) al valor del dato para darlo como salida,
uno para cada uno.
Por ejemplo, tenemos la clase de CLIENTE donde tenemos que calcular el saldo
del cliente, tenemos que cada objeto se representa mediante los datos:
NombreCliente --- Nombre del cliente
SaldoAnterior ---- Saldo antes del abono
Abono ---- Abono del mes
CuotaInteres ---- Calculo de interés
SaldoNuevo ---- Saldo actual
Entonces para cada dato se debe establecer un método setter y/o getter , en el
ejemplo se requieren los siguientes métodos:
EstablecerNombreEm( ) Para leer (entrada) el valor del dato nombre
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 54
EstablecerSaldoAnt( ) - Para leer (entrada) el Valor del dato Saldo Anterior
EstablecerAbono ( ) Para leer Abono el valor del dato abono del cliente
CalcularCuotaInte( ) - Calcular el valor del dato interés
CalcularNuevoSaldo( ) Calcular el dato nuevo saldo
Obtener(Nombre( ) Para acceder y visualizar (imprimir) el valor del
dato nombre
ObtenerNuevo Saldo( ) Para acceder y visualizar (imprimir) el valor del dato
Nuevo saldo.
Nota: Observe que el método setter inician su nombre con establecer o calcular
Los métodos getter inician con obtener
Algunas
Observe quecaracterísticas dedefine
no para todos los datos se la encapsulación
un método getter.
Modificadores de acceso (visibilidad)
Los símbolos - + # _ * sirven para indicar la visibilidad que tendrá cada dato o
método, se conocen como modificador de acceso:
Privado (-) Estos datos solo pueden ser vistos y utilizados por los
(Private) métodos de la misma clase. Por defecto los datos de
una clase son privadosa
Protegido ( # ) Pueden ser vistos y utilizados por métodos de la
(Protected) mmisma clase y por métodos de subclases derivadas
de la clase madre.
Publico (+) Pueden ser visto y utilizados tanto por métodos de la
(Public) clase, como por métodos de otra clase
Estático (_) Son únicos para toda la clase, es decir, no peaerteneen
(Static) a ninguna instancia (objeto) de la clase, pero pueden ser
utilizados por todas las instancias de la clase.
Abstracto ( * ) Los métodos que se declaran abstracto no tienen
( Abstract) implementación, por lo tanto deber ser implementados
en subclase
Como generar instancias de clases
Las clases definidas se utilizan para generar instancias u ocurrencias, estas
instancias son los objetos, que se utilizaran en el funcionamiento del programa,
esto significa que podemos ver la clase como un molde o plantilla o un tipo de
dato, que se utiliza para generar objetos específicos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 55
CLIENTE
Nombrecliente
SaldoAnterior
Abono
establecerNombreEmp()
establecerSaldoAnte()
establecerInteres()
calcularSaldoActual()
ObjetoCliente ObjetoCliente
NombreCliente NombreCliente
Juan Maria
SaldoAnterior SaldoAnterior
4574.50 12740.50
Abono Abono
560.00 6600.00
establecerNombreEmp() establecerNombreEmp()
establecerSaldoAnte() establecerSaldoAnte()
establecerInteres() establecerInteres()
calcularSaldoActual() calcularSaldoActual()
Explicación
En el ejemplo anterior podemos observar que tenemos la clase CLIENTE, la cual
genera una instancia que es el ObjetoCliente que representa a Juan, y así
sucesivamente hasta generar todas las instancias de la clase.
Puede observar que las instancias de la clase tienen los mismos tipos de datos y
métodos, pero NO la misma información
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 56
Como realizamos el programa orientado a objeto
Arquitectura modelo-vista-controlador
Un programa orientado a objeto que utilice la arquitectura modelo-vista-
controlador.
Esta formado por tres partes muy importantes:
1.- El modelo
Es la clase o conjunto de clases identificadas en el dominio del problema,
esta clase (o clases) representan al objeto u objetos presentes en el
problema
2.- La Vista o Interface grafica de usuario
Es la que el usuario observara en la pantalla, impresora u otro dispositivo
de salida de la computadora al operar el programa
3.- El controlador
Es la parte que permite que el usuario interactúe con la interface para
utilizar el modelo que representa y soluciona el problema planteado, puede
ser otra clase o varias
En programas complejos, la arquitectura modelo-vista-controlador se observa
asi:
CONTROLADOR
En programas
MODELOno muy complejos o que la vista INTERFAZ
es sencilla O
la VISTA
parte controlador se
combina con la interfaz y la arquitectura se simplifica:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 57
MODELO CONTROLADOR
Diseño de clases con algoritmos OO, utilizando el modelo- vista-
controlador.
Ejemplo Calcular el salario de un empleado, información a sacar por pantalla
Nombre del empleado y Salario semanal, datos conocidos : nombre, número de
horas trabajadas y pago por hora del empleado
El salario se calcula de la manera siguiente:
Si el número de horas trabajadas es mayor que 40, el excedente de 40 se paga al
doble de la cuota por hora, en caso de no ser mayor que 40 se paga a la cuota por
hora normal.
Realicemos la solución de acuerdo al modelo-vista-controlador
Solución
Primero: Se diseña el diagrama de clases
Empleado
NombreEmpleado
HorasTrabajadas
PagoHora
Salario EjecutaEmpleado
EstablecerNombre()
EstablecerHoras()
EstablecerPago()
CalcularSalario()
ObtenerNombre()
ObtenerSalario()
Explicación
Este diagrama consta de dos clases; una clase es la clase Empleado que es el
modelo que representa y soluciona el problema planteado; la otra es la clase
EjecutaEmpleado que es la clase controlador, la cual utiliza el modelo (la clase
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 58
Empleado) para controlar la interacción con el usuario representado y resolviendo
el problema
Segundo: Se diseña la lógica de las clases en pseudocódigo
Algoritmo Calcular Salario de un empleado
Clase Empleado
1.- Declaraciones
Datos
NombreEmpleado: Cadena
HorasTrabajadas: Entero
PagoHora: Real
Salario: Real
2.- Metodo EstablecerNombre( nom: cadena)
NombreEmpleado = nom
Fin Metodo EstablecerNombre
3.- Metodo Establecerhoras(horas: Entero)
HorasTrabajadas = horas
Fin Metodo EstablecerHoras
4.- Metodo EstablecerPago( pago: Real)
PagoHora = pago
Fin Metodo EstablecerPago
5.-Metodo CalcularSalario( )
If HorasTrabajadas<= 40 Then
Salario = HorasTrabajadas * PagoHora
Else
Salario = (40 * PagoHora) + (( HorasTrabajadas -40) *( PagoHora * 2))
Endif
Fin Metodo EstablecerNombre
6.- Metodo ObtenerNombre() : Cadena
Return NombreEmpleado
Fin Metodo ObtenerNombre
7.- Metodo ObtenerSalario( ) : Real
Return Salario
Fin Metodo ObtenerSalario
Fin de clase empleado
Clase EjecutaEmpleado
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 59
Metodo Principal
Declaraciones
Variables
NEmple : Cadena
HT: Entero
PagoH: Real
Declarar, crear e iniciar objeto
Empleado objEmpleado = new Empleado()
Solicitar nombre, número de horas, pago por hora
Leer NEmple, HT, PagoH
Establecer [Link](NEmple)
[Link](HT)
[Link](PagoH)
Calcular [Link]()
Imprimir [Link]()
[Link]()
Fin Metodo principal
Fin clase EjecutaEmpleado
Tercero se realiza la prueba con el lenguaje OO. (! Esto se estudiara en la
Siguiente unidad ¡)
Diseño de algoritmo OO usando selección múltiple
Ejemplo:
Elaborar un algoritmo que dado un numero del 1 al 7, el programa imprima por
pantalla “Domingo ”,si es 1, “Lunes”, si es 2… “Sábado”, si es 7.
Solución:
Diagrama de Clases
PresentaDia
NumeroDia
NombreDia
EjecutaPresentaDia
EstablecerNDia()
CalcularNombreDia()
ObtenerNombreDia()
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 60
Segundo: Se diseña la lógica de las clases en pseudocódigo
Algoritmo PresentaDia de la semana
Clase PresentaDia
Declaraciones
Datos
NumDia : Entero
NombreDia : Cadena
Metodo EstablecerNDia( num: Entero)
NumDia = Num
Fin de método EstablecerDia
Metodo CalcularNombredia()
Swith NumDia
1: Nombredia = “Domimgo”
2: Nombredia = “Lunes”
3: Nombredia = “Martes”
4: Nombredia = “Miercoles”
5: Nombredia = “Jueves”
6: Nombredia = “Viernes”
7: Nombredia = “Sabado”
DEFAULT
NombreDia = “No está en el rango de 1 a 7 “
ENDSWITCH
Fin Metodo CalcularNombreDia
Metodo ObtenerNombreDia() : Cadena
Return NombreDia
Fin Metodo ObtenerDia
Fin clase PresentaDia
Clase EjecutaPresentaDia
Metodo Principal
Declaraciones
Variables
Ndia : Entero
Declarar, crear e iniciar objeto
PresentaDia Objdia = new PresentaDia
Solicitar numero de dia
Leer Ndia
Establecer [Link](Ndia)
Calcular [Link]()
Obtener [Link]()
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 61
Fin Metodo Principal
Fin Clase EjecutaPresentaDia
Tercero se realiza la prueba con el lenguaje OO. (Esto se estudiara en la
Siguiente unidad ¡¡¡)
Diseño de algoritmo OO usando Estructura de repetición
DO…WHILE
Ejemplo:
Elaborar un algoritmo para calcular e imprimir el sueldo de varios empleado
de una empresa.
Datos disponibles: Nombre, Horas Trabajadas, Cuota por Hora
Proceso: Sueldo = Horas Trabajadas * cuota por Hora
Imprimir: Nombre, Sueldo.
Solución:
Diagrama de Clases
Empleado
NombreE
HorasT
PagoH
Sueldo
EstablecerNombreE() EjecutaEmpleado
EstablecerHorasT()
EstablecerPagoH()
CalcularSueldo()
ObtenerSueldo()
ObtenerNombreE()
Segundo: Se diseña la lógica de las clases en pseudocódigo
Clase Empleado
Declaraciones
Datos
NombreE : Cadena
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 62
HorasT : Entero
PagoH : Real
Sueldo : Real
Metodo EstablecerNombreE(nom : Cadena)
NombreE = nom
Fin método EstablecerNombreE
Metodo EstablecerHorasT (Horas : Enterol)
HorasT = Horas
Fin de método EstablecerHorasT.
Metodo EstablecerPagoH( Pago : Real)
PagoH = Pago
Fin Metodo EstablecerPagoH
Metodo CacularSueldo()
Sueldo = HorasT * PagoH
Fin método CalcularSueldo
Metodo ObtenerNombreE(): Cadena
Return NombreE
Fin Metoddo ObtenerNombreE
Metodo ObtenerSueldo() : Real
Return Sueldo
Fin método ObtenerSueldo
Fin Clase Empleado
Clase EjecutaEmpleado
Metodo Principal
Declaraciones
Variables
NomEmple : Cadena
HTraba : Entero
PagoHora : Real
Desea : Carácter
Do
Declarar, crear e iniciar objeto
Empleado objEmpleado = new Empleado()
Solicitar Nombre, horas trabajadas, cuota por hora
Leer nomEmple, HTraba,PagoHora
Establecer
[Link](NomEmple)
[Link](HTraba)
[Link](PagoHora)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 63
Calcular [Link]()
Imprimir [Link]()
[Link]()
Preguntar “¿Desea procesar otro empleado (S/N) ?”
Leer Desea
WHILE Desea = “S”
Fin Metodo principal
Fin clase EjecutaEmpleado
Diseño de algoritmo OO usando arreglos unidimensionales
Ejemplo:
Se conoce el número de unidades producidas por un obrero en cada uno de los 30
días del mes. Elaborar un algoritmo que permita leer la producción de cada uno de
los 30 días y luego los visualice.
Solución
Diagrama de clases
Clase: Obrero
establecerProduccion()
EjecutaObrero
obtenerProduccion()
Algoritmo Obrero
Clase Obrero
1.- Declaraciones
Datos
Producción: Arreglo[30] : Entero
2.- Método establecerProduccion(pro[]: Entero)
Producción = pro
Fin método establecerProduccion
3.- Metodo obtenerProduccion(): Arreglo[] Entero
Return producción
Fin método obtenerProduccion
Fin Clase Obrero
Clase Ejecutaobrero
1.- Metodo principal
Declaraciones
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 64
Variables
Prod, prod2:arreglo[30] Entero
I : Entero
Declarar, crear e iniciar objeto
Obrero objObrero = new Obrero()
For i = 0; i<=29; i++
Solicitar producción del dia i +1
Leer prod[i ]
EndFor
Establecer
[Link](prod)
Obtener
Prod2 = [Link]()
For i = 0 ; i <= 29: i++
Imprimir prod[i]
EndFor
Fin Metodo principal
Fin Clase EjecutaObrero
Diseño de algoritmo OO usando herencia
Ejemplo:
En cierta empresa se tienen empleados; los empleado se dividen en dos tipos,
empleados por hora, a los que se les paga de acuerdo con el número de horas
trabajadas y a una cuota por hora. El otro tipo son los empleados asalariados, a
quienes se les paga de acuerdo a un sueldo fijo mensual.
Analisis, en este problema podemos identificar dos objetos :
Objeto EmpleadoPorHora
nombreEmpleado
deptoEmple
puestoTrabajo
horasTrabajo
cuotaHora
sueldoHoras
Objeto EmpleadoAsalariado
nombreEmpleado
deptoEmple
puestoTrabajo
sueldoMensual
sueldoQuincenal
Observamos que los objetos tienen datos en común, cuando se tiene una situación
como esta, podemos utilizar el mecanismo de herencia, mediante un proceso de
abstracción en el que definimos un objeto más abstracto que contenga en común a
los demás objetos, para uqe a partir de ese se deriven los otros objetos a utilizar.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 65
Empleado
EmpleadoPorHora EmpleadoAsalariado
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 66
Aplicando el diseño de estructura de clase tenemos:
Empleado
# nombreEmpleado
# deptoEmple
# puestoTrabajo EjecutaEmpleado
establecerNombre()
establecerDepto()
establecerPuesto()
obtenerNombre()
obtenerPuesto()
obtenerDpto()
EmpleadoPorHora EmpleadoAsalariado
horasTrabajadas SueldoQnalAsal
cuotaHora SueldoMensual
SueldoQnal
calcularSueldoQnalAsal()
establecerHoras() establecerSueldoMensual()
establecerCuota() obtenerSueldoQnalAsal()
calcularSueldoQnal()
obtenerSueldoQnal()
Diseño del algoritmo:
Algoritmo Calcular sueldo de varios empleados
Clase empleado
Declaraciones
Datos
# nombreEmpleado : cadena
# deptoEmple : cadena
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 67
# puestoTrabajo: cadena
Método establecerNombre(nom : cadena)
nombreEmpleado = nom
Fin método establecerNombre
Método establecerDepto(dep: cadena)
depatoEmple = dep
Fin de método establecerDepto
Método establecerPuesto(pues : cadena)
puestoTrabajo = pue
fin método establecerPuesto
Metodo obtenerNombre() : cadena
Return nombreEmpleado
Fin método obtenerNombre
Método obtenerPuesto() : cadena
Return puestoTrabajo
Fin método obtenerPuesto
Método obtenerDpto() : cadena
Return deptoEmple
Fin método obtenerDpto
Fin clase empleado
Clase EmpleadoPor Hora
Declaraciones
Datos
horasTrabajadas : Entero
cuotaHora : Real
SueldoQnal : Real
Metodo establecerHoras(horasT : Entero)
horasTrabajadas = horasT
Fin método establecerHoras
Metodo establecerCuota(cuotaH : Real)
cuotaHora = cuotaH
Fin método establecerCuota
Metodo calcularSueldoQnal()
SueldoQnal = horasTrabajadas * cuotaHora
Fin método CalcularSueldoQnal
Metodo obtenerSueldoQnal() : Real
Return sueldoQnal
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 68
Fin método obtenerSueldoQnal
Fin Clase EmpleadoPorHoras
Clase EmpleadoAsalariado
Declaraciones
Datos
SueldoQnalAsal : Real
SueldoMensual : Real
Método calcularrSueldoQnalAsal()
SueldoQnalAsal = SueldoMensual/2
Fin método calcularSueldoQnalAsal
Método establecerSueldoMensual(sdo : Real)
SueldoMensual = sdo
Fin método establecersueldoMensual
Metodo obtenerSueldoQnalAsal() : Real
Return SueldoQnalAsal
Fin método obtenerSueldoQnalAsal
Fin clase EmpleadoAsalariado
Clase EjecutaEmpleado
Metodo principal
Declaraciones
Variables
nomEmple, depto, puesto : cadena
hrsTra,TipoEmp : Entero
cuoH, SdoMen : Real
desea : carácter
Do
Imprimir menú y solicitar tipo de empleado
Tipos de empleados
1.- Empleado por Horas
2.- Empleado asalariado
Teclee tipo
Leer tipoEmp
Solicitar Nombre, departamento y puesto
Leer nomEmple, depto, puesto
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 69
If tipoEmple = 1 then
Crear objeto
EmpleadoPorHora objEmpleado = new empleadoPorHora()
Solicitar número de horas trabajadas y cuota por hora
Leer hrsTra, cuoH
Establecer
objEmpleado. establecerNombre(nomEmple)
[Link](depto)
[Link](puesto)
objEmpleado. establecerHoras(hrsTra)
[Link](cuoH)
Calcular
objEmpleado. calcularSueldoQnal()
Visualizar
objEmpleado. obtenerNombre()
[Link]()
[Link]()
objEmpleado. obtenerSueldoQnal()
Else
Crear objeto
EmpleadoAsalariado objEmpleado = new EmpleadoAsalariado()
Solicitar sueldo mensual
Leer SdoMen
Establecer
objEmpleado. establecerNombre(nomEmple)
[Link](depto)
[Link](puesto)
objEmpleado. establecerSueldoMensual(SdoMen)
Calcular
objEmpleado. calcularSueldoQnalAsal()
Visualizar
objEmpleado. obtenerNombre()
[Link]()
[Link]()
objEmpleado. obtenerSueldoQnalAsal()
Endif
Preguntar “¿Desea procesar otro empleado (S/N)? ”
Leer Desea
WHILE Desea = “S”
Fin metodo principal
Fin clase EjecutaEmpleado
Diseño de algoritmo OO usando polimorfismo
Ejemplo:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 70
El mismo ejercicio anterior, pero utilizando el concepto de polimorfismo
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 71
Empleado2
# nombreEmpleado
# deptoEmple
EjecutaEmpleado2
# puestoTrabajo
# SueldoQna
establecerNombre()
establecerDepto()
establecerPuesto()
calcularSueldoQna() **
obtenerNombre()
obtenerPuesto()
obtenerDpto()
obtenerSueldoQna()
EmpleadoPorHora2 EmpleadoAsalariado2
horasTrab SueldoMensual
cuotaHora
calcularSueldoQnalAsal()
establecerHoras()
establecerSueldoMensual()
establecerCuota()
calcularSueldoQnal()
Diseño del algoritmo
Algoritmo CALCULAR SUELDO DE VARIOS EMPLEADOS
Clase abstracta Empleado2
Declaraciones
Datos
# nombreEmpleado: Cadena
# deptoEmple : Cadena
# puestoTrabajo : Cadena
# SueldoQna: Real
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 72
Metodo establecerNombre(nom: Cadena)
nombreEmpleado = nom
Fin método establecerNombre
Método establecerDepto(dep: cadena)
deptoEmple = dep
Fin de método establecerDepto
Método establecerPuesto(pues : cadena)
puestoTrabajo = pue
fin método establecerPuesto
Metodo abstracto calcularSueldoQna()
Metodo obtenerNombre() : cadena
Return nombreEmpleado
Fin método obtenerNombre
Método obtenerPuesto() : cadena
Return puestoTrabajo
Fin método obtenerPuesto
Método obtenerDpto() : cadena
Return deptoEmple
Fin método obtenerDpto
Método obtenerSueldoQna() : Real
Return SueldoQna
Fin método obtenerDpto
Fin clase Empleado2
Clase EmpleadoPor Hora2 hereda de Empleado2
Declaraciones
Datos
horasTra : Entero
cuotaHora : Real
Metodo establecerHoras(horasT : Entero)
horasTrab = horasT
Fin método establecerHoras
Metodo establecerCuota(cuotaH : Real)
cuotaHora = cuotaH
Fin método establecerCuota
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 73
Metodo calcularSueldoQna()
SueldoQnal = horasTrabajadas * cuotaHora
Fin método CalcularSueldoQna
Fin Clase EmpleadoPorHora2
Clase EmpleadoAsalariado2
Declaraciones
Datos
SueldoMensual : Real
Método calcularrSueldoQnalAsal()
SueldoQnalAsal = SueldoMensual/2
Fin método calcularSueldoQnalAsal
Metodo obtenerSueldoQnalAsal() : Real
Return SueldoQnalAsal
Fin método obtenerSueldoQnalAsal
Fin clase EmpleadoAsalariado2
Clase EjecutaEmpleado2
Metodo principal
Declaraciones
Variables
nomEmple, depto, puesto : cadena
hrsTra,TipoEmp : Entero
cuoH, SdoMen : Real
desea : carácter
Do
Imprimir menú y solicitar tipo de empleado
Tipos de empleados
1.- Empleado por Horas
2.- Empleado asalariado
Teclee tipo
Leer tipoEmp
Solicitar Nombre, departamento y puesto
Leer nomEmple, depto, puesto
If tipoEmple = 1 then
Crear objeto
EmpleadoPorHora2 objEmpleado = new empleadoPorHora2()
Solicitar número de horas trabajadas y cuota por hora
Leer hrsTra, cuoH
Establecer
objEmpleado. establecerNombre(nomEmple)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 74
[Link](depto)
[Link](puesto)
objEmpleado. establecerHoras(hrsTra)
[Link](cuoH)
Calcular
objEmpleado. calcularSueldoQnal()
Visualizar
objEmpleado. obtenerNombre()
[Link]()
[Link]()
objEmpleado. obtenerSueldoQnal()
Else
Crear objeto
EmpleadoAsalariado2 objEmpleado = new EmpleadoAsalariado2()
Solicitar sueldo mensual
Leer SdoMen
Establecer
objEmpleado. establecerNombre(nomEmple)
[Link](depto)
[Link](puesto)
objEmpleado. establecerSueldoMensual(SdoMen)
Calcular
objEmpleado. calcularSueldoQnalAsal()
Visualizar
objEmpleado. obtenerNombre()
[Link]()
[Link]()
objEmpleado. obtenerSueldoQnalAsal()
Endif
Preguntar “¿Desea procesar otro empleado (S/N)? ”
Leer Desea
WHILE Desea = “S”
Fin método principal
Fin clase EjecutaEmpleado2
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 75
Resumen de la II Unidad
Sistemas de información
El analista en su desempeño realiza diferentes tipos de sistemas de
información, todo con el objetivo de satisfacer las demandas y/o necesidades
de cada nivel de una institución o empresa en la cual realiza su trabajo.
Entre los principales sistemas de información tenemos:
Sistemas de carácter transaccional
Sistemas de información general
Sistemas de soporte de decisiones
Sistemas estratégicos
Sistemas expertos
INTRODUCCION AL ANALISIS Y DISEÑO DE SISTEMAS
Conceptos de Análisis y Diseño Estructurado.
El diseño de arriba –abajo proporciona este método para descomponer un
problema dado en sus unidades componentes o módulos. Este diseño recibe
otros nombres tales como diseño estructurado, diseño compuesto, etc. Todas
estas metodologías describen la descomposición del problema en sus
funciones más importantes, la subdivisión de esas funciones en
subdivisiones y así sucesivamente
Reglas muy importantes
1.- Cada modulo debe ser independiente de los demás módulos.
2.- La responsabilidad operacional de cada modulo debe ser definida
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 76
concisamente.
3.- Cada modulo debe ofrecer solo un punto de entrada.
Análisis y Diseño Orientado a Objeto (ADOO)
El análisis orientado a objetos se basa en la solución del problema a partir de
objetos, es decir que la implementación del software será a partir de
comportamiento específicos de los objetos. Además los objetos tienen
procesos dinámicos en el análisis, estos pueden generar nuevos objetos,
crear nuevas relaciones entre los objetos, ser destruidos.
Es como analizar una estructura compleja, que se va armando por partes, sub
partes, sub sub partes, etc.
Capas del Análisis orientado a Objetos (AOO):
Capa de clases y objetos
Capa de estructura
Capa de atributos
Capa de servicios
Capa de tema
Metodologías de Análisis y Diseño Orientados a Objetos
El objetivo fundamental de un análisis del problema orientado a objeto (AOO)
es la definición de todas las clases que son relevantes para el mismo, sus
atributos y operaciones, las relaciones y demás elementos que determinan el
ámbito del problema…
Relaciones de Clases
Cuando modelamos objetos, las clases al igual que los objetos tienen
diferentes formas de relacionarse entre ellas, con el propósito de lograr los
objetivos propuestos de la aplicación de estudio.
Booch define las relaciones de clases de la siguiente forma:
Generalización/Especialización (es un)
Agregación (Todo-parte/Tiene un)
Asociación
Uso
Instanciación (Plantilla)
Metaclase
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 77
UML (Unified Modeling Lenguaje )
UML es lo más representativo de los métodos de análisis y diseño orientados
a objetos que aparecieron a finales de los ochenta y primeros años de los
noventa, expertos tales como Coad/Yourdon, Shlaer y Mellor, Booch, OMT,
Jacobson. Han realizado grandes aportes al análisis del modelado de datos.
Fichas o tarjetas CRC (clase, responsabilidad, colaborador)
El uso de fichas para representar las clases individuales es una técnica, de las
muchas que existen, que se utiliza para asignar responsabilidades a cada acción,
esta fichas se conocen como Tarjetas CRC (Beck 89) , una tarjeta CRC esta
dividida en tres partes
Clase: los nombres de las clases se crea el vocabulario con el que se formulara el
diseño.
Responsabilidades: Estas describen el problema que se va a resolver, deben
describir que se debe hacer y evitar los detalles de cómo se deben hacer.
Colaboradores: todos los objetos guardan relación con otro objeto del sistema.
Otro método de AOO: Clases y su relación con los objetos.
Diseño del programa.
Para diseñar un programa, se elabora o diseña el algoritmo que soluciona el
problema de tres partes:
Primero se diseña el diagrama de clases
Segundo se diseña la lógica de las clases en pseudocódigo
Tercero se realiza la prueba de escritorio.
Cuando realice el análisis del problema se buscan los verbos. Por lo general estos
son métodos u operaciones de la clase, por ejemplo:
LeerLosDatos()
ImprimirSalario()
VerificarId()
CalcularSalario()
EncontrarIva()
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 78
Para establecer los valores de cada uno de los datos de un objeto, se debe definir
un método del objeto (Clase) que permita colocar (setter) el valor a cada dato, ya
sea que lo lea o que lo calcule
De igual forma para dar salida al valor de un dato se requiere un método de acceder
(getter) al valor del dato para darlo como salida, uno para cada uno
Las clases definidas se utilizan para generar instancias u ocurrencias, estas
instancias son los objetos, que se utilizaran en el funcionamiento del programa,
esto significa que podemos ver la clase como un molde o plantilla o un tipo de dato,
que se utiliza para generar objetos específicos.
Un programa orientado a objeto que utilice la arquitectura modelo-vista-controlador
Está formado por tres partes muy importantes.
El modelo Es la clase o conjunto de clases identificadas en el dominio del problema,
esta clase (o clases) representan al objeto u objetos presentes en el problema
La Vista o interface gráfica o visualización.- Es la que el usuario observara en la
pantalla, impresora u otro dispositivo de salida de la computadora al operar el
programa
El controlador.- Es la parte que permite que el usuario interactúe con la interface
para utilizar el modelo que representa y soluciona el problema planteado, puede ser
otra clase o varias
Ejercicios de la II unidad.
Problemas para visualizar clases:
Dados los siguientes ejercicios encuentre:
a.- Definiciones de clases, utilizando la metodología CRC.
b.- Realice un diagrama de Generalización / Especialización si es necesario.
c.- Realice un diagrama de Agregación si es necesario
d.- Realice un diagrama de asociación de las clases encontradas.
Dados los siguientes ejercicios aplicar la arquitectura modelo-vista-
controlador para presentar la solución orientada a objeto:
1. Escribir un programa que visualice una tabla de los N primeros números, siendo
N un número que ingresa el usuario. Utilizar el siguiente diseño de salida
suponiendo que el usuario ingresó un tres:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 79
NÚMERO CUADRADO CUBO
1 1 1
2 4 8
3 9 27
2. Escribir un programa que permita registrar de los empleados de una fábrica (no
se sabe cuántos) su peso y saber cuántos pesan hasta 80 kg. inclusive y cuantos
pesan más de 80 kg.
3. En una tienda de artículos para caballeros al final del día se carga en la
computadora las boletas que confeccionaron los distintos vendedores para
saber cuanto fue la comisión del día de cada uno de ellos. Los datos que se
ingresan (por boleta) son: el número de vendedor y el importe. Cuando no hay
más boletas para cargar se ingresa 0. Teniendo en cuenta que el negocio tiene
3 vendedores y que el porcentaje sobre las ventas es del 5%, indicar cuánto
ganó cada vendedor en el día
4. Ingresar por teclado 3 números correspondientes a los lados de un triángulo.
Teniendo en cuenta que la suma de los dos lados menores tiene que ser superior
al lado mayor para que formen un triángulo, indicar si los números indicados
forman un triángulo y si lo forman que tipo de triángulo es (según sus lados).
5. Dados 3 números donde el primero y el último son límites de un intervalo, indicar
si el tercero pertenece a dicho intervalo
6. Por teclado se ingresa el valor hora de un empleado. Posteriormente se ingresa
el nombre del empleado, la antigüedad y la cantidad de horas trabajadas en el
mes. Se pide calcular el importe a cobrar teniendo en cuenta que al total que
resulta de multiplicar el valor hora por la cantidad de horas trabajadas, hay que
sumarle la cantidad de años trabajados multiplicados por $30, y al total de todas
esas operaciones restarle el 13% en concepto de descuentos. Imprimir el recibo
correspondiente con el nombre, la antigüedad, el valor hora, el total a cobrar en
bruto, el total de descuentos y el valor neto a cobrar.
7. Realizar la tabla de multiplicar de un número entre 0 y 10 de forma que se
visualice de la siguiente forma:
4x1= 4
4x2= 8
..........
8.- El Trabajo consiste en calcular calificaciones de los estudiantes del curso por
medio de dos formulas, la entrada del nombre del estudiante, código, código de la
clase y las calificaciones de cuatro exámenes, la ultima corresponde al examen final.
El profesor quiere utilizar dos formulas diferencias para calificar a los estudiantes,
ya que ellos provienen de dos diferente cursos, si el código de la clase es 1, el
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 80
examen final es el 40 % de la calificación y los otros tres exámenes el 60 %, si el
código de la clase es 2, todas las calificaciones son sumadas y divididas entre 4
para obtener una calificación promedio.
En la clase 1 si la calificación del alumno es mayor de 70, el estudiante obtiene
“APROBADO”, en caso contrario “REPROBADO”, en la clase 2 la calificación final
es el promedio de las cuatro.
9.- El problema es calcular las cuotas del sindicato, las entradas al problema
son: El nombre del empleado, puesto, salario por hora y código del sindicato. Solo
existen dos códigos del sindicato, 1 o 2 , Si el código es 1, la cuota del sindicato es
el 15 % del salario por hora mas C$ 2.00.
Por otro parte se necesita saber el total de aportaciones de los trabajadores con el
código 1. Los de categoría 2 esta divididos en dos tipo y cada uno debe ser tratado
en forma diferente, si el sueldo por hora es mayor de C$ 5.00, la cuota del sindicato
es del 40 % del salario mas C$3.50, si es menos se le cobra el 25 % del salario
más C$ 1.00.
También se debe saber el total de aportaciones de los trabajadores con código 2.,
imprimir los datos de los empleados con sus respectivas aportaciones.
10.-Se desea calcular el salario de los empleados, los datos de entrada del
problema son el nombre del empleado, las horas trabajadas, el pago por hora y las
deducciones de la semana, el salario bruto se calcula utilizando la siguiente formula
Sueldo bruto = horas * pago por hora ; Salario neto = Sueldo bruto – deducciones,
imprimir los detalles de los empleados y los totales correspondiente de salarios y
deducciones.
11.- Una empresa distribuidora de artículos de diversión desea crear tarjetas
que almacenen el nombre del artículo y el código del mismo. A partir de de esa clase
(llamada producto) derive dos clases que nombraremos discos de música y libros,
la clase disco de música tendrá el dato de duración de minutos, el precio y el
cantante, la clase libro, tendrá la información numero de paginas, precio, fecha de
publicación, cada una de las tres clases tendrá la función leer() y mostrar() ,para
visualizar datos.
12.- Una persona desea saber en qué día del mes realizó más gastos en
compras, para ello ingresa por teclado día a día lo que gastó por día, cargando un
vector definido en memoria. Puede haber varias o ninguna compra para un
determinado día. Informar cual fue el día de mayor gasto.
13.- Leer dos listas A y B de dimensión 10. Generar una tercera lista C de 100
elementos donde la componente C[ i ] sea igual al mínimo valor de A[ i ] y B[ i ].
Mostrar los tres vectores
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 81
14.- Leer 20 números enteros positivos. Mostrar la lista tal como fue ingresado y
luego mostrarla ordenada en forma decreciente.
15.- De los 100 empleados de una fábrica se registra: número de legajo (coincide
con el número de índice), edad y salario. Se pide:
Ingresar los datos correlativamente
Calcular la edad promedio informando número de legajo de los empleados cuya
edad supere el promedio
16.- Mismo enunciado al ejercicio anterior. Se pide:
Ingresar los datos en forma aleatoria. (se pide ingreso de número de legajo de 1 a
100, se posiciona en el elemento correspondiente y se ingresa edad y salario)
Calcular salario promedio informando número de legajo de aquellos cuyo salario
supere el promedio
17.- Se tiene un grupo de alumnos , los datos por cada alumno son:
Nombre, Sexo(M,F), Edad,, Estatura, Peso, Color de los ojos, (1 = azul, 2= café, 3=
otro ), Color del cabello (1 = castaño, 2=negro, 3 = otro)
Elaborar un programa que lea los datos de entrada y que proporcione
a) Un listado de las mujeres de cabello negro y ojos azules, que midan entre
1.65 m y 1.75 my que pesen menos de 55 kg.
b) Un listado de los hombres de ojos cafés de mas 1.70 m de estatura y que
pesen entre 60 y 70 kg.
18.- Elaborar un programa que lea los datos de varios estudiantes: Nombre y tres
calificaciones parciales, visualizar los siguientes datos:
Reporte de Calificaciones
Nombre Calif Final
X ----------------------------X 999.99
X-----------------------------X 999.99
X------------------------------X 999.99
Total Alumnos : 999
Para aprobar el curso, debe tener 70 o mas de promedio , en caso de haber
reprobado la calificación será NA (No Acreditado)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 82
19.- Elaborar un programa que contabilice una cuenta de cheques, al inicio se
le introduce el nombre del cuentahabiente y el saldo inicial. A continuación se puede
hacer depósitos y retiros. Cuando sea depósito se incrementa al saldo, y cuando
sea retiro se resta. Este programa terminara cuando ya no se desee hacer
movimientos entonces se requiere la visualización siguiente:
Estado de cuenta
Nombre Cuentahabiente: X------------------------------X
Saldo inicial: 99,999,999.99
Movimiento Deposito Retiro Saldo
------------------- ---------------- --------------- --------------
1 999,999.99 999,999.99
2 999,999.99 999,999.99
3 999,999.99 999,999.99
4 999,999.99 999,999.99
..
TOTALES 9,999,999.99 9,999,999.99 9,999,999.99
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 83
LENGUAJE VISUAL BASIC NET
Indice:
1.- Elementos básicos de Visual Basic NET pagina 5
1.1.-Introduccion a Visual Basic NET
1.2.- Plataforma .NET
1.3.- Entorno de ejecución CLR
1.4.- El Lenguaje Intermedio y el CLS
1.5.- La biblioteca de clases de .NET
1.6.-Los espacios de nombres
1.7.- Acceso a datos con [Link]
1.8.- Aplicaciones Windows Forms
2.- Elementos del Lenguaje Visual Basic pagina 11
2.1.- Variables Visual Basic NET
2.2.- Constantes en Visual Basic NET
2.3.- Listas enumeradas
2.4.- Estructuras
2.5.- Ambito de variables
2.6.- Operadores aritméticos
2.7.- Jerarquía de las operaciones
2.8.- Orden de las operaciones
2.9.- Comentarios en Visual Basic NET
3.- Programas, formas y componentes de Visual Basic NET pagina 20
3.1.- Programa ejemplo de Visual Basic NET
3.2.- Otros componentes
3.3.- Dos o más forms en Visual Basic NET
4.- Estructuras, ciclos, decisiones en visual Basic NET pagina 30
4.1.-Instrucciones condicionales en Visual Basic
4.2.- Operadores relacionales en Visual Basic
4.3.- Instrucciones If… Then Else en Visual Basic
4.4.- Condiciones compuestas en Visual Basic
4.5.- Instrucciones de control
4.6.- Ciclos For… To Next
4.7.- Ciclo Do… Loop While
4.8.- Arreglos en Visual Basic
4.9.- Funciones del lenguaje integradas
4.10.- Procedimientos o sub rutinas en Visual Basic
5.- Programando con controles en Visual Basic pagina 68
5.1- El cuadro de herramienta
5.2.-Controles Window Basicos
5.2.1.- Control formulario
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 84
5.2.2.- Control Label
5.2.3.- Control TextBox
5.2.4. -Control Button
5.2.5.- Control ListBox
5.2.6.- Control Combobox
5.2.7.- Control CheckBox
5.2.8.- Control CheckedListBox
5.2.9.- Controles RadioButton
5.2.10.- Control GroupBox
5.2.11.- Control VScrollBar, HScrollBar. TrackBar
5.2.12.- Controles tipo menú
5.3.- Foco de entrada
5.4.- Codificando con los eventos de controles
5.5.- Codificando otros eventos de control
5.6.- Orden de tabulación de los controles
5.7.- Funciones para presentar mensajes
5.7.1.- Funcion InputBox()
5.7.2- Funcion MsgBox()
5.8.- Controles avanzados de Visual Basic
5.8.1- Control temporizadores (Timer)
5.8.2- Control ImageList
5.8.3-Control ToolBar
5.8.4- Control StatusBar
5.8.5 Control DateTimePiker
5.8.6- Control NumericUpDown
5.8.7- Control DomainUpDown
5.8.8- Control MonthCalender
5.8.9- Control LinkLabel
5.8.10- Control NotifyIcon
5.8.11- Controles de Dialogos
5.8.12- Control FontDialog
5.8.13- Control ColorDialog
5.9.- Interfaces
5.10.- Creando programas MDI
5.11.-Control de excepciones
5.11.1- Tipos de errores
5.11.2.- Formas de control de excepciones
[Link]- Control no estructurado
[Link]- Control estructurado
6.- Programacion Orientada a Objeto (POO) en Visual Basic pagina 170
6.1.- Que es una clase
6.2.- Crear la primea clase
6.3.- Propiedades de solo lectura y escritura
6.4.- Agregar métodos a una clase
6.5.- Agregar evento a una clase
6.6.- Crear una instancia de clase
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 85
6.7.- Como utilizar los constructores
6.8.- Como utilizar los destructores
6.9.- Como utilizar los miembros datos compartidos
6.10.- Como utilizar los métodos compartidos
6.11.- Polimorfismo en Visual Basic NET
6.12.- Probar controladores de eventos
6.13.- Herencia de clases en Visual Basic NET
7.- Impresión en Visual Basic pagina 210
7.1.- La solucion: Como imprimir en .NET
7.2.- Las clases para imprimir en .NET
Clase PrintDocument
Clase PrintSetting
Clase PrintDialog
Clase PrintPreviewDialog
Clase PrintPreviewControl
7.4.- Conclusion para imprimir en VB net
7.5.-Hacer Crystal Report con DataSet en Visual [Link]
7.6.- Reportes en visual [Link] con Crystal Report
7.7.- Como crear un reporte (ReportViewer)
7.8.- Reportes con datos agrupados (Reporting Service)
7.9.- Dar formato a un reporte (Reporting Service)
8.- Formularios de interfaz múltiple (MDI) página 258
8.1.- Aplicaciones estilo SDI
8.2.- Aplicaciones estilo MD
8.3.- Creación de menú de tipo ventana en formularios MDI
8.4.- Bloqueo de opciones de menús en formularios MDI
8.5.- Recorrer formularios hijos de un MDI
8.6.- Comportamiento no modal
8.7.- Modal de un formulario
8.8.- Controles de cuadro de diálogos de sistema
8.9.- Formularios dependientes
8.10.- Validación de controles.
9.-Streams en .NET página 289
Las clases basadas en stream
Manejar unfichero usando FileStream
Manejar un fichero usando StreamReader y StreamWriter
10.- Colecciones de datos pagina 332
Tipos de colecciones
Tipos de datos de almaceniamiento de las colecciones
Clases bases para crear colecciones personalizadas
11.- GDI+ Sistema gráfico de Windows pagina 342
[Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 86
12.- Operaciones de entrada y salida (I/O). pagina 368
[Link]
Objetos Stream
Clases TextReader y TextWriter
Manejo de datos binarios
13.- Ensamblados en Visual Basic Pagina 391
14 .-Crear un proyecto de instalación (Setup) Pagina 397
Adendum
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 87
1.- ELEMENTOS BASICOS DE VISUAL BASIC NET
1.1.- Introducción a Visual Basic NET
Información y Conocimiento son los dos elementos claves del nuevo milenio ninguna
sociedad podrá alcanzar ni puede ignorar este nuevo esquema ya las naciones no se miden
por su riqueza industrial, ni sus activos físicos, ni por su poder militar, sino por la cantidad
de información que produce y consume, así como por la recombinación de información nueva
en un conocimiento de grado superior.
Nuevos sistemas de información, tienden a ser cada vez de mayor alcance y complejidad
sobre todo cuando se toman en cuenta las nuevas necesidades de información y conocimiento
que demandan las nuevas organizaciones.
VISUAL BASIC NET es un lenguaje de programacion desarrollado por Microsoft muy
apropiado para construir sistemas de informacion basados en red o mejor aun en internet.
1.2.- Plataforma .NET
Es un amplio conjunto de bibliotecas o librerías de desarrollo que pueden ser utilizadas por
otras aplicaciones para acelerar enormemente el desarrollo y obtener de manera automática
características avanzadas de seguridad, rendimiento, etc... .NET permite compilar, depurar,y
ejecutar aplicaciones .NET.
Desde que apareció la primera versión de [Link] Framework 1.0 en Visual Studio
2002, hasta la última versión del 2010 se vienen realizando mejoras continuas que permiten
realizar una mejor integración de todos los componentes en aplicaciones mas robustas y
completas del mercado para la tecnología de desarrollo de Microsoft.
[Link] Framework es una apliacion que se iintegra en el entorno de desarrollo de forma
fácil y transparente al programador, el cualse utiliza para ayudarnos a desarrollar de forma
rápida, correcta, segura y en el menor tiempo posible nuestras aplicaciones.
1.3.- Entorno de ejecución CLR
.NET ofrece un entorno de ejecución para sus aplicaciones conocido como Common Language
Runtime o CLR. La CLR es la implementación de Microsoft de un estándar llamado Common
Language Infrastructure o CLI. Éste fue creado y promovido por la propia Microsoft pero
desde hace años es un estándar reconocido mundialmente por el ECMA.
El CLR/CLI esencialmente define un entorno de ejecución virtual independiente en el que
trabajan las aplicaciones escritas con cualquier lenguaje .NET. Este entorno virtual se ocupa
de multitud de cosas importantes para una aplicación: desde la gestión de la memoria y la vida
de los objetos hasta la seguridad y la gestión de subprocesos.
1.4.- El Lenguaje Intermedio y el CLS
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 88
Al contrario que otros entornos, la plataforma .NET no está atada a un determinado lenguaje
de programación ni favorece a uno determinado frente a otros. En la actualidad existen
implementaciones para varias decenas de lenguajes que permiten escribir aplicaciones para la
plataforma .NET. Los más conocidos son Visual Basic .NET, C# o J#, pero existen
implementaciones de todo tipo, incluso de ¡COBOL!.
Lo mejor de todo es que cualquier componente creado con uno de estos lenguajes puede ser
utilizado de forma transparente desde cualquier otro lenguaje .NET. Además, como ya se
ha comentado, es posible ejecutar el código .NET en diferentes plataformas y sistemas
operativos
1.5.- La biblioteca de clases de .NET
Todo lo que se ha estado comentando hasta ahora en el curso constituye la base de la
plataforma .NET. Si bien es muy interesante y fundamental, por sí mismo no nos serviría de
mucho para crear programas si debiésemos crear toda la funcionalidad desde cero.
Obviamente esto no es así, y la plataforma .NET nos ofrece infinidad de funcionalidades "de
fábrica" que se utilizan como punto de partida para crear las aplicaciones. Existen
funcionalidades básicas (por ejemplo todo lo relacionado con la E/S de datos o la seguridad)
y funcionalidades avanzadas en las que se fundamentan categorías enteras de aplicaciones
(acceso a datos, creación de aplicaciones Web...).
Toda esta funcionalidad está implementada en forma de bibliotecas de funciones que
físicamente se encuentran en diversas DLL (bibliotecas de enlazado dinámico).
A su conjunto se le denomina Base Classes Library (Biblioteca de clases base o BCL) y
forman parte integral de la plataforma .NET, es decir, no se trata de añadidos que se deban
obtener o adquirir aparte.
La siguiente figura ilustra a vista de pájaro la arquitectura conceptual de la plataforma .NET.
En ella se pueden observar los elementos que se han mencionado en apartados anteriores
(lenguajes, CLR, CLS...) y en qué lugar de se ubican las bibliotecas de clases base:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 89
Todo lo que se encuentra en la BCL forma parte de la plataforma .NET. De hecho existe tal
cantidad de funcionalidad integrada dentro de estas bibliotecas (hay decenas de miles de
clases) que el mayor esfuerzo que todo programador que se inicia en .NET debe hacer es el
aprendizaje de las más importantes. De todos modos Visual Studio ofrece mucha ayuda
contextual (documentación, Intellisense...) y una vez que se aprenden los rudimentos resulta
fácil ir avanzando en el conocimiento de la BCL a medida que lo vamos necesitando.
1.6.- Los espacios de nombres
Dada la ingente cantidad de clases que existen debe existir algún modo de organizarlas de un
modo coherente. Además hay que tener en cuenta que podemos adquirir más funcionalidades
(que se traducen en clases) a otros fabricantes, por no mencionar que crearemos
continuamente nuevas clases propias. Para solucionar este problema existen en todos los
lenguajes .NET los espacios de nombres o namespaces. Un espacio de nombres no es más
que un identificador que permite organizar de modo claro las clases que estén contenidas en
él así como otros espacios de nombres.
Así, por ejemplo, todo lo que tiene que ver con el manejo de estructuras de datos XML en la
plataforma .NET se encuentra bajo el espacio de nombres [Link]. La funcionalidad
fundamental para crear aplicaciones Web está en el espacio de nombres [Link]. Éste a
su vez contiene otros espacios de nombres más
1.7.- Acceso a datos con [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 90
El acceso a fuentes de datos es algo indispensable en cualquier lenguaje o lataforma de
desarrollo. La parte de la BCL que se especializa en el acceso a datos se denomina de forma
genérica como [Link].
Si usted ha programado con Visual Basic 6.0 o con ASP, ha empleado en su código con total
seguridad la interfaz de acceso a datos conocida como ADO (ActiveX Data Objects), puede
que combinado con ODBC (Open Database Connectivity). Si además es usted de los
programadores con solera y lleva unos cuantos años en esto es probable que haya usado RDO
o incluso DAO, todos ellos métodos mucho más antiguos.
[Link] ofrece una funcionalidad completamente nueva, que tiene poco que ver con lo
existente hasta la fecha en el mercado. Sin embargo, con el ánimo de retirar barreras a su
aprendizaje, Microsoft denominó a su nuevo modelo de acceso a datos con un nombre similar
y algunas de sus clases recuerdan a objetos de propósito análogo en el vetusto ADO.
[Link] es un modelo de acceso mucho más orientado al trabajo desconectado de las
fuentes de datos de lo que nunca fue ADO. Si bien este último ofrecía la posibilidad de
desconectar los Recordsets y ofrecía una forma de serialización de estos a través de las
diferentes capas de una aplicación, el mecanismo no es ni de lejos tan potente como el que
nos ofrece [Link].
El objeto más importante a la hora de trabajar con el nuevo modelo de acceso a datos es el
DataSet. Sin exagerar demasiado podríamos calificarlo casi como un motor de datos
relacionales en memoria. Aunque hay quien lo asimila a los clásicos Recordsets su
funcionalidad va mucho más allá como se verá en el correspondiente módulo.
1.8.- Aplicaciones Windows Forms
Las aplicaciones de escritorio son aquellas basadas en ventanas y controles comunes de
Windows que se ejecutan en local. Son el mismo tipo de aplicaciones que antes construiríamos
con Visual Basic 6 u otros entornos similares.
En la plataforma .NET el espacio de nombres que ofrece las clases necesarias para construir
aplicaciones de escritorio bajo Windows se denomina Windows Forms. Este es también el
nombre genérico que se le otorga ahora a este tipo de programas basados en ventanas.
Windows Forms está constituido por multitud de clases especializadas que ofrecen
funcionalidades para el trabajo con ventanas, botones, rejillas, campos de texto y todo este
tipo de controles habituales en las aplicaciones de escritorio. Visual Studio ofrece todo lo
necesario para crear visualmente este tipo de programas, de un modo similar aunque más
rico al que ofrecía el entorno de desarrollo integrado de Visual Basic.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 91
Diseñador de interfaces de aplicaciones de escritorio con Windows Forms en Visual Studio
Este es el aspecto que presenta parte del código que genera la interfaz mostrada en la
anterior figura:
2.- Elementos del Lenguaje Visual Basic
2.1.- VARIABLES VISUAL BASIC NET
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 92
Identificadores son conjuntos de letras y/o numeros que se utilizan para simbolizar todos los
elementos que en un programa, son definibles por el usuario (programador o ingeniero de
software) del mismo, como son las variables donde se almacenan datos, funciones (pequenos
modulos con codigo), etiquetas, clases, objetos, etc.
En VISUAL BASIC NET un identificador es una palabra compuesta de letras y/o numeros
de hasta 32 caracteres significativos, empezando siempre con una letra.
Una variable se define como un identificador que se utiliza para almacenar todos los datos
generados durante la ejecucion de un programa.
Existen ciertas reglas en cuanto a variables:
Claras y con referencia directa al problema.
No hay espacios en blanco, ni simbolos extraños en ellas.
Se pueden usar abreviaturas, pero solo de caracter general.
No usar palabras reservadas del lenguaje.
Ejemplos de buenas variables:
Nombre, Edad, SdoDiario, IngMensual, Perimetro, Calif1, etc.
2.1.1.- Declaracion y tipos de datos
En Visual Basic NET a toda variable que se use en un programa, se le debe asociar
(generalmente al principio del programa) un tipo de dato especifico.
Un tipo de dato define todo el posible rango de valores que una variable puede tomar al
momento de ejecucion del programa y a lo largo de toda la vida util del propio programa.
Los tipos de datos más comunes en Visual Basic NET son:
Tipo Rango
BYTE 0-255
INTEGER(%) +-2,147,483,698
SINGLE(!) 3.4E+-38(7 DECIMALES)
DOUBLE(#) 1.8E+308(16 DECIMALES)
CURRENCY 15 DIG IZQ 4 DIG DEECHA
STRING($) 2 BILLONES CHARS
BOOLEAN TRUE, FALSE
DATE FECHA
VARIANT TODOS LOS TIPOS y mas usado en este curso
Recordar Tambien que en Visual Basic NET toda variable usada en un programa se debera
declarar al principio del programa el formato de declaracion mas sencillo es:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 93
DIM VARIABLE AS TIPO
Ejemplos
DIM vVALOR AS INTEGER
DIM vVALOR AS LONG, BETA AS LONG
DIM vVALOR AS INTEGER, sNOMBRE AS STRING
DIM sCIUDAD AS STRING * 20, ALFA AS DOUBLE
Observar último caso de ciudad asi de esta manera se consigue una string de tamano definido.
En Visual Basic NET un problema comun a lo largo de este curso, es la necesidad de convertir
variables numericas a strings y tambien el problema inverso es decir convertir strings a su
representacion numerica.
Para este último problema por ejemplo se tiene:
DIM VPI AS STRING
VPI = “3.1416”
Como se observa del ejemplo anterior, se puede dar en algun momento la necesidad de
convertir la string VPI a su valor numerico, para resolver este problema se deberan usar las
siguientes funciones de conversion numerica que proporciona Visual Basic NET.
En Visual Basic NET se tendria:
DIM ALFA AS STRING
DIM BETA AS SINGLE Nota: Estamos usando una
ALFA = “3.1416” función de Visual Basic para
BETA= CINT (ALFA) tomar solo el valor entero de
ALFA
Tambien podemos declarar variables utilizando unos símbolos o caracteres detrás de las
variables que indiquen el tipo de variable utilizada, la tabla muestra estos símbolos:
Tipo de dato Simbolo Caracter
Short S
Integer % I
Long & L
Single ! F
Double # R
Decimal D
UShort US
UInteger UI
Ulong UL
String $
Tipos de datos Objetos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 94
Object es un tipo de datos de forma implicitay del cual heredan el resto de tipos de datos
2.2.- Constantes en Visual Basic NET
Formato:
Const variables As tipo = valor
Ejemplos
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Const vPI as double = 3.1416
Dim valor As decimal
Valor = (2 * vPI) ^2
[Link](Valor)
End sub
2.3.- Listas enumeradas
Son listas de variables o datos que hacen referencia a índices y estos empiezan desde 0 en
adelante. El formato que se utiliza es el siguiente:
Private Enum <Nombre_Variable> As <Tipo_Dato>
<Variable> = Valor_asignado
…
End Enum
Observemos el siguiente ejemplo:
Private Enum valores As Integer
Valor1 = 3
Valor2 = 5
Valor3 = 7
End Enum
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Dim valor As valores
Valor = valores.valor2
[Link](Valor)
End sub
Nota: Si deseamos conocer el nombre de la variable seleccionada de la lista enumerada,
podemos utilizar:
Dim valor As valores
Valor = valores.valor2
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 95
[Link]([Link]() & “: “ & Valor)
Se presentara: valor2: 5
2.4.- Estructuras en Visual Basic
Las estructuras están formadas por uno o mas miembros y cada miembro puede ser de un
tipo de datos determinado. El formato a utilizar es:
Structure <nombre>
Public <nombre> As <tipo>
End Structure
Ejemplo de uso de estructura:
Private Structure Alumno
Public nombre As String
Public Edad As Integer
Public Id As String
End Structure
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Dim MiAlumno As Alumno
[Link] = “Carlos “
[Link] = 23
[Link] = “2011-23056”
[Link]([Link] & “ tiene “ & [Link] & “ años”)
End sub
Se presentara en pantalla: Carlos tiene 23 años
Tambien podemos utilizar la palabra reservada With para realizar acciones que se repiten,
evitando escribir una parte del código, analicemos el siguiente ejemplo:
Private Structure Alumno
Public nombre As String
Public Edad As Integer
Public Id As String
End Structure
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 96
Dim MiAlumno As Alumno
With MiAlumno
.nombre = “Carlos “
.edad = 23
.Id = “2011-23056”
[Link]([Link] & “ tiene “ & [Link] & “ años”)
End sub
2.5.- Ambito de variables en Visual Basic
El lugar donde sea declarada una variable afectara el uso que el programa quiera hacer de
esa variable. Las reglas basicas que determinan como una variable puede ser usada
depende del lugar donde se puede declarar una variable. Veamos la siguiente tabla:
Declaración Lugar de Declaración Alcance o Ámbito
Public Módulo o Clase Global, en todo el proyecto.
Protected Clase En la clase declarada o en una derivada.
Friend Clase En el Assemblie.
Private Módulo Solo en el módulo.
Dim Procedimiento Solo en el Procedimiento.
Static Procedimiento Solo en el Procedimiento.
En escencia una variable local solo es conocida por el codigo de esa funcion o procedimiento
y es desconocida por otras funciones o procedimientos.
En la programacion formal no es acostumbrado usar muchas variables globales por varias
razones, una de ellas es que variables globales estan vivas todo el tiempo de ejecucion del
programa.
Si una variable global solo la ocupa unos cuantos procedimientos no tiene caso que este
viva para todo el resto, otra razon es que es peligroso tener variables globales porque todo
el conjunto de procedimiento y funciones que componen un programa tienen acceso o
comparten su valor y se corre el riesgo de que inadvertidamente alguno de ellos modifique
su valor.
Programa
' Creando y cargando una variable global
Dim varglobaluno as integer = 50 ‘Fuera de todo procedimiento
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 97
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
' creando, cargando y mandando una var local Este es un
Dim varlocaldos = 20 procedimiento
Call PROC1(varlocaldos) en Visual Basic
End Sub NET
Sub PROC1(ByVal varlocaltres As Single)
'aqui se puede usar varglobaluno por ser global
'y varlocaltres por ser local pero no se puede usar varlocaldos
' porque es local en otro procedimiento
[Link] = varglobaluno + varlocaltres
End Sub
2.6.-- Operadores aritmeticos
En Visual Basic NET un operador es un simbolo especial que indica al compilador que debe
efectuar una operacion matematica o logica.
Visual Basic reconoce los siguientes operadores aritmeticos:
OPERADOR OPERACIÓN
+ Suma
- Resta
* Multiplicacion
/ Division flotante
\ Division Entera
^ Potencia
MOD Modulo
El Operador (/) Division Flotante es el operador de division normal.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 98
El Operador (\) tambien es division pero los datos:
a) Primero son redondeados al entero más cercano (byte, integer, long)
b) Al final visual basic trunca la parte residual.
El Operador (^), resuelve dos problemas:
a) Ejemplo 5 2 se resuelve enVisual Basic NET:
dim alfa as integer 9
alfa = 5 ^ 2
Desplegar alfa, sale 9 en pantalla
b) Ejemplo para Raices solo recordar la ley de exponentes que dice:
Para estos casos:
= 5^8/3
= 9^1/2
En Visual Basic el operador (MOD) devuelve el residuo entero de una division entre enteros,
ejemplo:
Dim alfa As Single 3
alfa = 23 MOD 4
Visualizar alfa; El resultado en pantalla es 3
Otro ejemplo;
8
alfa = 108 MOD 10
Visualizar alfa; El resultado en pantalla es 8
Actividades de reforzamiento de lo aprendido
Ejercicios de programacion
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 99
Resolver algebraicamente en papel las siguientes ecuaciones expresándolas en formato de
Visual Basic NET
1.-
2.-
3.-
2.7.- Jerarquia de operaciones
En Visual Basic NET el problema de no tomar en cuenta la jerarquia de los operadores al
plantear y resolver una operacion casi siempre conduce a resultados muchas veces
equivocados como estos:
Ejemplos:
a) 2 + 3 * 4 = 20 (incorrecto)
2 + 3 * 4 = 14 (correcto)
b) si calif1 = 60 y calif2 = 80 ; Entonces si en programa se usa
promedio = calif1 + calif2/2 ; Da como resultado promedio = 100
En Visual Basic NET recordar siempre, que antes de plantear una formula en un programa
se debera evaluar respecto al orden siguiente:
2.8.- Orden de operaciones:
1.- Parentesis
Ordenes de
2.- Potencias y raices operacion
3.- Multiplicaciones y divisiones
4.- Sumas y restas
5.- Dos o más de la misma jerarquia u orden, entonces resolver de izquierda a derecha
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 100
Nota: Si se quiere alterar el orden normal de operaciones, entonces usar
parentesis.
Nota: Tampoco es bueno usar parentesis cuando no es necesario en una
operacion, esto solo indica que no se evaluo bien la formula
Ejemplo:
area = ( base * altura ) / 2
Aqui los parentesis estan de mas porque por orden de operaciones, multiplicacion y division
tienen la misma jerarquia y entonces se resuelven de izquierda a derecha en otras palabras
en visual basic NET ni que falten parentesis ni que sobren parentesis
2.9.- Comentarios en Visual Basic NET
Para agregar comentarios a nuestro código de programa podemos hacerlo de variasm
maneras:
1.- Utilizando el carácter ‘
area = base * altura / 2 ‘ Encontramos el área del cuadrado
2.- Utilizando la palabra reservada REM, se utiliza al comienzo de una línea:
Rem Encontramos el área del cuadrado
area = base * altura / 2
3.- Cuando queremos utilizar pequeñas porciones de regiones de comentarios y código que
se puede contraer y expandir, el formato a utilizar es:
#Region “ < texto >”
… Aquí se escribe lo que quermos poner como comentario en varia líneas
… Se puede escribir líneas de codigo
#End Region
Ejemplo:
#Region “ Problema 1”
‘El problema permite encontrar el Mayor de los números de una lista
‘Proporcionada por el usuario
Dim IValor As Integer = 0
#En Region
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 101
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 102
3.- PROGRAMAS, FORMAS y COMPONENTES VISUAL BASIC NET
Recordar que programas visuales, se construyen usando los siguientes elementos:
1.- Un objeto ventana o form1
2.- Objetos que permitan capturar y desplegar datos, de momento se usaran los dos
objetos de entrada / salida más comunes:
2.1 Objeto label Permite desplegar textos o mensajes estaticos
2.2 Objeto textbox Permite tanto capturar datos, asi como desplegar el resultado de
operaciones (recordar que textbox's) solo capturan o despliegan un dato a la vez, recordar
tambien que todos los datos que entren y salgan de un textbox o un label son de tipo string.
2.3.- Objetos InputBox() Para obtener datos directos y sencillos del usuario
2.4.- Objetos MessageBox() Para presentar informacion relevante al usuario
3.- Objeto Button Es el componente principal de la forma, contiene el código principal del
programa y su activación por el usuario provoca que se realicen los principales procesos del
problema planteado (aquí es donde se capturan datos, se realizan operaciones, etc.).
De este componente se maneja su propiedad Text para etiquetarlo con la palabra “OK” o
“ACEPTAR” o “EXE” y su evento Click para activarlo, es en dicho evento donde se
construirá muchas veces el código del programa.
Nota importante: Recordar que aunque no es un componente necesario en los
programas ya que el código se puede asociar o pegar a cualquier evento de
cualquier forma o componente del programa, Microsoft ya acostumbro a todos
los usuarios al boton OK, de acuerdo, OK.
RECORDAR que todos los componentes vistos incluyendo el propio form y ventana estos
tienen muchas propiedades que se pueden asignar o modificar y tambien tienen muchos
eventos a los cuales les podemos asociar o cargar el codigo del programa, todos estas
propiedades y eventos las podemos accesar dentro de la ventana de propiedades.
No olvidar que las palabras reservadas del lenguaje NO se deben utilizar como
variables, esto producirá un error en al aplicacion
Regresando a Form1, es sobre esta forma donde se construira el programa y esta forma se
convierte en ventana al momento de ejecutarse el programa.
Es decir sera la primera ventana que el usuario ve al momento de ejecutarse el programa, su
nombre es Form1.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 103
Esta forma o ventana es un objeto de VISUAL BASIC NET y como todos los
objetos de Visual Basic y del universo, la forma o ventana tiene asociados
propiedades y eventos.
Propiedades: Son todas las caracteristicas particulares que diferencian un objeto de otro
objeto, las propiedades o caracteristicas mas comunes son forma, tamano, color, etc., para
objetos en visual basic, estas propiedades se modifican o individualizan usando la PAGINA
DE PROPIEDADES, que es la parte del programa que las contiene.
Recordar que se pueden modificar las propiedades dentro de un programa, usando
instrucciones apropiadas, mismas que llevan el siguiente formato:
[Link] = nvovalor;
Ejemplo: [Link] = Yellow
Eventos: son todos aquellos sucesos de caracter externo que afectan o llaman la atencion
del objeto, para estos casos la forma o ventana u objeto:
1. Debe tener capacidad de detectar el evento
2. Aun más importante debe tener capacidad de reaccionar y emitir una respuesta,
mensaje o conducta apropiada al evento detectado.
Evento es por ejemplo que otro objeto llamado humano pulse el objeto tecla ESC, o haga
click derecho con el objeto raton en alguna parte de la ventana, etc. es en estos casos, cuando
la ventana u objeto detecte un evento de estos la propia forma u objeto debera responder de
manera apropiada.
Nota: Esta respuesta no es automatica, sino son la serie de instrucciones del lenguaje
(o programa) que los ingenieros de software diseñan (o programan) en otras palabras
son los eventos quienes contendran los programas.
Es tambien la VENTANA DE PROPIEDADES, quien contiene todos los posibles eventos
asociados a la forma.
Para los primeros programas en VISUAL BASIC solo se usaran propiedades sencillas como
color, font, etc. de Form1 y los objetos ya mencionados (LABEL, TEXTBOX, BUTTON,
INPUTBOX, MESSAGEBOX, LISTBOX, COMBOBOX) y no se usan de momento los
eventos que puede detectar Form1.
3.1.- Programa ejemplo Visual Basic NET
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 104
Resolvemos el problema de calcular el área de un triangulo con la formula área = base *
altura /2
Para resolver este problema se ocuparan los siguientes objetos. (para realizar el disño)
1.- Una ventana de windows (form1) para contener a todo el resto de componentes.
2.- Tres label's o etiquetas para desplegar mensajes apropiados al problema.
3.- Tres componentes TEXTBOX dos para capturar datos (base y altura) y el tercero para
desplegar el resultado (area).
4.- Un componente BUTTON para que active y contenga el codigo del problema y/o
programa.
Procedimiento detallado
1.- Crear un folder o directorio en su disco duro C:\ llamado PROGRAM1
2.- Cargar VISUAL BASIC desde la barra de start de windows
3.- Usar la opción FILE –> NEW PROJECT –> WINDOWS APPLICATION
4.-Usar Ahora la opcion FILE –> SAVEALL De la pantalla de grabación que sale ponerle
un nombre al proyecto (dejar el default ) y apuntarlo al directorio que se hizo de programas:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 105
5.- Queda ahora la pantalla de trabajo o diseno o construccion del programa
Recordar que pueden agregar TOOLBOX, (VENTANA DE PROPIEDADES Y
EXPLORADOR DE SOLUCIONES) usando la opción VIEW de la barra del menú.
6.- Observar que en grafica de arriba esta seleccionada la propia forma o ventana.
Dentro del programa se estarán cargando todos los objetos que usa el programa y por ejemplo
Visual Basic NET a los dos textbox's que se estarán usando los nombra por DEFAULT
como TextBox1 y TextBox2, con esas mayúsculas y minúsculas así que estará dificil estar
recordando su nombre por defecto
Es conveniente estar usando la propiedad NAME de todos los objetos sobre todo
textbox y label que se coloquen en una forma o ventana.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 106
Es decir es mas fácil construir una formula que diga [Link] = [Link] + 5 a el
original que seria [Link] = [Link] + 5 por esta razón es conveniente
asignarle un nombre relevante a cada TextBox usando la propiedad NAME de la pagina de
propiedades, en este curso se les asigna NAME a todos los textbox's y muchos de los otros
componentes que se usan.
7.- Arrastrar y acomodar desde la CAJA DE HERRAMIENTAS a FORM1 3 (tres)
compontes LABEL y cargarles su PROPIEDAD TEXT con las palabras BASE, ALTURA y
AREA respectivamente para escribir esto solo hacerlo usando la cajita que esta a un lado de
la propiedad dentro dela pagina de propiedades.
NOTA: si de alguna manera el editor los manda al código del programa,
observar que arriba de FORM1 hay tres pestañas:
[Link] la que contiener el codigo del programa en los procedimientos y
eventos
FORM1 DESIGN que contiene el diseño
START PAGE contiene las caracteristicas de la pagina de inicio
De solo click en form1 design para regresar al ambiente visual.
8.- Arrastrar y acomodar ahora tres componentes textBox de los cuales en su propiedad
TEXT, limpiarla y dejarla en blanco y en su propiedad (NAME) cargarlos con las palabras
BASE, ALTURA y AREA respectivamente.
9.- Arrastrar y acomodar ahora un componente o control BUTTON, poner su propiedad
text=OK.
La pantalla diseñada es: 10.-Colocaremos el siguiente codigo
dentro del evento click de BUTTON
Private Sub Button1_Click(ByVal
sender As [Link], ByVal e As
[Link]) Handles
[Link]
[Link]=([Link]*[Link]
xt / 2)
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 107
Para escribir este código solo haga CLIK dentro de BUTTON1 y VISUAL BASIC los
mandara a la pantalla de código, donde ya estará cargado el evento button1_clik(){}.
Atención solo se escribe el código en rojo, el evento [Link](){} ya lo
escribe visual basic por default y respetar todas las mayusculas y minusculas
dentro del codigo.
Los dos parámetros que van dentro de button_click (OBJETO, variable e)–> son para
indicarle al compilador que se estarán enviando OBJETOS entre la forma o ventana y el
usuario del programa ( LOS TEXTBOXS son los objetos y primero se mandan vacios al
usuario y luego el sistema los recoge con datos desde el usuario).
La VARIABLE “e” (environment) es donde el sistema o compilador los va almacenando
temporalmente, si ya vieron algo de msdos y conocen el comando set ahí observaran los
textbox's con sus datos.
Regresando al código:
a.- Son las propiedades TEXT de los TEXTBOX'S quienes contienen los datos tanto
capturados como los de salida.
b.- Recordar además que cualquier propiedad TEXT de cualquier CONTROL o
COMPONENTE solo maneja datos de tipo TEXTO o STRING y por tanto para poder
realizar operaciones con los [Link] visual basic NET internamente los convierte
a los tipos apropiados.
c.- [VARNUMERICA COMPONENTE EXPRESION] .ToString() –> se uso para convertir
el valor numérico a tipo string Y PODERLO FORMATEAR para que salga el resultado con
dos decimales ( este tema de formateo se ve en el tema siguiente), para poderlo almacenar en
la propiedad TEXT del TEXTBOX.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 108
11.- Ya cargada la forma con sus componente y el evento click con su código respectivo,
grabar el programa con la opción FILE→SAVE o usar el icono de grabación (el disquito o
disquitos que esta en la barra de iconos arriba) y luego ejecutar el programa usando el icono
de RUN que también se encuentra en la barra de herramientas arriba o DEBUG START
o F5.
12.- El programa en ejecucion:
Nota: Si buscan muy bien dentro del folder
project1 se encontraran con muchos
archivos que creo VISUAL BASIC, dos de
ellos son los interesantes:
[Link] que contiene todo el código
fuente, es decir el programa original y
[Link]
(dentro del folder bin\debug) que es el
archivo ejecutable, basta darle un click
desde el explorer de windows y se ejecutara
solo sin necesidad de que este cargado el
compilador de visual basic.
3.2.- Otros componentes Visual Basic
En este tema analizamos algunas instrucciones de VISUAL BASIC que nos permitirán
facilitar algunas tareas que están pendientes y también algunos controles y componentes que
también nos darán buena ayuda.
Formateo de datos numericos
Como se observa en los aplicaciones ya construidas los formatos numéricos de salida dejan
mucho que desear, para corregir esta situación, solo basta agregar una string de control dentro
del paréntesis de ToString(“strcontrol”) que son una serie de caracteres especiales que
proporciona la plataforma NET.
Ejemplo;
Double alfa = 3456.678 * 21.456 / 73.78902
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 109
Es claro que cuando esta variable alfa se mande a un textbox o un label el valor numérico
desplegado contendrá un montón de valores decimales, para mandar solo la cantidad de
decimales apropiados, solo usar la string de control con los caracteres apropiados ej;
[Link] = [Link](”#.##”)
Esta instrucción desplegara el resultado con solo dos decimales como resultado, si buscamos
la documentación de Visual Basic, esta nos muestra todos los posibles caracteres que se
pueden incluir en la string de control.
User-Defined Numeric Formats (Format Function)
3.3.-Dos o más forms en Visual Basic NET
El siguiente problema común, con el manejo de programas en VISUAL BASIC, es el de poder
crear, controlar y administrar mas de dos forms a la vez.
En este ejemplo o tema se crea un segundo form en diseño.
IMPORTANTE: TODOS LOS COMPONENTES LABEL'S TEXTBOX'S BUTTON'S, etc. que se
coloquen dentro de una forma o ventana deberan de asignarles su propiedad (NAME), es
decir VISUAL BASIC por default si se pone un label en la primera ventana (Form1) le asigna
el nombre de label1, si también se coloca otra label en la segunda ventana (Form2) también
le asignara el nombre de label1 y cuando se este ejecutando el programa y se codifique una
referencia a label1 visual basic tendrá problemas para conocer de cual label se está
tratando.
Para resolver este problema la referencia deberá realizarse usando el formato
[Link]
También es recomendable usar la propiedad NAME para todos los componentes
que se usen dentro de una forma.
a) Crear un proyecto normal con su FORM1 normal.
b) Ahora se crea un segundo FORM2 o ventana, para lograr esto solo usar la opción
PROJECT→ADD NEW→WINDOWSFORM y seleccionar windowsform y observar y tratar
de usar algunos de los otros tipos de forma que ya trae incorporado visual basic .
Esta opción solo se muestra cuando ya se creó un proyecto, observar también que en el
ADMINISTRADOR DE PROYECTOS aparece registradas los dos forms [Link] y [Link].
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 110
c) Solo hacer click en [Link] en el administrador de proyectos (o usar la pestaña arriba
en el compilador que ya debe mostrar las dos formas o ventanas) para tener en la pantalla
de diseno la segunda ventana, cargarle con sus propios label's, textbox's y buttons, es decir
contruirle su programa, recordar tambien asignarles sus propios NAME'S.
d) El codigo del BUTTON1 de la primera ventana Form1 es:
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
[Link]()
End Sub
Solo usar propiedad SHOW() con la ventana2 o FORM2
Recordar que si se quiere que FORM1 haga otro proceso u operación solo agregarle
componentes y mas BUTTON's
El Código del botón OK de la segunda ventana Form2, es:
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
[Link]()
End Sub
Estamos viendo ahora un nuevo operador de visual basic NET, el operador ME, este
operador es una referencia o enlace directo al objeto activo, el evento button1_Clic() está
contenido dentro de esta FORM2 por tanto el objeto activo es FORM2 [Link]() sería
equivalente a [Link]() pero visual basic prefiere trabajar mejor con referencias o
enlaces a objetos, por eso es mejor usar THIS.
Corrida: form1
Nota:
Recordar que si se quiere que FORM2 haga
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 111
otro proceso u operación solo agregarle
componentes y mas BUTTON's
Recordar que les indique que windowsforms tiene muchos y valiosos controles o
componentes en esta ventana se uso CALENDAR y se ve elegante
Corrida form2:
Recordar otra vez que
windowsforms tiene muchos y
valiosos controles o
componentes en esta ventana se
uso WEBBROWSER y se ve
elegante
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 112
4.- Estructuras, ciclos, decisiones, en Visual Basic
4.1.-Instrucciones condicionales Visual Basic
Instrucciones de control de programa que permiten alterar la secuencia normal de ejecución
de un programa. Estas instrucciones se dividen en tres grandes categorías:
1.- Instrucciones Condicionales que en VISUAL BASIC NET se implementan con las
instrucciones if y select case.
Instrucciones de ciclos con
for
do while loop
do loop while
Muchas de ellas con sus correspondientes componentes visuales, tanto en html como
en activex, htmlcontrols y webcontrols, pero para propósito del curso solo se usaran
los Controls ASP NET
Una de las más poderosas caracteristicas de cualquier computador es la capacidad que tiene
de tomar decisiones.
Es decir al comparar dos alternativas diferentes el computador puede tomar una decision
basandose en la evaluacion que hace de alguna condicion. Ejemplo de instrucciones
condicionales:
si sueldo > 3000
desplegar rico
si no
desplegar pobre
Fin-si
si sexo = 'm'
imprime mujer
si no
imprime hombre
Fin-si
De los ejemplos observar que los caminos a seguir por el computador dependeran de la
evaluacion que el computador hace con la condicion. Todo lenguaje de programacion debe
tener instrucciones que permitan formar condiciones e instrucciones que pueden evaluar esas
condiciones.
Pero recordar que lenguajes modernos y orientados a clientes-servidores de igual forma
tienen componentes que permiten del mismo modo al usuario tomar decisiones incluso
directamente en pantalla, es decir tambien existen los objetos, controles o componentes de
seleccion y decision en html, htmlcontontrols, activex, webcontrols.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 113
El formato general de una instruccion condicional es:
Como se observa, son cuatro partes bien diferenciadas entre si;
La propia instruccion condicional en si
La condicion
El grupo cierto de instrucciones
El grupo falso de instrucciones
Cuando el computador evalua una condicion el resultado de esa evaluacion solo es evaluado
de dos maneras o la condicion es CIERTA o la condicion es FALSA.
Esto dependerá del valor que tenga asignado o que se haya capturado para la variable que
está en la condició
Por ejemplo si se capturo 8000 en sueldo en el ejemplo a) entonces el computador indicaría
que la condicion es CIERTA pero en otro caso si a la variable sueldo primero se le asigno un
valor de 250 entonces el computador indicaría que la condicion es FALSA. Dependiendo del
resultado de la evaluacion, el programa realiza las instrucciones contenidas en el grupo de
cierto o falso respectivamente.
Empezaremos el análisis por la CONDICION presentada.
CONDICIONES SIMPLES VISUAL BASIC En general todas las condiciones se forman
con tres elementos los cuales son:
Variables Operadores relacionales Constantes o variables
sexo = “m”
sueldo > 30000
Carrera = “informatica”
Una condicion simple en visual basic NET se define como el conjunto de variables y/o
constantes unidas por los llamados operadores relacionales.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 114
4.2- OPERADORES RELACIONALES EN VISUAL BASIC
Los operadores relacionales que reconoce Visual Basic NET se presentan en la siguiente
tabla:
Operador Significado Descripcion
= Igual Es verdadero si las expresiones comparadas son
iguales
< Menor que Es verdadero si la expresión de la izquierda es
menor que la expresión de la derecha
> Mayor que Es verdadero si la expresión de la izquierda es
mayor que la expresión de la derecha
<> Diferente que Es verdadero si la expresión de la izquierda es
diferente de la expresión de la derecha
<= Menor o igual que Es verdadero si la expresión de la izquierda es
menoro igual que la expresión de la derecha
>= Mayor o igual que Es verdadero si la expresión de la izquierda es
mayor o igual que la expresión de la derecha
4.3.- INSTRUCCION IF… Then Else en VISUAL BASIC
Es la instrucción condicional más usada en los diversos lenguajes de programación, su
formato completo y de trabajo en VISUAL BASIC es:
If condicion Then
Instrucciones cuando la condicion sea cierta
Else
Instrucciones cuando la condicion sea falsa
End If
Si un if no ocupa un grupo falso de instrucciones entonces no usar la clausula else
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
If [Link] > 3000 Then
[Link]("RICO")
Else
[Link]("POBRE")
End If
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 115
Si lo corremos veremos algo asi:
En Visual Basic NET es valido usar mas de
una instruccion dentro del grupo cierto o
falso del if.
Actividades de reforzamiento de lo aprendido
EJERCICIOS DE PROGRAMACION EN VISUAL BASIC NET
1.- Capturar un número cualesquiera e informar si es o no es mayor de 100
2.- Capturar un número entero cualesquiera e informar si es o no es multiplo de 4 (recordar
el operador mod analizado en el tema de operadores aritmeticos).
3.- Capturar los cinco datos más importantes de un Empleado, incluyendo el sueldo diario y
los dias trabajados desplegarle su cheque semanal solo si gano mas de $500.00 en la
semana, en caso contrario desplegarle un bono de despensa semanal de $150.00, PUEDEN
USAR PANELS PARA SEPARAR O MEJOR AUN OTRAS VENTANAS O FORMAS.
4.- Capturar los datos mas importantes de un estudiante incluyendo tres calificaciones
construir una boleta de calificaciones en un PANEL O VENTANA de respuesta bien bonita si
el estudiante es de la carrera de medicina, en caso contrario construir un PANEL O VENTANA
mas bonita todavia que despliega un oficio citando a los padres del estudiante a una platica
amistosa con los maestros de la escuela.
5.- Capturar los datos más importantes de un producto cualesquiera, incluyendo cantidad,
precio, etc. desplegar una orden de compra, solo si el producto es de origen nacional, en
caso contrario no hacer nada.
Nota: Es muy importante realizar siempre un diseño visual de lo que queremos
realizar en el grograma y como esto se vera en la aplicación, Visual Basic NET
facilita mucho esta situacion
4.4.- CONDICIONES COMPUESTAS EN VISUAL BASIC
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 116
En muchas ocasiones es necesario presentar más de una condicion para su evaluacion al
computador. Por ejemplo se necesita un programa que el computador muestre la boleta de un
alumno si este estudia la carrera de medicina y su promedio de calificaciones es mayor de
70.
Una condicion compuesta se define como dos o más condiciones simples unidas por los
llamados operadores lógicos.
Los operadores logicos que VISUAL BASIC NET reconoce son:
OPERADOR DESCRIPCION
AND Es verdadera si las dos expresiones comparadas son verdadera
OR Es verdadera si una de las dos expresiones es verdadera
NOT Invierte el valor de la expresión. Dos negaciones es una afirmación y
negar una afirmación es el valor contrario de la afirmacion
Xor Es verdadera si una de las dos expresiones comparadas es verdadera
AndAlso Es verdadera si las dos expresiones comparadas son verdadera, con al
particularidad de que evalua la segunda parte de la expresión si la
primera la cumple
OrElse Es verdadera si una de las dos expresiones comparadas son verdadera,
con al particularidad de que si cumple la primera expresión no continua
la siguientedando como verdadera la comparación logica
La cantidad total de casos posibles cuando se unen dos o mas condiciones simples esta dada
por la relacion 2n donde n es la cantidad de condiciones, la primera mitad de ellos empieza
en cierto y la segunda mitad en falso. Ejemplo, si formamos una condicion compuesta con
dos condiciones simples y el operador logico “y”, la cantidad total de casos posibles serian
22 = 4, y se puede construir la siguiente tabla de verdad.
Tabla de verdad con “AND”
PRIMERA CONDICION SEGUNDA CONDICION EVALUACION
SIMPLE SIMPLE
C C C
C F F
F C F
F F F
La evaluacion final, se obtiene usando la regla anteriormente descrita para una condicion
compuesta, que contiene el operador “AND”.
Esta tabla significa lo siguiente:
1.- Cualquiera que sean la cantidad de datos procesados, siempre caera en uno de estos cuatro
casos generales. La tabla de verdad para una condicion compuesta con “OR” es la siguiente:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 117
PRIMERA CONDICION SEGUNDA CONDICION EVALUACION
SIMPLE SIMPLE
C C C
C F C
F C C
F F F
Otro ejemplo: Construir una tabla de verdad para una condicion compuesta de tres o mas
condiciones simples es tambien tarea sencilla, solo recordar que;
1.- La cantidad posible de casos es 23 = 8 casos posibles, la mitad empiezan con Cierto y la
otra mitad empiezan con Falso.
2.- Para evaluar esta condicion triple primero se evaluan las dos primeras incluyendo su
operador bajo las reglas ya descritas y luego se evalua el resultado parcial contra la ultima
condicion y ultimo operador para obtener la evaluacion final.
Ejemplo una condicion compuesta de tres condiciones simples, donde el primer operador
logico es el “AND” y el segundo operador logico es el “OR”, daria la siguiente tabla de
verdad.
PRIMERA SEGUNDA EVALUACION TERCERA EVALUACION
CONDICION CONDICION DE PRIMERA CONDICION OR DE
SIMPLE SIMPLE Y SEGUNDA SIMPLE TERCERA Y
CONDICION CUARTA COL.
C C C C C
C C C F C
C F F C C
C F F F F
F C F C C
F C F F F
F F F C C
F F F F F
Programa ejemplo: Determinar de acuerdo a la edad si los datos del ususario son de un joven
o de una persona “anciana”, (edad limite = 30)
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
If [Link] < 30 And [Link] = "H" Then
[Link] = "Muchacho Joven"
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 118
Else
[Link] = "Anciano"
End If
End Sub
Salida del programa
Actividades de reforzamiento de lo aprendido
EJERCICIOS DE PROGRAMACION
1.- Construir un programa que capture un número cualesquiera e informe si es o no es mayor
de 50 y múltiplo de tres. (Solo escribir el mensaje de respuesta de manera muy clara y esto
resuelve el problema)
2.- Construir un programa que indique si un número es un par positivo.
3.- Capturar los datos de un producto incluyendo su cantidad en existencia, desplegar una
orden de compra si la cantidad en existencia del producto es menor que el punto de reorden,
o si el origen del producto es nacional.
4.- Construir un programa que capture los datos de un empleado, desplegar en un panel o
ventana su cheque semanal si gana mas de $500.00 y si esta en el departamento de producción
en caso contrario desplegarle en otro panel o ventana un bono de despensa del 25% de su
sueldo semanal.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 119
4.5.-Instrucciones de control en visual basic.
INSTRUCCION SELECT CASE VISUAL BASIC
También existen ocasiones o programas donde se exige evaluar muchas condiciones a la vez,
en estos casos o se usa una condicion compuesta muy grande o se debe intentar convertir el
problema a uno que se pueda resolver usando la instrucción SELECT CASE.
Esta instrucción es una instrucción de
Select Case variableopcion decisión múltiple donde el compilador
case const1 prueba o busca el valor contenido en una
instruccion(es) variable ENTERA, CHARACTER,
case const2 STRING contra una lista de constantes
instruccion(es) apropiadas, cuando el computador
case const3 encuentra el valor de igualdad entre
Instruccion(es) variable y constante entonces ejecuta el
… grupo de instrucciones asociados a dicha
case Else instruccion(es) constante, si no encuentra el valor de
End Select igualdad entre variable y constante,
entonces ejecuta un grupo de
instrucciones asociados a un default,
aunque este ultimo es opcional. El
formato de esta instrucción es el
siguiente:
Programa ejemplo :
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Select Case [Link]
Case "A"
[Link] = "AGUILA"
Case "B", "b"
[Link] = "BESTIA"
Case "C"
Dim ALFA As Integer
ALFA = 100 + 5
' observar como se encadenan strings usando simbolo &
[Link] = ALFA & " CABALLOS"
Case Else
[Link] = "NO HAY"
End Select
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 120
End Sub
Observar el caso “b”, se pueden usar más de
dos constantes.
En el caso “C” recordar que cada CASE
puede llevar un conjunto de instrucciones
que se ejecutaran hasta que el compilador
encuentre el siguiente case.
Observar y recordar en caso “C” como se
unen dos o mas strings, usando el signo &.
4.6.-Ciclo FOR TO NEXT
Instrucciones para ciclos resuelven el problema de repetir todo el programa o cierta parte del
programa más de una vez. Este ciclo es uno de los más usados para repetir una secuencia
de instrucciones sobre todo cuando se conoce la cantidad exacta de veces que se quiere que
se ejecute una instruccion simple o compuesta. El formato es el siguiente:
FOR VARCICLO = VALINICIAL TO VALFINAL [STEP INCR O DECR]
INSTRUCCION(ES)
NEXT
Ejemplo:
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Dim X As Integer
[Link]()
For X = 1 To 10
[Link](X & "= MAMA")
Next X
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 121
Notas:
Se esta usando un objeto listbox con
NAME = LISTA para procesar el
conjunto de datos. O se usan
muchos webcontrols label o textbox
para desplegar todo lo que despliega
el ciclo for o se esta usando mejor
un objeto listbox para procesar el
. conjunto de datos. Se esta usando la
propiedad add de la coleccion
items del control listbox (lista).
Observar que para encadenar strings
en visual basic se usa el signo &
El metodo [Link], es porque
cuando el usuario usa el click más
de una vez, el control listbox los va
agregando de nuevo abajo, por eso
en cuanto se activa el onclick lo
primero que se realiza es limpiar el
listbox.
El ciclo for es muy sencillo y no ocupa mucha explicacion, solo
empieza en UNO y se va incrementando de UNO en UNO
Casos Particulares del ciclo for:
1.- El ciclo comienza en uno y se incrementa de uno en uno, este es el caso más general.
2.- Pero el valor inicial puede se diferente de uno, ejemplo;
FOR X=5 TO 28
Desplegar X
NEXT
3.- Incluso el valor inicial puede ser negativo, ejemplo;
FOR X= -5 TO 18
Desplegar X
NEXT
4.- Los incrementos tambien pueden ser diferentes al de uno en uno, ej.;
FOR X=1 TO 50 STEP 4
Desplegar X
NEXT
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 122
5.- Incluso pueden ser decrementos, solo que en este caso, recordar;
5.1.- el valor inicial de la variable debe ser mayor que el valor final y usar un step negativo.
FOR X=100 TO 20 STEP - 5
Desplegar X
NEXT
El uso, gestión y manipulación de matrices (Que estudiaremos adelante) utilizan el bucle :
For … Each
Instrucciones…
Next
Veamos este ejemplo:
Private Sub Button2_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Dim MiArreglo() As String = {“Uno”,”Dos”,”Tres”}
Dim SCadena As String
Dim Smensaje As String = “ ”
For Each SCadena In MiArreglo
Smensaje += SCadena & “ “
Next
[Link]([Link])
End Sub
Actividades de reforzamiento de lo aprendido
EJERCICIOS DE PROGRAMACION
1.- Construir un programa que despliegue los numeros del 20 al 30.
2.- Desplegar los enteros entre 50 y 30 acompañados de su potencia cuadrada y raiz cubica
respectiva (revisar tema de operadores aritmeticos y buscar la libreria de funciones
matematicas de Visual Basic).
3.- Desplegar los multiplos de 5, entre 10 y 50, acompañados de su factorial y logaritmo
respectivo (La misma recomendacion del ejercio anterior).
4.- Desplegar la tabla de multiplicar que el usuario indique
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 123
5.- Evaluar la funcion y = 5x2 + 3x + 8 cuando x= -3…10 (rango de -3 hasta 10)
4.5.-Ciclo DO WHILE LOOP
En este ciclo el cuerpo de instrucciones se ejecuta mientras una condicion permanezca
como verdadera en el momento en que la condicion se convierte en falsa el ciclo termina.
Su formato general es :
DO WHILE CONDICION(ES)
INSTRUCCION(ES) CIERTAS
INSTRUCCION(ES) DE SALIDA DE CICLO
LOOP
Programa
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Dim X As Integer
X=1
[Link]()
Do While X <= 10
[Link](X & "= GATO")
X=X+1
Loop
End Sub
Corrida
Nota:
While puede llevar dos condiciones; en este caso
inicializar 2 variables de condicion y cuidar que
existan 2 de rompimiento o terminacion de ciclo.
El grupo cierto de instrucciones puede ser una sola
instruccion o todo un grupo de instrucciones. La
condicion puede ser simple o compuesta.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 124
A este ciclo tambien se le conoce tambien como ciclo de condicion de entrada o prueba por
arriba porque este ciclo evalua primero la condicion y posteriormente ejecuta las
instrucciones.
Actividades de reforzamiento de lo aprendido
EJERCICIOS DE PROGRAMACION
1.- Desplegar enteros entre 50 y 80
2.- Desplegar multiplos de 4 entre 60 y 20 acompanados de su logaritmos de base 10 y base
e respectivos (revisar tema operadores atitmeticos)
3.- Construir la tabla de dividir que el usuario indique
4.- Evaluar una función cualesquiera para el rango de valores de x de -3 a +5
4.7.-Ciclo DO LOOP WHILE
Su diferencia básica con el ciclo do while loop es que la prueba de condición es hecha al
finalizar el ciclo, es decir las instrucciones se ejecutan cuando menos una vez porque primero
ejecuta las instrucciones y al final evalúa la condición.
También se le conoce por esta razón como ciclo de condición de salida.
Su formato general es:
DO
INSTRUCCION (ES) CIERTAS
INSTRUCCION (ES) DE SALIDA DE CICLO
LOOP WHILE CONDICION (ES)
Programa
Private Sub EVENTO1(ByVal sender As Object, ByVal e As [Link])
Dim X As Integer
X=1
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 125
[Link]()
Do
[Link](X & " perico")
X=X+1
Loop While X <= 10
End Sub
Otra diferencia básica con el ciclo do while loop es que aunque la condición sea falsa desde
un principio el cuerpo de instrucciones se ejecutara por lo menos una vez.
CONCLUSIONES CICLOS VISUAL BASIC
En Visual Basic NET dado un problema o programa cualesquiera que sea el tipo de ciclo que
se utilice, se resuelve con:
1. Si se conoce la cantidad exacta de veces que se quiere que se ejecute el ciclo o si el
programa de alguna manera puede calcularla usar for..net.
2. Si se desconoce la cantidad de veces a repetir el ciclo o se quiere mayor control sobre
la salida o terminacion del mismo entonces usar do while loop.
3. Si se quiere que al menos una vez se ejecute el ciclo entonces usar do loop while.
4.7.-Arreglos en Visual Basic NET
Aspectos básicos
También conocido con las denominaciones de matriz y vector, un array es aquel elemento
del lenguaje que nos permite agrupar un conjunto de valores del mismo tipo, y acceder
a ellos a través de una misma variable o identificador, especificando la posición o
índice en donde se encuentra el dato a recuperar. El Código fuente , muestra las
operaciones esenciales que podemos realizar con un array.
Private sub form1_load…
‘ vamos a utilizar un control textbox con la propiedad multiliea a verdadero
‘ para visualizar los resultados de los programas, y botones para cada
‘caso de estudio..
' declarar un array de tipo String, el número de elementos es el indicado
' en la declaración más uno, porque la primera posición de un array es cero
Dim sNombres(3) As String
' asignar valores al array
sNombres(0) = "Ana"
sNombres(1) = "Pedro"
sNombres(2) = "Antonio"
sNombres(3) = "Laura"
' pasar un valor del array a una variable
Dim sValor As String
sValor = sNombres(2)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 126
' mostrar en la pantalla el valor pasado a una variable
' y un valor directamente desde el array
[Link] =[Link] &"Valor de la variables: " & sValor & VbCrLf
[Link] =[Link] & "Valor del array, posición 1: "& sNombres(1)
End Sub
A lo largo de este texto, emplearemos de forma genérica el término array, para
referirnos a este elemento del lenguaje. Por otra parte, recomendamos al lector la creación
de un nuevo proyecto en el IDE de tipo consola, para realizar las pruebas mostradas a lo
largo del tema.
La clase Array
Esta clase, perteneciente a la jerarquía de clases del sistema, es decir, incluida en el
espacio de nombres System, proporciona a través de sus miembros, acceso orientado a
objeto para los arrays que manipulemos en nuestras aplicaciones. Esto quiere decir que
los arrays, como sucede con otros elementos del lenguaje, son también objetos.
Al igual que el resto de elementos del entorno, los arrays son tipos pertenecientes al sistema
común de tipos de la plataforma o CTS, y se encuentran clasificados como tipos por
referencia; esto quiere decir, que durante la ejecución, un array será gestionado en la zona
de memoria conocida como montón o heap.
Aunque podemos trabajar con los arrays como objetos, no será necesario instanciar un
objeto de esta clase para poder disponer de un array. Al declarar una variable como array,
implícitamente se instancia un objeto de la clase. En sucesivos apartados de este tema,
haremos una descripción de los miembros de instancia y compartidos más importantes de la
clase Array.
Adecuación de los arrays en VB con los arrays de la plataforma .NET
Los arrays son uno de los elementos de VB que menos han evolucionado a lo largo de
las sucesivas versiones aparecidas de este lenguaje. Todo esto, sin embargo, ha
cambiado con la llegada de la plataforma .NET.
La especificación CLS del entorno .NET, dicta que todos los lenguajes que cumplan
con la misma, podrán ser utilizados bajo .NET Framework. Esto quiere decir además, que
dos ensamblados escritos en distintos lenguajes de la plataforma, podrán compartir código
entre ellos. En el caso que nos ocupa, una aplicación [Link] podrá llamar a un método
de un objeto escrito en C# que devuelva un array, y dicho array, será manejado desde
[Link].
Los diseñadores de .NET han realizado un gran esfuerzo en proporcionar la máxima
optimización y versatilidad a los arrays, siempre y cuando, el lenguaje del entorno que
los utilice, cumpla con unos mínimos requerimientos. En este aspecto, [Link] como
lenguaje, ha obtenido toda la potencia de base inherente en el sistema para la creación
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 127
y manipulación de arrays; mientras que como contrapartida, ciertas características
exclusivas en VB para el manejo de arrays han necesitado ser readaptadas. Algunas de
estas características se describen a continuación.
El primer índice de un array debe ser siempre cero
[Link] no soporta la instrucción Option Base, que nos permitía indicar que el primer
índice de un array podía ser cero o uno. Por lo tanto, al declarar ahora un array en
[Link], su número de elementos será el indicado en la declaración más uno. Veamos
las diferencias en el Código fuente:
Private sub form1_load…
' array de 3 elementos
Dim sNombres(2) As String
sNombres(0) = "Pedro"
sNombres(1) = "Ana"
sNombres(2) = "Jaime"
End Sub
Todos los arrays son dinámicos
En [Link] todos los arrays son de tamaño variable, tanto si se especifica como no un
tamaño al ser declarados. En este punto debemos matizar un aspecto: cada vez que en
[Link] se cambia el tamaño de un array, el entorno internamente destruye el array actual,
y crea un nuevo objeto de la clase Array, con el nuevo tamaño especificado, usando el
mismo nombre de la variable correspondiente al array eliminado en primer lugar.
Declaración
Declararemos un array de igual forma que hacemos con una variable normal, con la
excepción de que junto al nombre de la variable, situaremos unos paréntesis. Esto indica
que dicha variable contiene un array. Opcionalmente, podemos especificar entre los
paréntesis las dimensiones del array, o número de elementos que va a contener. Es posible
también, realizar una asignación de valores al array en el mismo momento de su
declaración. El Código fuente, muestra algunos ejemplos.
Private sub form1_load…
' formas de declaración de arrays
' ===============================
' 1)
' estableciendo el número de elementos
Dim sNombres(2) As String
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 128
' 2)
' asignando valores al array al mismo tiempo que se declara, la lista de valores
' debe ir encerrada entre llaves
Dim sEstaciones() As String = {"Ana", "Pedro", "Luis"}
' 3)
' indicando el tipo de dato pero no el número de elementos, de este modo la variable
' todavía no es considerada un array ya que contiene una referencia a Nothing
Dim iValores() As Integer
' 4)
' indicando el tipo de dato y estableciendo una lista vacía de elementos, a diferencia
' del caso anterior, la variable ahora sí
' es considerada un array aunque de longitud cero
Dim iDatos() As Integer = {}
' 5)
' instanciando el tipo de dato, estableciendo el número de elementos al
' instanciar, e indicando que se trata de un array al situar las llaves
Dim iCantidades() As Integer = New Integer(20) {}
' 6)
' declarar primero la variable que contendrá el array, asignar valores al array
' al mismo tiempo que se instancia la lista de valores debe ir encerrada
' entre llaves
Dim iNumeros() As Integer
iNumeros = New Integer() {10, 20, 30, 10, 50, 60, 10, 70, 80}
End Sub
Recomendamos al lector, que en estos ejemplos con arrays, utilice el depurador para
ejecutar línea a línea el código, y abra la ventana Locales del depurador para ver en
cada caso, el contenido de los elementos del array.
Asignación y obtención de valores
Para asignar u obtener valores de los elementos de un array, emplearemos la variable que
contiene el array haciendo referencia al índice o posición a manipular. O bien, puesto que
un array es un objeto, utilizaremos los métodos SetValue( ) y GetValue( ) que asignan
y obtienen respectivamente los valores del array. Veamos un ejemplo en el Código fuente
:
Private sub button1…..
' asignación de valores a los elementos de un array
' =================================================
Dim sNombres(4) As String
' directamente sobre la variable, haciendo referencia al índice
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 129
sNombres(0) = "Juan"
sNombres(1) = "Ana"
sNombres(2) = "Luis"
' o con el método SetValue(), asignando el valor en el primer parámetro
' y especificando la posición en el segundo
[Link]("Elena", 3)
[Link]("Miguel", 4)
' obtención de valores de un array
Dim sValorA As String
Dim sValorB As String
sValorA = sNombres(2) ' directamente de la variable
sValorB = [Link](3) ' usando el meth GetValue
[Link] = "Contenido de las variables " & vbCrLf
[Link] = [Link] & "==========================" & vbCrLf
[Link] = [Link] & "ValorA ValorB:" & vbCrLf
[Link] = [Link] & sValorA & vbTab & sValorB & vbCrLf
End Sub
Recorrer el contenido
Para realizar un recorrido por los elementos de un array, disponemos de las funciones
LBound( ) y UBound( ), que devuelven el número de índice inferior y superior
respectivamente del array que pasemos como parámetro. No obstante, la orientación a
objetos proporcionada por el entorno, pone a nuestra disposición el nuevo conjunto de
características que comentamos seguidamente.
Length. Esta propiedad de un objeto array devuelve el número de elementos que
contiene.
GetLowerBound( ), GetUpperBound( ). Estos métodos de un objeto array,
devuelven respectivamente, el número de índice inferior y superior de una
dimensión del array. El resultado es el mismo que usando LBound( ) y
UBound( ), pero desde una perspectiva orientada a objetos.
Enumeradores. Un objeto enumerador pertenece al interfaz IEnumerator,
diseñado para realizar un recorrido o iteración a través de uno de los diferentes
tipos de colección (arrays incluidos) existentes en .NET Framework. Mediante el
método GetEnumerator( ) de un objeto array, obtenemos un objeto que implementa
el interfaz Ienumerator, que sólo puede realizar labores de lectura sobre el array,
en ningún caso de modificación.
La estructura de control utilizada para recorrer el array, puede ser indistintamente un bucle
For...Next, For Each...Next, o la novedosa técnica de los objetos enumeradores
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 130
proporcionados por el objeto array. Como muestra de estas funcionalidades, el Código
fuente siguiente que vemos a continuación, contiene algunos ejemplos de cómo realizar una
iteración sobre los elementos de un array.
Private Sub [Link]…..
' recorrer un array
Dim sNombres() As String = {"Ana", "Pedro", "Pablo", "Jorge", "Jesus"}
Dim iContador As Integer
Dim sUnNombre As String
' modo tradicional
[Link] = [Link] & "Recorrido del array con LBound() y UBound()"
& vbCrLf
For iContador = LBound(sNombres) To UBound(sNombres)
[Link] = [Link] & "Posicion " & vbTab & iContador & vbTab & _
sNombres(iContador) & vbCrLf
Next
[Link] = [Link] & vbCrLf ' linea en blanco con bucle For Each
[Link] = [Link] & "Recorrido del array con bucle For Each" &
vbCrLf
For Each sUnNombre In sNombres
[Link] = [Link] & "Nombre actual: " & sUnNombre _
& vbCrLf
Next
' linea en blanco usando la propiedad Length
[Link] = [Link] & vbCrLf
[Link] = [Link] & "Recorrido del array con propiedad Length" &
vbCrLf
For iContador = 0 To ([Link] - 1)
[Link] = [Link] & "Posicion: " & vbTab & " Valor" _
& iContador & vbTab & sNombres(iContador) & vbCrLf
Next
[Link] = [Link] & vbCrLf ' linea en blanco
' usando los métodos GetLowerBound() y GetUpperBound()
[Link] = [Link] & "Recorrido del array con métodos
GetLowerBound() y GetUpperBound()" & vbCrLf
For iContador = [Link](0) To [Link](0)
[Link] = [Link] & "Posicion: " & iContador & vbTab & " Valor: " _
& sNombres(iContador) & vbCrLf
Next
[Link] = [Link] & vbCrLf ' linea en blanco
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 131
' recorrer con un enumerador
[Link] = [Link] & "Recorrido del array con un enumerador" &
vbCrLf
Dim sLetras() As String = {"a", "b", "c", "d", "e", "f"}
Dim oEnumerador As [Link]
' obtener el enumerador del array
oEnumerador = [Link]()
' con un enumerador no es necesario posicionarse en el primer elemento ni
' calcular la cantidad de elementos del array, sólo hemos de avanzar posiciones con
' MoveNext() y obtener el valor actual con Current
While [Link]()
[Link] = [Link] & "Valor actual: " & [Link] &
vbCrLf
End While
End Sub
Modificación de tamaño
Para aumentar o disminuir el número de elementos de un array disponemos de la
palabra clave ReDim. Esta instrucción crea internamente un nuevo array, por lo que los
valores del array original se pierden. Evitaremos este problema utilizando junto a ReDim
la palabra clave Preserve, que copia en el nuevo array, los valores del array previo.
Veamos unos ejemplos en el Código fuente:
Private Sub [Link]…
' modificar el tamaño de un array
' ===============================
Dim sNombres(2) As String
sNombres(0) = "Juan"
sNombres(1) = "Pedro"
sNombres(2) = "Elena"
[Link] = [Link] & "Array sNombres original" & VbCrLf
MostrarArray(sNombres)
' ampliamos el número de elementos ,pero perdemos el contenido previo
ReDim sNombres(4)
sNombres(3) = "Isabel"
sNombres(4) = "Raquel"
[Link] = [Link] & "Array sNombres con tamaño ampliado"
&VbCrLf
MostrarArray(sNombres)
' creamos otro array
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 132
Dim sMasNombres(2) As String
sMasNombres(0) = "Juan"
sMasNombres(1) = "Pedro"
sMasNombres(2) = "Miguel"
[Link] = [Link] & "Array sMasNombres original" & VbCrLf
MostrarArray(sMasNombres)
' ampliamos el array sin perder elementos
ReDim Preserve sMasNombres(4)
sMasNombres(3) = "Antonio"
sMasNombres(4) = "Paco"
[Link] ="Array sMasNombres ampliado sin perder valores" & VbCrLf
MostrarArray(sMasNombres)
' reducimos el array, pero sin perder los primeros elementos
ReDim Preserve sMasNombres(1)
[Link] = [Link] & "Array sMasNombres reducido" & VbCrLf
MostrarArray(sMasNombres)
[Link] = [Link] & vbCrLf
End Sub
Private Sub MostrarArray(ByVal sMiLista() As String)
' este es un procedimiento de apoyo que muestra el array pasado como parámetro
Dim iContador As Integer
For iContador = 0 To [Link] - 1
[Link] = [Link] &"Elemento: “ & VbTab & ” Valor: " _
& iContador & VbTab & sMiLista(iContador) &VbCrLf
Next
[Link] = [Link] & vbCrLf
End Sub
Uso del método CreateInstance() para establecer el número de elementos
en un array
Ya hemos comprobado que al crear un array en [Link], el primer índice es siempre cero,
y además, el número de elementos del array es el indicado en la declaración más uno.
Sin embargo, la clase Array dispone del método compartido CreateInstance( ), que como
su nombre indica, permite crear una nueva instancia de la clase, es decir un objeto array,
con la particularidad de que en este caso, el número de elementos del array será realmente
el que establezcamos al llamar a este método.
El Código fuente siguiente, muestra la diferencia entre crear un array del modo habitual,
y empleando CreateInstance( ).
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 133
Private Sub [Link]…
' declarar un array del modo habitual:
' este array tiene cuatro elementos, desde el índice 0 al 3
Dim sEstaciones(3) As String
sEstaciones(0) = "Primavera"
sEstaciones(1) = "Verano"
sEstaciones(2) = "Otoño"
sEstaciones(3) = "Invierno"
[Link] = [Link] & "Array sEstaciones" &VbCrLf
MostrarArray(sEstaciones)
[Link] = [Link] & vbCrLf
' crear un array instanciándolo con el método CreateInstance()
' de la clase Array
Dim sColores As Array
' este array tendrá tres elementos reales que van desde el índice 0 hasta el 2
sColores = [Link](GetType(String), 3)
sColores(0) = "Azul"
sColores(1) = "Rojo"
sColores(2) = "Verde"
[Link] = [Link] & "Array sColores" & VbCrLf
MostrarArray(sColores)
[Link] = [Link] & vbCrLf
End Sub
Private Sub MostrarArray(ByVal sMiLista() As String)
' muestra el array pasado como parámetro
Dim iContador As Integer
For iContador = 0 To [Link] - 1
[Link] = [Link] &"Elemento: “ & VbTab & ” Valor: " _
& iContador & VbTab & sMiLista(iContador) & VbCrLf
Next
End Sub
Paso de arrays como parámetros, y devolución desde funciones
Podemos pasar un array como parámetro a una rutina de código, teniendo en cuenta que
los cambios que realicemos sobre el array en el procedimiento llamado, se mantendrán
al volver el flujo de la ejecución al procedimiento llamador.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 134
Ello es debido a que los arrays son tipos por referencia del entorno, y por lo tanto, las
variables del array que manejamos tanto desde el procedimiento llamador, como desde
el procedimiento llamado, son en realidad punteros hacia una misma zona de memoria o
referencia, la que contiene el array.
En el ejemplo del siguiente Código fuente, comprobaremos que al pasar un array por valor,
los cambios que realicemos sobre sus elementos se mantendrán al volver al procedimiento
que hizo la llamada.
Private Sub [Link]…
[Link] = “”
Dim iValores() As Integer = {10, 20, 30}
' en ambos casos, se pasa una referencia del array
ManipArrayVal(iValores)
ManipArrayRef(iValores)
' al volver de las llamadas a los procedimientos, ' el array ha sido modificado en
' ambas llamadas, independientemente de que haya sido pasado por ' valor o
' referencia
MostrarArray(iValores)
[Link] = [Link] & vbCrLf
End Sub
' a este procedimiento le pasamos un array por valor
Private Sub ManipArrayVal(ByVal iListaPorValor As Integer())
' cambiar elemento del array
iListaPorValor(0) = 888
End Sub
' a este procedimiento le pasamos un array por referencia
Private Sub ManipArrayRef(ByRef iListaPorReferencia As Integer())
' cambiar elemento del array
iListaPorReferencia(2) = 457
End Sub
Private Sub MostrarArray(ByVal sMiLista() As Integer)
' muestra el array pasado como parámetro
Dim iContador As Integer
For iContador = 0 To [Link] – 1
[Link] = [Link] &"Elemento: “ & VbTab & ” Valor: " _
& iContador & VbTab & sMiLista(iContador) & VbCrLf
Next
[Link] = [Link] & vbCrLf
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 135
End Sub
Clonación
Para evitar el problema planteado en el apartado anterior, si necesitamos disponer de un
array con las mismas características que uno ya existente, y que sea totalmente
independiente del primero, utilizaremos el método Clone( ). Con esto solucionaremos
el problema de que al pasar un array como parámetro, las modificaciones que precisemos
realizar, afecten al array original. Veamos un ejemplo en el Código fuente.
Private Sub [Link]…
' crear un array
[Link] = “”
Dim iValores() As Integer = {10, 20, 30}
CambiaArray(iValores)
' mostrar el array original, ' en este no se habrán producido cambios
[Link] = [Link] & "Array original " & VbCrLf
MostrarArray4(iValores)
[Link] = [Link] & VbCrLf
End Sub
Private Sub CambiaArray(ByVal iListaDatos As Integer())
' crear un array clónico, cambiarle valores y mostrarlo
Dim iListaClonada As Array
iListaClonada = [Link]()
iListaClonada(0) = 621
iListaClonada(1) = 900
[Link] = [Link] &"Array clónico" & VbCrLf
MostrarArray4(iListaClonada)
End Sub
Private Sub MostrarArray4(ByVal sMiLista() As Integer)
Dim iContador As Integer
For iContador = 0 To [Link] – 1
[Link] = [Link] &"Elemento: “ & iContador & VbTab _
& ” Valor: "& VbTab & sMiLista(iContador) & VbCrLf
Next
[Link] = [Link] & VbCrLf
End Sub
Copia
Si intentamos copiar un array asignando la variable que contiene un array a otra, el resultado
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 136
real serán dos variables que apuntan a la misma lista de valores, por lo que en definitiva sólo
tendremos un array, al cual podremos acceder usando dos variables. Ello es debido a que
como explicamos en un apartado anterior, los arrays son tipos por referencia que apuntan al
mismo conjunto de valores.
Podemos clonar el array, como se ha descrito en el apartado anterior, con lo que
obtendremos un nuevo array, que será idéntico al original.
O bien, podemos copiar el array utilizando los métodos CopyTo( ) y Copy( ) de la clase
array. La diferencia con respecto a la clonación, consiste en que al copiar un array, el array
destino ya debe estar creado con el número suficiente de elementos, puesto que los
métodos de copia de la clase Array, lo que hacen es traspasar valores de los elementos
del array origen al array destino, en función de los parámetros utilizados, copiaremos
todos los elementos o un subconjunto. Veamos unos ejemplos en el Código fuente:
Private Sub [Link]….
Dim sColores(3) As String
[Link] = “”
sColores(0) = "Azul"
sColores(1) = "Verde"
sColores(2) = "Rosa"
sColores(3) = "Blanco"
MostrarArray5(sColores)
' copiar usando el método CopyTo(), copiamos en el array sColorDestino,
' y comenzando por su posición 2, los valores del array sColores
Dim sColorDestino(6) As String
[Link](sColorDestino, 2)
[Link] = [Link] & "Array sColorDestino de la posic 2 en adelante "
_
& VbCrLf
MostrarArray5(sColorDestino)
' copiar usando el método Copy(), copiamos en el array sListaColores,
' a partir de su posición 2, 2 elementos del array sColores, comenzando
' desde la posición 1 de sColores
Dim sListaColores(5) As String
[Link](sColores, 1, sListaColores, 2, 2)
[Link] = [Link] & "Array sListaColores de la posic 2 se toman 2 " _
& vbCrLf
MostrarArray5(sListaColores)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 137
[Link] = [Link] & VbCrLf
End Sub
Private Sub MostrarArray5(ByVal sMiLista() As String)
Dim iContador As Integer
For iContador = 0 To [Link] - 1
[Link] = [Link] &"Elemento: “ & iContador & _
VbTab & ” Valor: " & VbTab & sMiLista(iContador) & VbCrLf
Next
[Link] = [Link] & VbCrLf
End Sub
Inicialización de valores
Para inicializar o eliminar los valores de los elementos de un array, utilizaremos el
método Clear, al que pasaremos el array a inicializar, el índice a partir del que
comenzaremos, y el número de elementos. Los valores serán inicializados en función
del tipo de dato del array; cadena vacía en arrays String; cero en arrays numéricos, etc
Veamos el Código fuente:
Private Sub [Link]…
[Link] = “ “
' array String, asignar valores e inicializar
Dim sLetras(2) As String
sLetras(0) = "a"
sLetras(1) = "b"
sLetras(2) = "c"
' limpiar elementos en un array de tipo String,
' los elementos limpiados quedan como cadena vacía
[Link](sLetras, 0, 1)
[Link] = [Link] & "Array sLetras" & VbCrLf
MostrarArray6(sLetras)
[Link] = [Link] & VbCrLf
' array Integer, asignar valores e inicializar
Dim iNumeros() As Integer = {100, 200, 300, 400, 500, 600}
' limpiar elementos en un array de tipo Integer, los elementos limpiados
' se ponen a 0
[Link](iNumeros, 1, 2)
[Link] = [Link] & "Array iNumeros" & VbCrLf
MostrarArrayNum(iNumeros)
[Link] = [Link] & VbCrLf
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 138
' array Object, asignar valores e inicializar
Dim oVarios(6) As Object
oVarios(0) = "Hola"
oVarios(1) = 456
oVarios(2) = 1200
oVarios(3) = #12/25/2001#
oVarios(4) = 900
oVarios(5) = True
oVarios(6) = "adelante"
' al ser este un array de tipo Object los elementos limpiados se
' establecen a Nothing
[Link](oVarios, 3, 2)
[Link] = [Link] & "Array oVarios" & VbCrLf
MostrarArrayObj(oVarios)
[Link] = [Link] & VbCrLf
End Sub
' recorrer un array de cadenas
Private Sub MostrarArray6(ByVal sMiLista() As String)
Dim iContador As Integer
For iContador = 0 To [Link] - 1
[Link] = [Link] &"Elemento: “ & iContador & VbTab & _
” Valor: " & VbTab & sMiLista(iContador) & VbCrLf
Next
[Link] = [Link] & vbCrLf
End Sub
' recorrer un array de números
Private Sub MostrarArrayNum(ByVal iMiLista() As Integer)
Dim iContador As Integer
For iContador = 0 To [Link] - 1
[Link] = [Link] &"Elemento: “ & iContador & VbTab & ” _
Valor: " & VbTab & iMiLista(iContador) & VbCrLf
Next
[Link] = [Link] & vbCrLf
End Sub
' recorrer un array de objetos
Private Sub MostrarArrayObj(ByVal oMiLista() As Object)
Dim iContador As Integer
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 139
For iContador = 0 To [Link] - 1
[Link] = [Link] &"Elemento: “ & iContador & vbTab & ” _
Valor: " & vbTab & oMiLista(iContador) & vbCrLf
Next
[Link] = [Link] & vbCrLf
End Sub
Ordenación
Para ordenar un array disponemos del método Sort( ), que al estar sobrecargado,
tiene varias implementaciones; la más básica de ellas es la que ordena la totalidad del
array. También podemos ordenar una parte del array, indicando la posición inicial y
cantidad de elementos a ordenar, etc.
El método Reverse( ), invierte la posición de todos o parte de los elementos de un array. En
este punto, debemos matizar que no se realiza un orden inverso de los elementos,
sino que se cambian las posiciones de los mismos. Ver Código fuente :
Private Sub [Link]….
[Link] = “ “
' ordenar todo el array
Dim sLetras1() As String = {"z", "a", "g", "m", "w", "i", "c", "b"}
[Link] = [Link] &"arreglo original" & VbCrLf
MostrarArray7(sLetras1)
[Link](sLetras1)
[Link] = [Link] &"Ordenar todos el array" & VbCrLf
MostrarArray7(sLetras1)
' ordenar parte del array
Dim sLetras2() As String = {"z", "a", "g", "m", "w", "i", "c", "b"}
[Link](sLetras2, 4, 3)
[Link] = [Link] & "Ordenar parte del array" & VbCrLf
MostrarArray(sLetras2)
' invertir valores dentro del array
Dim sLetras3() As String = {"z", "a", "g", "m", "w", "i", "c", "b"}
[Link](sLetras3, 2, 4)
[Link] = [Link] & "Invertir valores del array" & VbCrLf
MostrarArray7(sLetras3)
[Link] = [Link] & vbCrLf
End Sub
Private Sub MostrarArray7(ByVal sMiLista() As String)
Dim iContador As Integer
For iContador = 0 To [Link] - 1
[Link] = [Link] &"Elemento: “ & iContador & VbTab & ” _
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 140
Valor: " & VbTab & sMiLista(iContador) & VbCrLf
Next
[Link] = [Link] & vbCrLf
End Sub
Búsqueda
Los métodos IndexOf( ) y LastIndexOf( ) de la clase Array, nos permiten buscar un
elemento en un array comenzando la búsqueda desde el principio o final respectivamente.
Ya que ambos disponen de diferentes implementaciones al estar sobrecargados, consulte el
lector la documentación de la plataforma. El Código fuente siguiente muestra algunos
ejemplos de uso.
Private Sub [Link]…
[Link] = “ “
Dim sNombres() As String = {"Alberto", "Juan", "Ana", "Paco", "Miguel", "Ana"}
' buscar una cadena a partir del índice 0 del array
[Link] = [Link] & "Paco está en la posición “ & VbTab & _
[Link](sNombres, "Paco") & VbCrLf
' buscar una cadena a partir del índice 3 del array
[Link] = [Link] & "Ana está en la posición" & _
" comenzando a buscar desde índice 3" & VbTab & _
[Link](sNombres, "Ana", 3) & VbCrLf
' introducir un valor a buscar en el array, si no existe se devuelve -1
Dim iPosicionBuscar As Integer
Dim TNom As Integer
TNom = InputBox("Introducir nombre a buscar")
iPosicionBuscar = [Link](sNombres, Tnom)
If iPosicionBuscar = -1 Then
MsgBox("El nombre no está en el array")
Else
MsgBox("El nombre está en la posición “ & VbTab &_
iPosicionBuscar & VbTab & “ del array " )
End If
' buscar comenzando por la última posición
Dim iNumeros() As Integer
Dim iUltPosicionBuscar As Integer
[Link] = [Link] & vbCrLf
iNumeros = New Integer() {10, 20, 30, 10, 50, 60, 10, 70, 80}
[Link] = [Link] & " En el arreglo {10, 20, 30, 10, 50, 60, 10, 70,
80}"_
& vbCrLf
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 141
[Link] = [Link] & "El 10 está en la posición " & _
[Link](iNumeros, 10) & " comenzando por el final"
[Link] = [Link] & vbCrLf
End Sub
EJERCICIOS DE PROGRAMACION DE ARREGLOS TIPO ARREGLOS
1.- Capturar y desplegar 5 precios de productos cualesquiera usando dos panel uno para
capturar y uno para desplegar
2.- Capturar 4 sueldos en un panel desplegarlos aumentados en un 25% en otro panel
3.- Capturar los datos de 5 productos comprados en una tienda, incluyendo nombre, precio y
cantidad en sus 3 listas respectivas, despues calcular una cuarta lista con el gasto total por
cada producto desplegarlo todo en un segundo panel e incluir tambien el gran total
4.- Capturar en una lista solamente 6 numeros multiplos de 5, se debe de estar capture y
capture numeros hasta que se completen los 6 multiplos de 5
Arrays multidimensionales
Todos los arrays vistos hasta el momento han sido de tipo unidimensional, es decir,
estaban compuestos de una lista de valores única. .NET Framework nos provee también de
la capacidad de crear arrays formados por más de una lista de valores, o lo que es igual,
arrays multidimensionales. Un array de este tipo, se caracteriza por estar compuesto de
varias dimensiones o listas anidadas al estilo de filas y columnas. Si declaramos un array del
modo que muestra el Código fuente:
Dim iDatos(2, 4) As Integer
Crearíamos un array multidimensional formado por tres filas y cinco columnas. En
este caso, el número correspondiente a la primera dimensión denota las filas, mientras que
el número de la segunda dimensión hace lo propio para las columnas. La Figura muestra
un diagrama con la estructura de este array.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 142
Estructura de un array multidimensional.
En este tipo de arrays, para acceder a los valores, debemos especificar la dimensión y la
posición a la que vamos a asignar o recuperar un dato. Ver código.
Private Sub [Link]…
' crear array multidimensional y rellenar de valores
Dim iDatos(2, 4) As Integer
Los elementos de la tabla se deberan simbolizar con el nombre de la tabla y 2 subindices, el
primer subíndice referencia al renglón o fila y el siguiente subíndice referencia la columna
los dos dentro del mismo corchete.
La declaración de una tabla sera de acuerdo al siguiente formato:
shared dim nomtabla(reng-1,col-1) as <tipodato>
Ejemplo:
shared dim sueldo(3,4) as double
Recordar que va a generar una matriz que tendra cuatro renglones y cinco columnas
empieza en sueldo(0,0)
Para procesar (recordar solo operaciones y comparaciones) internamente todos los
elementos de la tabla se ocupan dos ciclos for uno externo para controlar renglón o fila y
uno interno para controlar columna.
Para capturar sus elementos, usaremos un textbox y un boton de captura, solo tener
cuidado o mucho control sobre los indices rEN y col como lo muestra el ejemplo.
Para efectuar otros procesos tales como operaciones, despliegues con todos los elementos
de la tabla se deberan usar 2 ciclos un for externo para controlar renglon y un for interno
para controlar columna.
Programa
' declarando lista global
' recordar que son 3 reng y 4 columnas
Shared CALIFICACION(2, 3) As Integer
' declarando reng y col como global
Dim R, C As Integer
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 143
Private Sub Button1_Click_1(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
' En este modulo solo se trabaja con el arreglo en memoria
CALIFICACION(R, C) = [Link]
C=C+1
[Link] = ""
If C = 4 Then
R=R+1
C=0
End If
If R = 3 Then
[Link] = False
End If
End Sub
Private Sub Button2_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Dim TEMP As String
' procesando y regalando 50 puntos a todos
For R = 0 To 2
For C = 0 To 3
CALIFICACION(R, C) = CALIFICACION(R, C) + 50
Next C
Next R
' desplegando los datos
For R = 0 To 2
TEMP = CALIFICACION(R, 0) & " " & CALIFICACION(R, 1) & " " & CALIFICACION(R, 2) & " " &
CALIFICACION(R, 3)
[Link](TEMP)
' limpiando temporal antes de otro renglon
TEMP = " "
Next
End Sub
Notas: Observar el formato de declaracion y como se controlan los indices de captura r, c
Para procesar los elementos se usan dos ciclos for y el formato tabla (reng,col).
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 144
En este problema se usa el objeto LISTBOX para presentar el resultado mas adelante se
usara un objeto mas apropiado.
Diseño: Corrida:
Las matrices en Visual Basic tienen la capacidad de cambiar o modificar su tamaño, es
decir su dimensión en memoria, utilizando las palabras reservadas:
ReDim Y ReDim Preserve
Ejemplo:
Dim MiArreglo() As String ‘ Declaro mi arreglo
ReDim MiArreglo(2) ‘ Declaro nuevamente mi arreglo de dimension 3
MiArreglo(0) = “Uno” : MiArreglo(1) = “Dos” : MiArreglo(2) = “Tres”
ReDim Preserve MiArreglo(3) ‘Declaro nueva dimensión preservando los valores
MiArreglo(3) = “Cuatro”
[Link](MiArreglo(0)) ‘Muestro el valor del primer dato
Nota : Podemos concatenar varias líneas de código separadas por :
Importante: Si deseamos conocer el tamaño o dimensión, podemos utilizar unmetodo de
los arreglos :
[Link]
Ejemplo, utilizando el anterior podemos escribir
[Link]([Link])
Nos visualizaría 4, que es la dimensión del arreglo
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 145
Importante: Si deseamos eliminar los elementos de un arreglo de forma rápida utilizamos
la palabra rservada Nothing, ejemplo:
MiArreglo = Nothing
If MiArreglo IsNothing then
[Link](“ Nada”)
Else
[Link]([Link]) ‘presenta la dimension
Endif
Importante: Si deseamos copiar una matriz en otra podemos hacerlo de esta forma:
[Link](OtroArreglo,0)
Ejemplo:
Private Sub Button1_Click_1(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim MiArreglo() As String = {“Mercurio”,”Venus”,”Tierra”}
Dim OtroArreglo() As String
ReDim OtroArreglo([Link] – 1)
[Link](OtroArreglo,0)
[Link](OtroArreglo(0))
End Sub
Para recorrer arrays multidimensionales, la clase Array dispone de varios miembros,
algunos de los cuales, describimos seguidamente.
Rank. Devuelve el número de dimensiones del array.
GetLength(Dimension). Devuelve el número de elementos de la dimensión de
array pasada como parámetro.
GetLowerBound(Dimension). Devuelve el número de índice inferior de la
dimensión pasada como parámetro.
GetUpperBound(Dimension). Devuelve el número de índice superior de la
dimensión pasada como parámetro.
Vamos a completar el ejemplo anterior con las líneas del siguiente código, necesarias
para recorrer el array multidimensional mostrado.
Private Sub [Link]….
[Link] = " "
' crear array multidimensional y rellenar de valores
Dim iDatos(2, 4) As Integer
Dim iContadorDimUno As Integer
Dim iContadorDimDos As Integer
Dim sTextoFila As String
' poner títulos de la fila y columnas del array a mostrar
[Link] = [Link] & "Matriz de (3,5) tres filas , cinco columnas " &
vbCrLf
[Link] = [Link] & vbCrLf
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 146
[Link] = [Link] & "Fila" & vbTab & "Col 1" & vbTab & "Col 2" &
_
vbTab & "Col 3" & vbTab & "Col 4" & vbTab & "Col 5" & vbCrLf
' El bucle externo recorre la primera dimensión las Filas
For iContadorDimUno = [Link](0) To [Link](0)
' aquí obtenemos el número de fila que se está procesando
sTextoFila = iContadorDimUno
‘ escribo el nuemro de la fila
[Link] = [Link] & sTextoFila + 1 & vbTab
' este bucle recorre la segunda dimensión las columnas
For iContadorDimDos = [Link](1) To [Link](1)
' [Link] = [Link] & vbTab & sTextoFila & _
iDatos(iContadorDimUno, _
iContadorDimDos) ' & vbTab
[Link] = [Link] & iDatos(iContadorDimUno, iContadorDimDos) _
& vbTab
Next
[Link] = [Link] & vbCrLf
Next
sTextoFila = ""
[Link] = [Link] & vbCrLf
[Link] = [Link] & "El número de dimensiones es: " & [Link] _
& vbCrLf
[Link] = [Link] & "El número total de elementos es: " & _
[Link] & vbCrLf
End sub
Actividades de reforzamiento de lo a
aprendido
TAREAS PROGRAMACION DE TABLAS (ARREGLOS BIDIMENSIONALES)
1.- Construir un cuadro que contenga los costos fijos de cuatro productos cualesquiera, que
se producen en tres plantas diferentes de una empresa maquiladora (2 prog uno capturado
y otro inicializado).
2.- Construir un cuadro que contenga los ingresos mensuales por ventas durante los tres
primeros meses del ano de cuatro sucursales de una cadena de auto refacciones, agregar al
final una lista que muestre los ingresos mensuales totales por meses y una segunda lista
que muestre los ingresos mensuales totales por sucursal(2 progs uno capturado y otro
inicializado).
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 147
3.-Construir un cuadro que contenga las comisiones ganadas por tres vendedores, de los 5
tipos de linea blanca de conocida muebleria, ademas listas de comisiones totales y
promedios ganadas por los vendedores, asi como listas de comisiones totales y promedios
por tipo de linea blanca
Analizar este codigo:
' PARA TOTALES Y PROMEDIOS POR RENGLON (FILAS)
FOR R = 0 TO 3
FOR C = 0 TO 2
TOTRENG(R) = TOTRENG(R) + TABLA(R,C)
NEXT C
PROMRENG(R) = TOTRENG(R)/3
NEXT R
'PARA TOTALES Y PROMEDIOS POR COLUMNA
FOR C = 0 TO 2
FOR R = 0 TO 3
TOTCOL(C)=TOTCOL(C) + TABLA(R,C)
NEXT R
PROMCOL(C) = TOTCOL(C) / 4
NEXT C
4.9--Funciones del lenguaje integradas
Cada lenguaje dispone de un grupo de funciones de apoyo, para ayudar al programador
en su trabajo cotidiano. Las versiones anteriores de Visual Basic contenían un gran
número de funciones para realizar operaciones aritméticas, manipular cadenas, fechas,
etc.
[Link] también tiene funciones para las operaciones antes comentadas. No obstante,
debido a la orientación a objetos sobre la que está construida la plataforma .NET, la
gran potencia a la hora de resolver cualquier situación la encontraremos en el gran
número de clases proporcionadas por el entorno para resolver las más variadas
situaciones, lo que veremos en el tema dedicado a OOP.
En este apartado y organizadas por categorías, vemos una pequeña muestra de las
funciones disponibles en [Link]. Consulte el lector la documentación de la
plataforma, para obtener información más detallada de todas las funciones disponibles.
Funciones Numéricas
Int(Número), Fix(Número). Estas funciones devuelven la parte entera del
parámetro Número. La diferencia entre ambas reside en que cuando el parámetro pasado
es negativo, Int() devuelve el entero negativo menor o igual que Número, mientras
que Fix( ) devuelve el entero negativo mayor o igual que Número. Ver el Código
Dim Resultado As Integer
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 148
Resultado = Int(66.87) ' 66
Resultado = Fix(66.87) ' 66
Resultado = Int(-66.87) ' -67
Resultado = Fix(-66.87) ' –66
Randomize([Número]). Inicializa el generador de números aleatorios, que
utilizaremos posteriormente en la función Rnd( ). Opcionalmente recibe un número
como parámetro que sirve al generador como valor inicial o semilla para la creación
de estos números.
Rnd([Número]). Devuelve un número aleatorio de tipo Single, que será menor que 1,
pero mayor o igual a cero.
Podemos, opcionalmente, variar el modo de generación del número pasando un valor al
parámetro de esta función. En función de si el parámetro es mayor, menor de cero, o
cero, el comportamiento de Rnd( ) a la hora de generar el número será diferente. Ver el
Código
Dim Contador As Integer
Dim Aleatorio As Single
Randomize()
For Contador = 1 To 5
Aleatorio = Rnd()
MsgBox("Número generado: es "&, Aleatorio)
Next
El anterior código produce una salida similar a la mostrada en la Figura
Numero generado: 0,706402
Numero generado: 0,4058605
Numero generado: 0,337209
Numero generado: 0,8914912
Numero generado: 0,8711619
Generación de números aleatorios con Rnd( ).
Si necesitamos que el número aleatorio esté comprendido en un intervalo de
números enteros, utilizaremos la fórmula del Código para generarlo.
Int((LímiteSuperior - LímiteInferior + 1) * Rnd() + LímiteInferior)
El ejemplo del Código crea números aleatorios comprendidos entre el intervalo de los
números 7 y 12.
Dim Contador As Integer
Dim Aleatorio As Single
Randomize()
For Contador = 1 To 10
Aleatorio = Int((12 - 7 + 1) * Rnd() + 7)
MsgBox("Número generado: "& Aleatorio)
Next
Funciones Cadena de caracteres (Imports [Link])
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 149
Len(Cadena). Devuelve un número con la longitud de la cadena pasada como parámetro.
Ver el Código
Dim Longitud As Integer
Longitud = Len("comprobar cuantos caracteres hay")
MsgBox("La cadena tiene caracteres " & Longitud) ' 32
Space(Número). Devuelve una cadena de espacios en blanco, de una longitud igual al
número pasado como parámetro. Ver el Código.
Dim ConEspacios As String
ConEspacios = "Hola" & Space(7) & "a todos"
MsgBox("La cadena con espacios tiene el valor:" & [Link] &
ConEspacios)
' Hola a todos
[Link]([Comienzo, ]CadenaBuscar, CadenaBuscada [, TipoComparación]).
Busca dentro de CadenaBuscar la cadena contenida en el parámetro CadenaBuscada.
Opcionalmente podemos establecer en Comienzo, la posición en la que comienza la
búsqueda y el tipo de comparación (texto, binaria) en el parámetro TipoComparación. Ver el
Código
Dim CadBuscar As String
Dim CadBuscada As String
Dim PosComienzo As Integer
CadBuscar = "El castillo del bosque"
PosComienzo = InStr(CadBuscar, "tillo")
MsgBox("La posición de comienzo de la cadena encontrada es: " & ,PosComienzo)
'7
[Link](Cadena, Longitud). Esta función extrae, comenzando por la parte izquierda de
Cadena, una subcadena de Longitud de caracteres.
[Link](Cadena, Longitud). Esta función extrae, comenzando por la parte derecha
de Cadena, una subcadena de Longitud de caracteres.
El Código muestra ejemplos de Left( ) y Right( ).
Dim CadIzquierda As String
Dim CadDerecha As String
CadIzquierda = [Link]("Especial", 3)
MsgBox("Resultado de la función Left(): "& CadIzquierda) ' Esp
CadDerecha = [Link]("Especial", 3)
MsgBox("Resultado de la función Right(): "& CadDerecha) ' ial
Mid(Cadena, Inicio [, Longitud]). Extrae de Cadena, comenzando en la posición Inicio,
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 150
una subcadena. Opcionalmente podemos utilizar el parámetro Longitud, para indicar el largo
de la subcadena. En caso de no utilizar este último parámetro, la subcadena se obtendrá
hasta el final. Ver Código
Dim MiCadena As String
Dim SubCadena As String
MiCadena = "El bosque encantado"
SubCadena = [Link](MiCadena, 6)
MsgBox("Subcadena hasta el final: "& SubCadena) ' sque encantado
SubCadena = Mid(MiCadena, 6, 3)
MsgBox("Subcadena de 3 caracteres: "& SubCadena) ' squ
Replace(Cadena,CadOrigen,CadNueva [,Inicio] [,Sustituciones]
[,TipoComparación]).
Esta función toma la cadena situada en el primer parámetro y busca la cadena
CadOrigen, sustituyendo las ocurrencias encontradas por la cadena CadNueva.
Opcionalmente, el parámetro Inicio especifica la posición en la que comenzará la
sustitución; el parámetro Sustituciones indica el número de sustituciones a realizar; y
TipoComparación indica como se realizarán las comparaciones (texto, binaria). Veamos
unos ejemplos en el Código
Dim MiCadena As String : Dim CadSustituida As String
MiCadena = "Este coche es especial"
CadSustituida = Replace(MiCadena, "es", "xx")
' resultado: Este coche xx xxpecial
MsgBox("Resultado del reemplazo en la cadena: "& CadSustituida)
' en el anterior ejemplo los dos primeros caracteres no se sustituyen porque
' no se ha especificado el tipo de comparación, que a continuación sí indicaremos
CadSustituida = Replace(MiCadena, "es", "xx", , , [Link])
' resultado: xxte coche xx xxpecial
' ahora sí se han sustituido todas las ocurrencias de "es"
MsgBox("Resultado del reemplazo en la cadena: "& CadSustituida)
[Link](Cadena), RTrim(Cadena), Trim(Cadena). Estas funciones eliminan de
una cadena, los espacios en blanco a la izquierda en el caso de LTrim( ); los espacios
en blanco a la derecha en el caso de RTrim(); o los espacios en blanco a ambos lados Trim(
). Ver el Código
Dim CadEspacios As String : Dim CadResultante As String
CadEspacios = " Barco "
CadResultante = LTrim(CadEspacios) ' "Barco "
CadResultante = RTrim(CadEspacios) ' " Barco"
CadResultante = Trim(CadEspacios) ' "Barco"
UCase(Cadena), LCase(Cadena). Estas funciones, convierten la cadena pasada
como parámetro a mayúsculas y minúsculas respectivamente. Ver el Código .
Dim Cadena As String : Dim CadMay As String: Dim CadMin As String
Cadena = "Vamos a Convertir En Mayúsculas Y MinúscuLAS"
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 151
CadMay = UCase(Cadena)
CadMin = LCase(Cadena)
' "VAMOS A CONVERTIR EN MAYÚSCULAS Y MINÚSCULAS"
MsgBox("Conversión a mayúsculas: " & CadMay)
' "vamos a convertir en mayúsculas y minúsculas"
MsgBox("Conversión a minúsculas: " & CadMin)
Format(Expresión[,CadenaFormato][,PrimerDíaSemana[,PrimeraSemanaAño]).
Formatea la expresión pasada en el primer parámetro, empleando de forma opcional
una cadena para especificar el tipo de formateo a realizar. Si el valor a formatear es una
fecha, podemos utilizar los dos últimos parámetros para especificar el primer día de la
semana y la primera semana del año; estos dos últimos parámetros son enumeraciones,
cuyos valores aparecen automáticamente al asignar su valor. Consulte el lector, la
documentación de ayuda para más información.
Como cadena de formato, podemos utilizar los nombres predefinidos de formato, o una
serie de caracteres especiales, tanto para formateo de números como de fechas. En lo que
respecta a los nombres predefinidos, la Tabla 23 muestra algunos de los utilizados.
Nombre de formato Descripción
General Date Muestra una fecha con el formato largo del
sistema.
Short Date Muestra una fecha empleando el formato corto del
sistema.
Short Time Muestra un valor horario con el formato corto del
sistema.
Standard Muestra un número utilizando los caracteres de
separador de miles y decimales.
Currency Muestra un número con los caracteres
correspondientes a la moneda establecida en la
configuración regional del sistema.
Percent Muestra un número multiplicado por 100 y con el
carácter de tanto por ciento.
Nombres de formato para la función Format( ).
El Código fuente muestra algunos ejemplos de formateo con nombre
Dim MiFecha As Date
Dim MiNumero As Double
Dim ValorFormato As String
MiFecha = #7/19/2002 [Link] PM#
MiNumero = 1804
ValorFormato = Format(MiFecha, "Long Date")' "Viernes, 19 de julio de 2004”
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 152
ValorFormato = Format(MiFecha, "Short Date") ' "19/07/2002"
ValorFormato = Format(MiFecha, "Short Time") ' "18:25"
ValorFormato = Format(MiNumero, "Standard") ' "1.804,00"
ValorFormato = Format(MiNumero, "Currency") ' "1.804 pta"
ValorFormato = Format(MiNumero, "Percent") ' "180400,00%"
Para los caracteres especiales, la Tabla muestra un conjunto de los más habituales.
Carácter de Descripción
formato
: Separador de hora.
/ Separador de fecha.
d Visualiza el número de día sin cero a la
izquierda.
dd Visualiza el número de día con cero a la
izquierda.
ddd Visualiza el nombre del día abreviado.
dddd Visualiza el nombre del día completo.
M Visualiza el número de mes sin cero a la
izquierda.
MM Visualiza el número de mes con cero a
la izquierda.
MMM Visualiza el nombre del mes abreviado.
MMMM Visualiza el nombre del mes completo.
yy Visualiza dos dígitos para el año.
yyyy Visualiza cuatro dígitos para el año.
H Visualiza la hora sin cero a la izquierda.
HH Visualiza la hora con cero a la izquierda.
m Visualiza los minutos cero a la izquierda.
mm Visualiza los minutos con cero a la izquierda.
s Visualiza los segundos cero a la izquierda.
ss Visualiza los segundos con cero a la izquierda.
0 En valores numéricos, muestra un dígito o cero.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 153
# En valores numéricos, muestra un dígito o nada.
, Separador de millar.
. Separador decimal.
Caracteres de formato para la función Format( ).
El Código muestra algunos ejemplos de formato con caracteres especiales.
Dim MiFecha As Date
Dim MiNumero As Double
Dim ValorFormato As String
MiFecha = #7/19/2002 [Link] PM#
MiNumero = 16587.097
ValorFormato = Format(MiFecha, "dddd d/MMM/yyyy") ' "Viernes 19/jul/2002"
ValorFormato = Format(MiFecha, "HH:mm") ' "18:25"
ValorFormato = Format(MiNumero, "#,#.00") ' "16.587,10"
StrConv(Cadena, TipoConversión [,IDLocal]). Realiza una conversión de la cadena
pasada como parámetro, utilizando algunos de los valores de la enumeración
TipoConversión. Opcionalmente podemos pasar también un valor correspondiente al
identificador local del sistema. Ver el Código fuente
Dim MiCadena As String
Dim Conversion As String
MiCadena = "el tren llegó puntual"
' convertir a mayúscula
Conversion = StrConv(MiCadena, [Link])
' convertir a minúscula
Conversion = StrConv(MiCadena, [Link])
' convertir a mayúscula la primera letra de cada palabra
Conversion = StrConv(MiCadena, [Link])
[Link]("Conversion”)
Fecha y hora
Now( ). Devuelve un valor de tipo Date con la fecha y hora del sistema.
DateAdd(TipoIntervalo, ValorIntervalo, Fecha). Suma o resta a una fecha, un
intervalo determinado por el parámetro TipoIntervalo. El intervalo a utilizar pueden ser
días, semanas, meses, etc. Para determinar si se realiza una suma o resta, ValorIntervalo
deberá ser positivo o negativo respectivamente.
DateDiff(TipoIntervalo, FechaPrimera, FechaSegunda). Calcula la diferencia
existente entre dos fechas. En función de TipoIntervalo, la diferencia calculada serán días,
horas, meses, años, etc.
DatePart(TipoIntervalo, Fecha). Extrae la parte de una fecha indicada en
TipoIntervalo. Podemos obtener, el día, mes, año, día de la semana, etc.
El Código fuente muestra un conjunto de ejemplos que utilizan las funciones para
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 154
manipular fechas.
Dim MiFecha As Date
Dim FechaPosterior As Date
Dim DiasDiferencia As Long
Dim ParteFecha As Integer
MiFecha = Now() ' #1/19/2012 [Link] PM#
FechaPosterior = DateAdd([Link], 2, MiFecha) ' #3/19/2012 [Link]
PM#
DiasDiferencia = DateDiff([Link], MiFecha, FechaPosterior) ' 59
ParteFecha = DatePart([Link], MiFecha) ' 2012
[Link]("Dias de diferencias " & DiasDiferencia)
Funciones matemáticas
Las principales funciones matemáticas provistas por Visual Basic son:
[Link](): Devuelve el valor absoluto de una expresión numérica.
[Link](): Devuelve el arco tangente de un número.
[Link](): Devuelve el coseno de un ángulo.
[Link](): Devuelve el número "e" elevado a una potencia.
[Link](): Devuelve el logaritmo natural de un número.
[Link](): Devuelve un valor indicando el signo de un número.
[Link](): Devuelve el seno de un ángulo.
[Link](): Devuelve la raíz cuadrada de un número.
[Link](): Devuelve la tangente de un ángulo.
4.10.-PROCEDIMIENTOS O SUBRUTINAS EN VISUAL BASIC NET
Recordar que un objeto presenta tres aspectos, propiedades, metodos y eventos, en esta
unidad se analizan algunos elementos que intervienen en la definicion de un metodo.
Estamos hablando de los llamados procedimientos y funciones, que quede claro que
procedimientos y funciones son solo algunos aspectos (importantes) de la definicion de un
metodo, pero que existen elementos tan o mas importantes que los analizados en esta
unidad. Un procedimiento es un grupo de instrucciones, variables, constantes, etc, que
estan disenados con un proposito particular y tiene su nombre propio.
Es decir un procedimiento es un modulo de un programa que realiza tareas especificas y
que no puede regresar valores al programa principal u a otro procedimiento que lo este
invocando. Despues de escribir un procedimiento se usara su propio nombre como una
sola instruccion o llamada al procedimiento usando el formato:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 155
CALL NOMPROC()
El formato para construir un procedimiento o subrutina en VISUAL BASIC NET es:
Sub NomProc()
Instrucciones
End Sub
Un programa puede tener tantos procedimientos o subrutinas como se deseen, para hacer
una llamada o invocacion al procedimiento durante la ejecucion de un programa solo se
debera escribir el nombre del procedimiento y los parentesis en blanco.
Programa
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
' llamando, invocando o activando procedimiento uno
Call PROC1()
End Sub
Sub PROC1()
[Link] = [Link] * 12
End Sub
Corrida
Como se observa un procedimiento puede ser un programa completo.
Actividades de reforzamiento de
MSc. Ing. Jorge PradoloD.
aprendido Docente: Universidad Nacional de Ingeniería 156
EJERCICIOS DE PROGRAMACION DE FUNCIONES
Construir tres programas que contengan los procedimientos abajo del sub buttonclick().
a) Convertir $800.00 Cordobas a dolares.
b) Calcular el Area de un triangulo
c) Deplegar una Boleta de calificaciones.
PARAMETROS EN VISUAL BASIC
Un parametro es una variable que puede pasar su valor a un procedimiento desde el principal
o desde otro procedimiento.
Existen ocasiones en que es necesario mandar al procedimiento ciertos valores para que los
use en algun proceso.
Estos valores que se pasan del cuerpo principal del programa o de un procedimiento a otros
procedimientos se llaman parametros. Entonces la declaracion completa de un
procedimiento es :
SUB NOMPROC(lista de parametros)
cuerpo de instrucciones
END SUB
Donde lista de parametros es una o mas variables separadas por comas como lo muestra el
pograma ejemplo. Programa
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim nom As String
nom = "pepe"
'Se puede mandar como parametro un dato, variable 'o expresion algebraica
Call PROC1(3.75, nom, 4 + 8)
End Sub
Sub PROC1(ByVal deci As Single, ByVal nom As String, ByVal suma As Integer)
' pero siempre se recibe en una variable
[Link] = [Link] + deci + suma
[Link] = nom
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 157
Observar que en el procedimiento los parametros crean dos variables de manera local, es
decir variables que solo se pueden usar dentro del procedimiento estas variables son quienes
reciben los datos o valores.
REGLAS PARA EL USO DE PARAMETROS:
1.- Cuando se usan variables como parametros la variable que se manda debe ser declarada
dentro del principal o del procedimiento de donde se esta enviando.
2.- La variable que se manda tiene un nombre, la que se recibe puede tener otro nombre o el
mismo nombre por claridad de programa, pero recordar que internamente en la memoria del
computador existiran dos variables diferentes.
3.- La cantidad de variables que se envian deben ser igual en cantidad, orden y tipo a las
variables que reciben.
4.- La variable que se recibe tiene un ambito local dentro del procedimiento, es decir solo la
puede usar ese procedimiento.
5.- Se puede mandar a un procedimiento un dato, una variable (como lo muestran los
ejemplos) o una expresion algebraica (no ecuacion o formula) pero siempre se deberan recibir
en una variable.
Corrida
Actividad de reforzamiento de lo
aprendido
EJERCICIOS DE PROGRAMACION DE FUNCIONES
1.- En una VENTANA recoger 3 calificaciones en el onclick, calcular promedio en
procedimiento uno y desplegar nombre y promedio en un segundo procedimiento
2,- Construir una tabla de multiplicar que el usuario indique, captura y control de ciclo en
button_click, calculo y despliegue en un procedimiento usar un solo listbox para la tabla
resultado.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 158
3.- Construir un procedimiento que reciba un numero entero y que mande llamar a un segundo
procedimiento pasando el letrero “PAR O IMPAR”
FUNCIONES EN VISUAL BASIC NET
Una funcion es un modulo de un programa separado del cuerpo principal que realiza una
tarea especifica y que puede regresar un valor a la parte principal del programa u otra
funcion o procedimiento que la invoque.
La forma general de una funcion es:
Function NOMFUNCION(parametros)
instrucciones
NOMFUNCION = cargarlo porque es quien regresa el dato
End Function
La lista de parametros formales es una lista de variables separadas por comas (,) que
almacenaran los valores que reciba la funcion estas variables actuan como locales dentro
del cuerpo de la funcion. Aunque no se ocupen parametros los parentesis son requeridos.
Dentro del cuerpo de la funcion deber haber una instruccion que cargue el NOMFUNCION
para regresar el valor, de esta manera se regresan los datos.
Sin embargo es de considerar que NOMFUNCION puede regresar un dato, una variable o
una expresion algebraica (no ecuacion o formula) como lo muestran los siguientes
ejemplos:
a) NOMFUNCION = 3.1416
b) NOMFUNCION = area
c) NOMFUNCION = x + 15 / 2
Recordar ademas:
a) Una funcion no se llama usando CALL
b) Cuando se llame a una funcion debera haber una variable que reciba el valor que
regresara la funcion, es decir generalmente se llama una funcion mediante una sentencia
de asignacion, por ejemplo resultado = funcion(5, 3.1416)
Programa
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
'Creando variable que recibira el valor que regrese la funcion
Dim alfa as integer
'llamando la funcion y mandandole datos o parámetros observar que se llama por
'igualdad
alfa = FUNCION1(500)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 159
' Aunque se puede llamarla directamente y cuantas veces sea necesario
[Link] = FUNCION1(100) - alfa
End Sub
Function FUNCION1(ByVal varuno As Integer)
' cargando y regresando el nomfuncion
FUNCION1 = 100 + varuno
End Function
Corrida
Nota: Es permitido cargar más de
un NOMFUNCION en el cuerpo
de instrucciones sobre todo en
condiciones, pero solo uno de ellos
se ejecutara
Ejemplo;
if suma >= 10 then
funcion50 = 300
else
funcion50 = 20
end if
TIPOS USUALES DE FUNCIONES.
Las primeras son de tipo computacional que son diseñadas para realizar operaciones con
los argumentos y regresa un valor basado en el resultado de esa operacion.
Las segundas funciones son aquellas que manipulan informacion y regresan un valor que
indican la terminacion o la falla de esa manipulacion.
Las terceras son aquellas que no regresan ningun valor, es decir son estrictamenta
procedurales. Esto quiere decir que en general toda operacion o calculo en un programa
debera convertirse a una o muchas funciones y el resto deberan ser procedimientos.
ARREGLOS COMO PARAMETROS
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 160
Para pasar un arreglo completo como parametro a un procedimiento o a una funcion solo
se manda el nombre del arreglo sin corchetes e indices, en el procedimiento o funcion que
recibe solo se declara un arreglo del mismo tipo y se puede usar el mismo o diferente
nombre del arreglo sin corchetes e indices.
Sin embargo es conveniente aclarar, que a diferencia de variables escalares normales visual
basic no genera una nueva variable en memoria ni tampoco copia los datos al arreglo que
recibe, en su lugar visual basic sigue usando los datos que estan en el arreglo original, es
por esta razon que cambios que se le hagan a los datos del arreglo que recibe realmente se
esta haciendo al arreglo original como lo muestra el siguiente ejemplo:
Programa
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
' creando y cargando una lista local con 5 elementos
Dim lista1() As Integer = {1, 2, 3, 4, 5}
' pasandola a un procedimiento observar que se pasa sin parentesis
Call PROC1(lista1)
' desplegando lista original y observar el resultado
Dim r As Integer
For r = 0 To 4
[Link](lista1(r))
Next r
End Sub
Sub PROC1(ByVal vector)
' recibiendola con otro nombre y ' sumando a vector + 100
Dim r As Integer
For r = 0 To 4
vector(r) = vector(r) + 100
Next r
End Sub
Es de recordar que los cambios que le hagan
Corrida al arreglo dentro del procedimiento se
reflejaran en el arreglo original, es por esto
que si se quiere modificar un arreglo en un
procedimiento funcion no hay necesidad de
regresar ningun valor y por tanto no se
ocupan funciones.
Solo para los casos que se quiera regresar
algun dato especial del arreglo, por ejemplo
regresar el primer dato par, o la suma de
todos los elementos del arrreglo o el
promedio de todos sus elementos, etc etc
MSc. Ing. Jorge Prado D. Docente: etc,
Universidad Nacional
solo en casos de Ingeniería
como estos se mandara161
una arreglo a una funcion.
Actividades de reforzamiento de lo aprendido
EJERCICIOS DE PROGRAMACION DE FUNCIONES
1.- Capturar 3 calificaciones y nombre en un procedimiento, calcular promedio en una
funcion, desplegar en otro procedimiento, BUTTONCLICK SOLO ACTIVA EL PRIMER
PROCEDIMIENTO
2.- Crear una tabla de multiplicar, captura y control de ciclo en el principal (BUTTONCLICK),
operaciones en una funcion, despliegue en el principal.
3.- Inicializar 10 edades en el principal(buttonclick) mandar la lista a un procedimiento que
la convierte a meses, desplegar en principal.
4.- Capturar un arreglo de 7 ciudades en un primer procedimiento, sortear en un segundo
y desplegar en un tercero, la lista original y la lista ordenada.
Funciones de comprobación de tipos de datos
Si tenemos desactivada la comprobación de tipos con Option Strict, pero en ciertas
situaciones necesitamos comprobar si determinada variable o expresión contienen un valor
numérico, fecha, etc., el lenguaje nos proporciona para ello, algunas funciones con las que
podremos comprobar el tipo de dato, para evitar posibles errores.
IsNumeric( ). Esta función devuelve un valor lógico indicando si la expresión que
pasamos como parámetro contiene un número o una cadena que pueda ser convertida a
número. Ver el Código
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 162
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Dim Valor As Object
Dim Total As Integer
Valor = Inputbox(“ Introduzca un valor”)
If IsNumeric(Valor) Then
Total = Valor + 100
MsgBox("Resultado: "& Total)
Else
MsgBox("El valor introducido no es numérico")
End If
End Sub
IsDate( ). Esta función devuelve un valor lógico indicando si la expresión que pasamos
como parámetro contiene una fecha o una cadena que pueda ser convertida a fecha. Ver
el Código
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Dim Valor As Object
Dim UnaFecha As Date
Valor = Inputbox(“ Introduzca un valor”)
If IsDate(Valor) Then
UnaFecha = Valor
MsgBox("La fecha es: "& UnaFecha)
Else
MsgBox("El valor introducido no es una fecha")
End If
End Sub
IsArray( ). Esta función devuelve un valor lógico indicando si la expresión que
pasamos como parámetro contiene un array. Ver el Código
.
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Dim Colores() As String = {"Verde", "Azul", "Rojo"}
Verificar(Colores)
Verificar("prueba")
End Sub
Public Sub Verificar(ByVal ValorPasado As Object)
' comprobar si el parámetro contiene un array
If IsArray(ValorPasado) Then
MsgBox("El parámetro pasado es un array")
Else
MsgBox("El parámetro pasado no es un array")
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 163
End If
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 164
5.- Programando con controles en Visual Basic
Los controles proporcionan al usuario el medio para comunicarse con nuestro
formulario, y en definitiva, con la aplicación. Por ello, en los siguientes apartados,
mostraremos los principales aspectos que debemos tener en cuenta a la hora de su
creación, manipulación y codificación.
También realizaremos una revisión de los principales controles, mostrando
algunas de sus características más destacadas.
5.1.-El Cuadro de herramientas
Una vez creado un proyecto, o después de añadir un nuevo formulario, para utilizar
controles en el mismo, tendremos que tomarlos de la ventana Cuadro de herramientas
disponible en el IDE de [Link], y añadirlos al formulario. Ver Figura
Uso del ToolBox
El ToolBox es la caja de herramientas donde se encuentran los controles que se van ha usar
para diseñar la interface de los diferentes tipos de aplicaciones, este varía de acuerdo al tipo
de plantilla elegida. A continuación se presenta el ToolBox cuando elegimos una plantilla
“Windows Application”; éste presenta varias fichas: “Windows Forms”, “Data”,
“Components” y “General”.
Figura 3.2: ToolBox para Aplicaciones Windows
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 165
Para usar un control del ToolBox solo hay que elegir la ficha adecuada y luego seleccionar
el control y arrastrarlo sobre el formulario o contenedor donde se desea ubicarlo, también se
puede dar doble clic sobre el control y aparecerá por defecto en la posición 0,0 del formulario
(antes se ubicaba al centro de éste).
Como habrá comprobado el lector, el número de controles del cuadro de herramientas
es muy numeroso, por lo que en los próximos apartados, vamos a trabajar con los que se
consideran controles básicos o estándar, dada su gran frecuencia de uso. La Tabla
relaciona este conjunto de controles básico, junto a una breve descripción.
Insertar un control en el formulario
Para añadir un control en el formulario, proceso que también se conoce como dibujar
un control, debemos seleccionar primeramente el control a utilizar de la lista que
aparece en el cuadro de herramientas.
Una vez localizado el control, haremos doble clic sobre él, o pulsaremos [INTRO], lo que
añadirá una copia del mismo en el formulario, que después, mediante el ratón o teclado,
situaremos en la posición adecuada.
Otra técnica, esta más habitual, consiste en hacer clic sobre el control, situar el cursor del
ratón en la superficie del formulario y hacer clic en él, arrastrando hasta dar la forma
deseada; de esta manera, proporcionamos al control en un solo paso la ubicación y tamaño
iniciales.
Dibujemos, a modo de práctica, un control Button sobre el formulario, con un aspecto
similar al mostrado en la
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 166
Un control, al igual que un formulario, dispone a su alrededor de un conjunto de guías de
redimensión, de modo que si después de situarlo en el formulario, queremos modificar su
tamaño, sólo tenemos que hacer clic sobre alguna de estas guías, y arrastrar modificando las
dimensiones del control.
Además de utilizando el ratón, podemos desplazar un control, manteniendo
pulsada la tecla[CONTROL], y pulsando además, algunas de las teclas de dirección.
Ajuste de la cuadrícula de diseño del formulario
La cuadrícula de diseño del formulario, consiste en el conjunto de líneas de puntos
que surcan la superficie del formulario, y nos sirven como ayuda, a la hora de realizar
un ajuste preciso de un control en una posición determinada.
Si el lector ya ha realizado algunas prácticas situando controles en el formulario, se percatará
de que cuando movemos un control con el ratón, dicho control se ajusta a la cuadrícula
obligatoriamente, por lo que no podemos ubicarlo entre dos líneas de puntos de la cuadrícula.
Para solventar este problema tenemos algunas soluciones que proponemos a continuación:
La más simple y directa, consiste en acceder a la ventana de propiedades del
formulario, y en la propiedad GridSize, cambiar los valores de espaciado de puntos que
tiene la rejilla. Cuanto menor sea ese valor, más junta estará la trama de puntos de la
rejilla, con lo que podremos ajustar de forma más exacta el control. Este ajuste es válido
sólo para el formulario sobre el que lo aplicamos. Probemos por ejemplo, a introducir 5 en
cada valor, como muestra la Figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 167
Cambiando el tamaño de la cuadrícula de diseño del formulario.
El otro modo consiste en asignar en el formulario, a la propiedad SnapToGrid, el valor
False; esto deshabilita el ajuste a la cuadrícula automático de los controles, con lo que
perdemos en precisión de ajuste, pero ganamos en libertad de ubicación para el control.
Si no queremos que la cuadrícula se visualice, asignaremos False a la propiedad DrawGrid
del formulario.
Los anteriores ajustes los podemos realizar también de modo genérico para todos los
formularios. Seleccionaremos para ello, la opción de menú del IDE Herramientas +
Opciones, y en la ventana Opciones, haremos clic sobre el elemento Diseñador de
Windows Forms. En el panel derecho de esta ventana, podremos configurar estas
propiedades de modo general para todo el IDE. Ver Figura
Ajuste general de las propiedades para la cuadrícula de diseño de
formularios.
Organización-formato múltiple de controles
Cuando tenemos un grupo numeroso de controles en el formulario, que necesitamos
mover de posición, o cambiar su tamaño, para redistribuir el espacio; podemos optar por
cambiar uno a uno los controles, tarea pesada y nada aconsejable; o bien, podemos
seleccionar todos los controles a modificar, y realizar esta tarea en un único paso,
mediante las opciones del menú Formato del IDE. Supongamos que en el formulario
tenemos dos controles Button y un ListBox distribuidos como muestra la Figura
En primer lugar, para seleccionarlos todos, debemos hacer clic sobre el formulario y
arrastrar, de modo que el rectángulo de selección que aparece, abarque a los controles,
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 168
que quedarán con sus correspondientes marcas de redimensión visibles, señal de que están
seleccionados.
En este punto, podemos hacer clic en uno de los controles y desplazarlos todos
conjuntamente por el formulario, o bien, hacer clic en una de las guías de redimensión y
cambiar su tamaño, lo que afectará a todos los controles seleccionados. Si necesitamos
de alguna acción especial, utilizaremos las opciones del menú Formato del IDE.
Por ejemplo, podemos ejecutar la opción Formato + Alinear + Lados izquierdos, de modo
que todos los controles se alinearán por la izquierda, tomando como referencia el control que
tiene las marcas de redimensión negras. Ver Figura
Después ejecutaremos la opción de menú Formato + Igualar tamaño + Ambos, que
ajustará tanto el ancho como el alto de todos los controles seleccionados. Ver Figura
Igualando tamaño de controles.
Para evitar que, una vez completado el diseño y ajuste de todos lo controles, accidentalmente
podamos modificar alguno, seleccionaremos la opción de menú Formato + Bloquear
controles, que bloqueará
los controles seleccionados, impidiendo que puedan ser movidos o modificado su
tamaño. Para desbloquear los controles del formulario, debemos seleccionar al menos uno
y volver a utilizar esta opción de menú, que desbloqueará todos los controles.
Una característica interesante del bloqueo de controles, consiste en que una vez que
tengamos bloqueados los controles del formulario, si añadimos un nuevo control, este
no estará inicialmente bloqueado, lo que facilita su diseño. Una vez que hayamos finalizado
de diseñar el último control, lo seleccionaremos en el formulario y seleccionaremos la
opción de bloqueo de controles, de modo que ya estarán bloqueados todos de nuevo.
El menú Formato de [Link] consta de un numeroso conjunto de opciones. Acabamos
de ver una muestra de sus posibilidades, por lo que recomendamos al lector, que realice
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 169
pruebas con el resto de opciones, para ver todas las posibilidades en cuanto a la
disposición de los controles dentro del formulario.
Para ilustrar mejor la funcionalidad que podemos obtener de Windows tenemos la
figura 4.1, que resume los principales objetos usados en Windows, para lo cual se
parte de la clase base llamada “System”, luego se muestran algunos de los objetos
de la clase “Drawing” y de la clase “WinForms” anteriormente comentadas.
Figura 3.1: Modelo de Objetos para Windows
Windows
Forms
Form
TextBox
Cabe comentar que dentro de la clase Windows encontramos definido el formulario
Cipboard
y los controles para Windows (Label, Button, TextBox, Menu, etc), así como también
algunos objetos no visuales de utilidad como Application (reemplaza al objeto App
Screen
de VB6), Clipboard, Help, Screen, etc.
5-2-Controles Windows Basicos
[Link] Formulario
El objeto Formulario es el contenedor principal de toda aplicación para Windows y
se encuentra en el siguiente NameSpace:
“[Link]”
En Visual Studio .NET el formulario ha sufrido muchos cambios, tanto en propiedades,
métodos y eventos, tal como se muestra en los siguientes cuadros:
Propiedades
Propiedad
Descripción
Autoscroll Es una nueva propiedad que permite desplazarse por el
formulario a través de una barra si es que los controles
sobrepasan el área cliente.
Backcolor Especifica el color de fondo del formulario.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 170
BackgroundImag Antes llamada Picture. Permite mostrar una imagen de fondo
e sobre el formulario, tiene 2 tamaños: cascada y centrado en
pantalla.
BorderStyle Controla la apariencia del borde del formulario y los controles
que se presentan en la barra de título. Tiene 6 opciones.
ControlBox Si esta en True muestra el menú de controles de la barra de
título, si esta en False no los muestra.
Cursor Especifica el cursor que aparecerá al situar el mouse sobre el
formulario. Antes era la propiedad MousePointer y si se quería
un cursor personalizado se configuraba MouseIcon, ahora solo
existe Cursor y sus gráficas son vistas en la lista.
Font Configura la fuente de los textos de los controles ubicados en
el formulario y de los textos mostrados con métodos de dibujo.
Forecolor Especifica el color del texto de los controles (excepto el
TextBox) y de los textos mostrados con métodos de dibujo.
GridSize Determina el tamaño de las rejillas que se muestran en tiempo
de diseño para diseñar controles.
Icon Indica el icono del formulario, este se muestra en la barra de
título de la ventana y en la barra de tareas de Windows.
IsMDIContainer Determina si es que el formulario es un MDI, antes se creaba
un formulario MDI añadiéndolo del menú “Project” y un
formulario hijo configurando la propiedad MDIChild en True.
Ahora solo se configura para ambos la propiedad
IsMDIContainer.
Location Indica la posición del formulario con respecto a la esquina
superior izquierda de la pantalla. Antes había que configurar la
propiedad Top y Left, ahora los valores de X e Y.
Opacity Es una nueva propiedad, que indica la forma de visualización
del formulario, que puede ser desde opaco (100%) hasta
transparente (0%). Antes para hacer transparente se usaba la
API SetWindowRgn
RightToLeft Determina la alineación de los textos con respecto a sus
controles, por defecto es No, es decir se alinean de izquierda a
derecha; si es True se alinearán de derecha a izquierda.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 171
Size Configura el tamaño del formulario en píxeles.
StartPosition Indica la posición en que aparecerá por primera vez el
formulario con respecto a la pantalla. Tiene 5 opciones.
Text Permite mostrar el texto de la barra de título en el formulario.
TopMost Posiciona en primer plano la ventana, siempre y cuando no este
desactivada. Antes se podía hacer esto con la API
WindowsOnTop.
WindowState Determina la forma en que se presentará la ventana, puede ser
Normal, Minimizada o Maximizada.
Métodos
Método
Descripción
Activate Activa el formulario y le da el foco.
ActivateControl Activa un control del formulario.
Close Cierra un formulario descargándolo de la memoria.
Focus Pone el foco sobre el formulario.
Hide Oculta el formulario, sin descargarlo de la memoria.
Refresh Repinta el formulario y sus controles.
SetLocation Ubica el formulario en una cierta posición de la pantalla.
SetSize Configura el tamaño de la ventana en píxeles.
Show Muestra un formulario como ventana no modal (modeles).
ShowDialog Muestra un formulario como ventana modal (modal).
Eventos
Evento
Descripción
Activated Ocurre al activarse el formulario.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 172
Click Se desencadena al dar clic con el mouse sobre el formulario.
Closed Se habilita al cerrar el formulario. Es similar al evento Unload
de Visual Basic 6.
Closing Ocurre mientras se está cerrando el formulario. Es similar al
evento QueryClose de Visual Basic 6. También se puede
cancelar la salida.
Deactivated Ocurre al desactivarse el formulario.
DoubleClick Se desencadena al dar doble clic con el mouse sobre el
formulario.
GotFocus Ocurre al ingresar el foco sobre el formulario.
Load Se produce al cargar los controles sobre el formulario
LostFocus Ocurre al salir el foco del formulario.
MouseEnter Se habilita al ingresar el mouse sobre el área cliente del
formulario.
MouseLeave Se habilita al salir el mouse del área cliente del formulario.
MouseMove Se desencadena al pasar el mouse sobre el formulario.
Move Este evento se habilita al mover la ventana o formulario.
Paint Ocurre al pintarse la ventana en pantalla.
Resize Ocurre cada vez que se modifica de tamaño el formulario.
5.2.2.- Control Label
El control Label o Etiqueta, muestra un texto informativo al usuario. Podemos utilizar
este control como complemento a otro control, por ejemplo, situándolo junto a un
TextBox, de modo que indiquemos al usuario el tipo de dato que esperamos que
introduzca en la caja de texto.
Se trata de un control estático; esto quiere decir que el usuario no puede interaccionar
con él, a diferencia, por ejemplo, de un control Button, sobre el que sí podemos actuar
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 173
pulsándolo; o de un TextBox, en el que podemos escribir texto.
Una de sus propiedades es BorderStyle, que permite definir un borde o recuadro alrededor
del control, o que dicho borde tenga un efecto 3D; por defecto se muestra sin borde. Veamos
unos ejemplos en la Figura
Controles Label.
Propiedades
Propiedad
Descripción
Anchor Es una nueva propiedad que permite ajustar el ancho del
control.
AutoSize Ajusta el texto de la etiqueta al tamaño del control.
Backcolor Especifica el color de fondo de la etiqueta.
BorderStyle Controla la apariencia del borde de la etiqueta. Tiene 3
opciones.
Cursor Especifica el cursor que aparece al situar el mouse sobre la
etiqueta.
Dock Da la posibilidad de acoplar la etiqueta a un lado del
contenedor, puede ser arriba, abajo, izquierda, derecha o al
centro.
Enabled Habilita o deshabilita la etiqueta.
Font Configura la fuente del texto de la etiqueta.
Forecolor Especifica el color del texto de la etiqueta.
Location Indica la posición de la etiqueta con respecto a su contenedor.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 174
Locked Bloquea el control para que no se mueva o modifique de
tamaño.
RightToLeft Determina la alineación del texto con respecto al control.
Size Configura el tamaño del control en píxeles.
Text Visualiza el texto de la etiqueta.
TextAlign Alinea el texto hacia el control, sea: izquierda, derecha o centro.
Visible Visualiza o no el control.
Métodos
Método
Descripción
FindForm Devuelve el formulario en el que se encuentra el control.
Focus Pone el foco sobre la etiqueta.
Hide Oculta la etiqueta, sin descargarla de la memoria.
Refresh Repinta la etiqueta.
SetLocation Ubica la etiqueta en una cierta posición de la pantalla.
SetSize Configura el tamaño de la etiqueta.
Show Pone visible la etiqueta.
Eventos
Evento
Descripción
Click Se desencadena al dar clic con el mouse sobre la etiqueta.
DoubleClick Se desencadena al dar doble clic con el mouse sobre la
etiqueta.
GotFocus Ocurre al ingresar el foco sobre el control.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 175
LostFocus Ocurre al salir el foco del control.
MouseEnter Se habilita al ingresar el mouse sobre la etiqueta.
MouseLeave Se habilita al salir el mouse de la etiqueta.
MouseMove Se desencadena al pasar el mouse sobre la etiqueta.
5.2.3.-Control TextBox
Un control TextBox muestra un recuadro en el que podemos introducir texto. Para poder
escribir texto en un control de este tipo, debemos darle primeramente el foco, lo que
detectaremos cuando el control muestre el cursor de escritura en su interior.
Entre las propiedades disponibles por este control, destacaremos las siguientes.
Control TextBox
Propiedades
Este control tiene propiedades similares al control Label, entre aquéllas propiedades
exclusivas de este control tenemos:
Propiedad
Descripción
Autosize Cuando esta propiedad tenga el valor True, al modificar el tamaño del
tipo de letra del control, dicho control se redimensionará
automáticamente, ajustando su tamaño al del tipo de letra establecido.
CharacterCasing Nueva propiedad que convierte a mayúsculas o minúsculas el texto.
Enable Contiene un valor lógico mediante el que indicamos si el control está o
No habilitado para poder escribir texto sobre él.
Font Cambia el tipo de letra y todas las características del tipo elegido.
Lines Muestra el contenido de cada línea del texto.
MaxLength Determina el número de caracteres que se pueden ingresar en éste.
MultiLine Si es True se pueden escribir varias líneas de texto.
PasswordChar Señala el carácter que aparecerá como mascara de entrada.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 176
ReadOnly Indica que el control solo se puede ver pero no editar. Antes se
llamaba Locked.
ScrollBars Habilita las barras de desplazamiento si el control es multilínea.
Text Cadena con el texto del control.
WordWrap Cambia de línea al llegar al final de un texto multilínea.
Métodos
Método
Descripción
AppendText Añade texto al final del texto actual.
Clear Borra el contenido del cuadro de texto.
Copy Copia el texto y lo envía al portapapeles.
Cut Corta el texto y lo envía al portapapeles.
Paste Pega el texto del portapapeles al cuadro.
ResetText Inicializa el texto.
Select Selecciona el texto.
Undo Deshace el último cambio en el texto.
Eventos
Evento
Descripción
KeyDown Ocurre al pulsar hacia abajo una tecla extendida.
KeyPress Ocurre al pulsar una tecla normal. También se desencadena
antes el evento KeyDown y después el evento KeyUp.
KeyUp Ocurre al soltar una tecla extendida previamente pulsada.
TextChanged Es un nuevo evento que reemplaza al evento change, es decir
ocurre al cambiar el texto.
Validated Se habilita después de validarse el control.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 177
Validating Se habilita cuando el control está validándose.
La Figura muestra un formulario con varios controles TextBox, a los cuales se han
aplicado diferentes efectos mediante sus propiedades.
Pruebas con controles TextBox.
Al comenzar a ejecutar el programa, observaremos que el foco de entrada no está situado
en el primer TextBox del formulario. Para asignar por código el foco a un determinado
control, disponemos del método Focus( ). En este caso, al pulsar el botón Foco nombre,
desviamos el foco al primer TextBox del formulario. Ver Código fuente
Private Sub btnFoco_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link]()
End Sub
Observe el lector, que en el botón Foco nombre, que acabamos de mencionar, la letra F se
encuentra subrayada, actuando de acelerador o hotkey. De este modo, no es necesario
pulsar con el ratón sobre ese botón para ejecutarlo, basta con pulsar la tecla
[CONTROL] junto a la letra subrayada para conseguir el mismo efecto.
Para definir una tecla aceleradora en un control, debemos anteponer el carácter & a la letra
que vamos a definir como acelerador, en este ejemplo se ha logrado con &Foco nombre.
Por otro lado, mediante el botón btnSoloLectura conseguimos activar/desactivar la
propiedad ReadOnly del TextBox txtNombre, cambiando el estado de dicha propiedad
en cada pulsación del botón. Ver Código fuente
Private Sub btnSoloLectura_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
If ([Link]) Then
[Link] = False
Else
[Link] = True
End If
End Sub-
Sin embargo, hay otro modo mucho más eficiente de cambiar el estado de una propiedad que
contiene un tipo Boolean: utilizando el operador Not.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 178
Con el botón btnActivar, cambiamos el valor de la propiedad Enabled del cuadro de texto que
contiene los apellidos. Para ello, aplicamos el operador Not a dicha propiedad, y el resultado
lo asignamos a esa misma propiedad. Ver Código fuente
Private Sub btnActivar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' utilizando operador Not simplificamos
[Link] = Not ([Link])
End Sub
Finalizando con este ejemplo, y aunque no tiene relación directa con el control TextBox, el
formulario se muestra con un tipo de borde especial que no permite su redimensión. La
propiedad del formulario con la que podemos establecer el tipo de borde es
FormBorderStyle, y en este caso, su valor es Fixed3D. Alterando los valores de esta
propiedad, conseguiremos distintos bordes y tipos de redimensión para el formulario.
Selección de texto en un TextBox
La selección de texto en un control TextBox es un proceso que funciona de modo
transparente al programador, en el sentido en que este no necesita añadir código
adicional para las operaciones de selección, cortar, copiar, etc., al ser tareas integradas en
el sistema operativo. Sin embargo, podemos necesitar en un determinado momento,
tener información acerca de las operaciones de selección que está realizando el usuario
en nuestros controles de texto. Para ello, el control TextBox dispone de las siguientes
propiedades.
SelectionStart. Posición del texto del control, en la que comienza la selección
que hemos realizado.
SelectionLength. Número de caracteres seleccionados en el control.
SelectedText. Cadena con el texto que hemos seleccionado en el control.
Mediante estas propiedades, no sólo averiguamos la selección que pueda tener un control
TextBox, sino que también podemos utilizarlas para establecer por código una
selección; teniendo el mismo efecto que si la hubiera efectuado el usuario con el ratón o
teclado.
Para comprobar el funcionamiento de las propiedades de selección del TextBox,
crearemos un proyecto Windows, y en su formulario añadiremos varios controles para
manipular la selección de texto que hagamos en un TextBox. La Figura muestra el
formulario del ejemplo.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 179
. Formulario para realizar selección en el control TextBox
El control de este formulario, que vamos a emplear para las operaciones de selección es
txtOrigen. En primer lugar, y aunque no se trata de una selección de texto, veremos su evento
TextChanged, el cual se produce cada vez que cambia el contenido del cuadro de texto; lo
usaremos por tanto, para contar lacantidad de caracteres escritos y mostrarlos en un Label.
Ver Código fuente
' al cambiar el texto del control se produce este evento
Private Sub txtOrigen_TextChanged(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
' calculamos la longitud del texto escrito
[Link] = [Link]
End Sub
Los eventos MouseMove y KeyDown del TextBox, se producen respectivamente, cuando
movemos el ratón sobre el control, o cada vez que pulsamos una tecla para escribir texto.
Detectaremos en este caso, si existen teclas o botones especiales presionados, que nos
indiquen que se está realizando unaselección de texto, y mostraremos en el formulario el
texto seleccionado, el número de caracteres y la posición del carácter de inicio de la
selección. Veamos los procedimientos manipuladores de estos eventos en el Código fuente
' al mover el ratón por el TextBox se produce este evento
Private Sub txtOrigen_MouseMove(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
' comprobamos si al mover el ratón está pulsado su botón izquierdo
' en caso afirmativo es que se está seleccionando texto, por lo que obtenemos la
' información de selección con las ' propiedades de selección del TextBox
If [Link] Then
[Link] = [Link]
[Link] = [Link]
[Link] = [Link]
End If
End Sub
' este evento se produce cuando se pulsa una tecla en el TextBox
Private Sub txtOrigen_KeyDown(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
' comprobamos las teclas pulsadas si está pulsada la tecla mayúsculas, y además
' se está pulsando la tecla flecha derecha, quiere decir que se está seleccionando
' texto ; obtener la información de las propiedades de selección del control TextBox
If [Link] Then
If [Link] Then
[Link] = [Link]
[Link] = [Link]
[Link] = [Link]
End If
End If
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 180
Finalmente, tras introducir un valor en los controles txtPosicion y txtLongitud,
pulsaremos el botón btnSeleccionar. Con ello conseguiremos realizar una selección de
texto en el TextBox txtOrigen, y pasar el texto seleccionado al control txtDestino. El
efecto será el mismo que si lo hubiera realizado el usuario, pero en este caso sin su
intervención. Veamos en el Código fuente, el evento Click del botón btnSeleccionar.
' al pulsar este botón, seleccionar por código texto del control txtOrigen y
' pasarlo al control txtDestino
Private Sub btnSeleccionar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link] = [Link]
[Link] = [Link]
[Link] = [Link]
End Sub
La Figura muestra este ejemplo en ejecución.
Pruebas de selección de texto con el control TextBox
5.2.4.-Control Button
Este control representa un botón de pulsación, conocido en versiones anteriores de
VB como CommandButton. Entre el nutrido conjunto de propiedades de este
control, destacaremos las siguientes.
Propiedades
Este control también tiene propiedades similares al control Label, entre aquéllas
propiedades exclusivas y nuevas de esta versión, tenemos:
Propiedad
Descripción
Cursor Permite modificar el cursor del ratón que por defecto tiene el botón.
Font Cambia el tipo de letra y todas las características del tipo
Name elegido, para e l t ex t o del boton
Generalmente usaremos el prefijo btn.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 181
BackgroundImag Especifica la imagen de fondo que usará el botón.
e
DialogResult Determina el valor del formulario padre si se da clic sobre el
botón.
FlatStyle Determina el estilo o apariencia del control. Tiene 3 valores.
Image Imagen que se mostrará en el control.
ImageAlign Alineación de la imagen dentro del control. Tiene 9 opciones.
Text Cadena con el título del botón.
TextAlign. Alineación o disposición del título dentro del área del botón; por
defecto aparece centrado.
Métodos
Método
Descripción
NotifyDefault Indica si el botón será el control por defecto. Es de tipo lógico.
PerformClick Ejecuta el evento clic del botón.
Eventos
Evento
Descripción
Click Se desencadena al dar clic con el mouse sobre la etiqueta.
GotFocus Ocurre al ingresar el foco sobre el botón.
LostFocus Ocurre al salir el foco del botón.
MouseEnter Se habilita al ingresar el mouse sobre el botón.
MouseLeave Se habilita al salir el mouse del botón.
MouseMove Se desencadena al pasar el mouse sobre el botón.
La Figura muestra un ejemplo de control Button, sobre el que se han modificado algunos
valores por defecto de sus propiedades.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 182
5.2.5.-Control ListBox
Un control ListBox contiene una lista de valores, de los cuales, el usuario puede
seleccionar uno o varios simultáneamente. Entre las principales propiedades de este
control, podemos resaltar las siguientes.
Items. Contiene la lista de valores que visualiza el control. Se trata de
un tipo [Link], de manera que el contenido de la lista puede ser
tanto tipos carácter, como numéricos y objetos de distintas clases. Al seleccionar esta
propiedad en la ventana de propiedades del control, y pulsar el botón que contiene,
podemos introducir en una ventana elementos para el control. Ver Figura
Introducción de valores para un ListBox en tiempo de diseño.
El control quedaría por lo tanto con valores asignados en la etapa de diseño, como
muestra la Figura
ListBox en diseño con valores en su lista.
Sorted. Cuando esta propiedad contiene el valor True, ordena el contenido de la lista.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 183
Cuando contiene False, los elementos que hubiera previamente ordenados, permanecen
con dicho orden, mientras que los nuevos no serán ordenados.
IntegralHeight. Los valores de la lista son mostrados al completo cuando esta propiedad
contiene True. Sin embargo, al asignar el valor False, según el tamaño del control, puede
que el último valor de la lista se visualiza sólo en parte. La Figura 253 muestra un ListBox
con esta propiedad a False.
ListBox mostrando parte del último elemento debido a la propiedad IntegralHeight.
Propiedades
Propiedad
Descripción
Name Generalmente usaremos el prefijo lst.
ColumnWidth Indica el ancho de cada columna en una lista de varias
columnas.
HorizontalExtent Indica el ancho mínimo en píxeles que se requiere para que
aparezca la barra horizontal.
HorizontalScrollbar Muestra u oculta la barra de desplazamiento horizontal de la
lista.
IntegralHeight Determina que las opciones de la lista se vean en forma
completa.
ItemHeight Devuelve el alto en píxeles de cada elemento de la lista.
Items Es la principal propiedad y se refiere a los elementos de la lista.
MultiColumn Indica si los elementos se pueden ver en varias columnas.
ScrollAlwaysVisible Visualiza siempre las 2 barras de desplazamiento.
SelectionMode Determina la forma de selección que puede ser: None
(ninguno), One (uno), MultiSimple (varios con click) y
MultiExtended (varios con shift + click o ctrl + click).
Sorted Ordena la lista en forma ascendente.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 184
SelectedIndex Devuelve o establece el índice del elemento seleccionado.
SelectedItem Devuelve el ítem seleccionado de la lista.
Métodos
Método
Descripción
FindString Devuelve el índice de un elemento buscado en una lista. Si no
existe devuelve -1 y si existe devuelve un número mayor que -1.
FindStringExact Realiza una labor similar al método anterior pero compara con
exactitud la cadena.
GetSelected Devuelve true si un elemento ha sido seleccionado o false si no.
InsertItem Inserta un elemento en una cierta posición de la lista.
Eventos
Evento
Descripción
DoubleClick Ocurre al dar dos veces clic sobre la lista.
SelectedIndexChange Ocurre al cambiar el índice del elemento seleccionado.
d
Colección Items
Para trabajar con los elementos de una lista se hace uso de la colección Items, la
cual se detalla a continuación:
Propiedades
Propiedad
Descripción
All Devuelve un objeto con todos los elementos de la lista.
Count Devuelve el número de elementos de la lista.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 185
Métodos
Método
Descripción
Add Añade un elemento al final de la lista.
Clear Borra todos los elementos de la lista.
Insert Inserta un elemento en la posición indicada por el índice.
Remove Elimina un elemento de la lista de acuerdo a su índice.
En resumen:
[Link](dato): Inserta un elemento al final del listbox.
[Link](): Elimina todos los elementos de la lista.
listBox1. [Link](): Regresa la cantidad de elementos en lista.
listBox1. [Link] = true; Ordena los elementos de la lista usada solo al tiempo de
diseno.
[Link](dato): Regresa true o false, si el dato se encuentra o no se
encuentra en la lista.
listBox1. [Link](dato): Regresa el indice del objeto dentro del listbox.
[Link](indice,dato): Inserta el dato en la posicion indicada.
[Link](dato): Elimina el dato de el listbox.
listBox1. [Link](indice): Elimina el dato que esta en la posicion indicada.
[Link][indice]: get or set el dato en la posicion indicada
Para mostrar algunas de las funcionalidades de este control, utilizaremos el proyecto
de ejemplo ListBoxPru. La Figura muestra esta aplicación en ejecución.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 186
Ejemplo de uso del control ListBox.
El ejemplo, como puede comprobar el lector, consiste en un formulario que contiene
un ListBox principal, con el nombre lstValores, que dispone de una serie de valores
asignados en tiempo de diseño.
Cada vez que hacemos clic en alguno de los valores, se produce el evento
SelectedIndexChanged, que utilizamos para mostrar en este caso, el nombre del elemento en
el título del formulario, como muestra el Código fuente, de la clase frmListas, correspondiente
al formulario.
' declaramos esta constante a nivel de clase, para poner como título
' del formulario junto al elemento seleccionado de la lista
Public Const TITULO As String = "Elemento seleccionado: "
' este evento se produce cada vez que se cambia el índice seleccionado del ListBox
Private Sub lstValores_SelectedIndexChanged(ByVal sender As [Link],
ByVal e As [Link]) Handles [Link]
' mostrar en el título del formulario el valor actualmente seleccionado de la lista
[Link] = TITULO & [Link]
End Sub
A través de los RadioButton, cambiamos el tipo de selección que podemos efectuar en
el control lstValores. Ver Código fuente
Private Sub rbtUno_CheckedChanged(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' establecer tipo de selección en el ListBox a un elemento
[Link] = [Link]
End Sub
Private Sub rbtMultiple_CheckedChanged(ByVal sender As [Link], ByVal e
As [Link]) Handles [Link]
' establecer tipo de selección en el ListBox a un múltiples elementos
[Link] = [Link]
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 187
Private Sub rbtExtendida_CheckedChanged(ByVal sender As [Link], ByVal
e As [Link]) Handles [Link]
' establecer tipo de selección en el ListBox a múltiples
' elementos de modo extendido
[Link] = [Link]
End Sub
Mediante los controles chkOrdenar y chkColumnas, ordenaremos y mostraremos en
columnas respectivamente el ListBox. Ver Código fuente.
Private Sub chkOrdenar_CheckedChanged(ByVal sender As [Link], ByVal e
As, [Link]) Handles [Link]
' según el valor del CheckBox, ordenamos o quitamos
' la opción de ordenar del ListBox
[Link] = [Link]
End Sub
Private Sub chkColumnas_CheckedChanged(ByVal sender As [Link], ByVal
e As [Link]) Handles [Link]
' según el valor del CheckBox, mostramos el ListBox
' en varias columnas o en una
[Link] = [Link]
End Sub
El TextBox de este formulario lo usaremos para añadir nuevos elementos al ListBox
lstValores, y buscar también elementos existentes, pulsando los botones btnAgregar y
btnBuscar en cada caso. Observemos el miembro NoMatches del ListBox, mediante el
que averiguamos si la búsqueda tuvo éxito. Ver el Código fuente
Private Sub btnAgregar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' añadimos el contenido del TextBox como un elemento a la lista
[Link]([Link])
End Sub
Private Sub btnBuscar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim iPosicion As Integer
' el método FindString() de la lista busca un valor
iPosicion = [Link]([Link])
' el campo NoMatches indica si no existe el valor buscado
If iPosicion = [Link] Then
[Link]("No existe el valor")
Else
' si encontramos el valor en la lista,lo seleccionamos por código
[Link] = iPosicion
End If
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 188
End Sub
La selección de los elementos de un ListBox no es competencia exclusiva del usuario. El
programador puede también, si lo necesita, seleccionar valores de la lista mediante el
código del programa. Al pulsar el botón btnSelecCod, utilizaremos el método SetSelected(
) del ListBox para realizar esta tarea.
En este método pasamos como parámetro el índice de la lista con el que vamos a operar,
y el valor True para seleccionarlo, o False para quitarle la selección. Ver el Código fuente
Private Sub btnSelecCod_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' para seleccionar elementos de un ListBox por código
' podemos utilizar el método SetSelected()
[Link] = True
[Link](1, True)
[Link](3, True)
[Link](5, True)
End Sub
El botón btnTraspasarSelec lo usaremos para tomar los elementos seleccionados de
lstValores, y pasarlos al otro ListBox del formulario. La propiedad SelectedItems del
control lstValores, devuelve una colección con sus elementos seleccionados. Por otra
parte, podemos eliminar los elementos de un ListBox llamando al método Clear( ) de
la colección de valores del control, cosa que hacemos pulsando el botón btnLimpiar.
Ver Código fuente
Private Sub btnTrapasarSelec_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim oSeleccion As [Link]
' obtenemos con SelectedItems los elementos seleccionados de un ListBox
oSeleccion = [Link]
' si existen elementos seleccionados, los traspasamos a otro ListBox del
' formulario
If [Link] > 0 Then
Dim oEnumerador As IEnumerator
oEnumerador = [Link]()
While [Link]()
[Link]([Link])
End While
End If
End Sub
Private Sub btnLimpiar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' con el método Clear() de la colección de elementos
' de un ListBox, borramos los elementos del controls
[Link]()
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 189
End Sub
Ejemplo programa
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link]([Link])
[Link] = ""
End Sub
Private Sub Button2_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim r, cant, meses As Integer
cant = [Link]
For r = 0 To cant - 1
meses = [Link](r)
meses = meses * 12
[Link](r) = meses
Next r
End Sub
Recordar que el primer indice en un ListBox es el cero por eso el ciclo va desde el cero hasta
la cantidad de elementos menos uno.
Corrida:
Actividades de reforzamiento de lo aprendido
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 190
EJERCICIOS PROGRAMACION DE LISTBOX
1.- Capturar en una lista los sueldos de 6 empleados y desplegarlos en una segunda lista
aumentados en un 30%
2.- Capturar en una lista los pesos en kilogramos de 6 personas desplegarlos en una segunda
lista convertidos a libras y ademas solo los mayores de 100 libras.
3.- Capturar en sus 4 listas respectivas matricula, nombre y dos calificaciones de 5 alumnos,
despues calcular una lista de promedios de calificaciones.
4.- Capturar en sus listas respectivas numempleado, nomempleado, dias trabajados y sueldo
diario de 5 empleados, desplegar en otra pantalla o panel la nomina pero solo de aquellos
empleados que ganan mas de $300.00 a la semana.
5.2.6.-Control ComboBox
El ComboBox es un control basado en la combinación (de ahí su nombre) de dos
controles que ya hemos tratado: TextBox y ListBox.
Un control ComboBox dispone de una zona de edición de texto y una lista de valores,
que podemos desplegar desde el cuadro de edición.
El estilo de visualización por defecto de este control, muestra el cuadro de texto y la
lista oculta, aunque mediante la propiedad DropDownStyle podemos cambiar dicho estilo.
La Figura muestra un formulario con diversos ComboBox, cada uno con diferente estilo.
Controles ComboBox de distintos estilos.
La propiedad DropDownStyle también influye en una diferencia importante de
comportamiento entre el estilo DropDownList y los demás, dado que cuando creamos un
ComboBox con el mencionado estilo, el cuadro de texto sólo podrá mostrar información, no
permitiendo que esta sea modificada.
En el caso de que la lista desplegable sea muy grande, mediante la propiedad
MaxDropDownItems, asignaremos el número de elementos máximo que mostrará la lista del
control.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 191
El resto de propiedades y métodos son comunes con los controles TextBox y ListBox.
En el Código fuente se muestra el código del botón btnAgregar, mediante el que
llenamos de valores los controles de este ejemplo.
Private Sub btnAgregar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link](New String() {"AZUL", "VERDE", "AMARILLO",
"ROJO", "BLANCO", "MARRÓN", "GRANATE"})
[Link](New String() {"ELENA", "JOSE", "ANA",
"ALFREDO", "LUIS", "ANGEL", "RAQUEL"})
[Link](New String() {"SEVILLA", "VALENCIA",
"ALICANTE", "TOLEDO", "SEGOVIA"})
End Sub
Propiedades de ComboBox
Propiedad
Descripción
Name Generalmente usaremos el prefijo cbo.
Items Es la principal propiedad y se refiere a los elementos del
combo.
MaxDropDownItem Indica el máximo número de elementos que se mostrarán al
s desplegarse el combo.
MaxLenght Determina el máximo número de caracteres que se podrán
escribir en el cuadro de texto del combo.
Sorted Ordena los elementos del combo en forma ascendente.
Style Especifica el tipo de combo que puede ser: Simple, DropDown
(por defecto), y DropDownList.
SelectedIndex Devuelve o establece el índice del elemento seleccionado.
SelectedItem Devuelve el ítem seleccionado de la lista.
SelectedText Devuelve el texto seleccionado de la lista.
Text Se refiere al texto escrito en el cuadro del combo.
Métodos
Método
Descripción
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 192
FindString Devuelve el índice de un elemento buscado en el combo. Si no
existe devuelve -1 y si existe devuelve un número mayor que -1.
FindStringExact Realiza una labor similar al método anterior pero compara con
exactitud la cadena.
Eventos
Evento
Descripción
Click Ocurre al dar clic con el mouse a un elemento de la lista.
DoubleClick Se da al dar dos veces clic sobre un elemento de la lista.
SelectedIndexChanged Ocurre al cambiar el índice del elemento seleccionado.
SelectionChangeCommi Se da cuando se selecciona un elemento del combo.
ted
TextChanged Ocurre al cambiar la propiedad Text del combo.
Colección Items
La colección Items del combo es similar a la del ListBox.
Propiedades
Propiedad
Descripción
All Devuelve un objeto con todos los elementos del combo.
Count Devuelve el número de elementos del combo.
Métodos
Método
Descripción
Add Añade un elemento al final del combo.
Clear Borra todos los elementos del combo.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 193
Insert Inserta un elemento en la posición indicada por el índice.
Remove Elimina un elemento del combo de acuerdo a su índice.
Ejemplo de del uso de ComboBox(). Ahora empecemos creando un nuevo proyecto de
Visual Basic. Necesitamos las siguientes herramientas: 2 LABEL, 2 TEXEDIT, 3
BOTONES y un COMBOBO Cuando arrastres estos componentes, trate de que tu
formulario tenga este aspecto
Primero aprenderemos a insertar un nuevo ítem, hacemos doble clic en el botón INSERTAR
Ahora en medio de la función BUTTON1_CLICK antes de END SUB escribimos el
siguiente código que sirve para agregar nuevos ítems a nuestro componente COMBOBOX1
Private sub [Link]…..
'primero verificamos que en TEXBOX2 no esté vacio
If [Link] > 0 Then
[Link]([Link]) 'adicionamos el item de COMBOX
End If
End Sub
Para editar un ítem de nuestra herramienta COMBOBOX1, hacemos doble clic en el botón
EDITAR, el siguiente código sirve para editar un ítem
Private sub [Link]…..
'primero verificamos que TEXBOX1 y TEXBOX2 no estén vacío
If [Link] > 0 And [Link] > 0 Then
' eliminamos el ítem de la posición TEXBOX1
[Link] (CInt([Link]))
' inserta el Nuevo elemento TEXBOX2
[Link] (CInt([Link]), [Link])
End if
End sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 194
Ahora volvemos al formulario y esta vez hacemos doble clic en el botón3 que es el botón
eliminar, Para eliminar un ítem de la herramienta COMBOBOX escribimos el siguiente
código en la función de nuestro botón Eliminar:
Private sub [Link]…..
'primero verificamos que TEXBOX1 no este vacío
If [Link] > 0 And [Link] > 0 Then
' eliminamos el ítem de la posición TEXBOX1
[Link] (CInt([Link]))
End if
End Sub
Este otro ejemplo siguiente muestra como ingresar una fecha considerando edades entre 17
y 90 años. El botón Comprobar permite mostrar un mensaje si la fecha seleccionada es
Correcta o Incorrecta.
A continuación sigue código en Visual Basic
Private Sub Cargar(ByVal sender As [Link], ByVal e As [Link]) Han
dles [Link]
'Llenar el Día
Dim i As Integer
For i = 1 To 31
[Link](i)
Next
'Llenar los Nombres de los Meses
For i = 1 To 12
[Link](MonthName(i, False))
Next
'Al ingresar el rango para los años existen diferentes posibilidades...
‘consideremos mayores de 18 años hasta las 90 años
For i = Year(Now) - 90 To Year(Now) - 17
[Link](i)
Next
End Sub
Private Sub CompruebaFecha(ByVal sender As [Link], ByVal e As [Link]
ntArgs) Handles [Link]
If [Link] = -1 Or [Link] = -1 Or _
[Link] = -1 Then
[Link]("Faltan datos...", "Fecha incompleta",
[Link])
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 195
Exit Sub
End If
Dim vfecha As String
vfecha = Trim([Link]) & "/" & Trim(Str([Link] + 1))
& "/" & Trim([Link])
If [Link](vfecha) = False Then
[Link]("Fecha no valida...", "Error de ingreso",
[Link])
Else
[Link]("Fecha CORRECTA...", "Dato Válido",
[Link])
End If
End Sub
5.2.7.-Control CheckBox
Este control muestra una casilla de verificación, que podemos marcar para establecer un
estado. Generalmente el estado de un CheckBox es marcado (verdadero) o desmarcado
(falso), sin embargo, podemos configurar el control para que sea detectado un tercer
estado, que se denomina indeterminado, en el cual, el control se muestra con la marca
en la casilla pero en un color de tono gris.
Las propiedades remarcables de este control son las siguientes.
Propiedades
Propiedad
Descripción
Name Generalmente usaremos el prefijo chk.
Appearance Controla la apariencia del control, puede ser: Normal (como
casilla) o Button (como botón de comando).
AutoCheck Cambia de estado cada vez que se da clic al botón.
CheckAlign Controla la alineación del checkbox. Hay 9 posiciones.
Checked Indica si el checkbox ha sido seleccionado o no.
CheckState Devuelve el estado del checkbox, que puede ser: Unchecked (sin
marcar), Checked (marcado) o Indeterminate (gris).
ThreeState Habilita o deshabilita el estado indeterminado del checkbox cada
vez que se da el tercer clic.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 196
Métodos
Método
Descripción
Focus Pone el foco sobre el checkbox.
Hide Oculta el checkbox, sin descargarlo de la memoria.
Show Pone visible el checkbox.
Eventos
Evento
Descripción
CheckedChanged Ocurre al cambiar el valor de la propiedad Checked del control.
CheckStateChange Ocurre al cambiar el valor de la propiedad CheckState del
d control.
Observacion:
Como detalle destacable de las propiedades Checked y CheckState, si modificamos desde
código sus valores, conseguiremos alterar el estado de la casilla del control.
El ejemplo CheckBoxPru, muestra un formulario con dos controles CheckBox.
El control chkPonColor asigna un color de fondo al formulario o restablece el
color original. Esto lo conseguimos codificando el evento CheckedChanged del control.
Ver Código fuente.
' Este evento se produce cuando se hace clic en el CheckBox y cambia el contenido
' de la casilla
Private Sub chkPonColor_CheckedChanged(ByVal sender As [Link], ByVal
e As [Link]) Handles [Link]
If [Link] = [Link] Then
[Link] = [Link]
Else
[Link]()
End If
End Sub
Por su parte, el control chkMostrar, definido con tres estados, muestra, al estar marcado,
una cadena en un control Label; elimina la cadena al desmarcarlo; y muestra la mitad
al entrar en el estado indeterminado. El evento CheckStateChanged es el que debemos de
utilizar para detectar el estado del CheckBox en cada ocasión. Para mantener el valor de la
cadena a mostrar, utilizamos una variable a nivel de la clase que inicializamos en el
constructor del formulario. Ver Código fuente
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 197
Public Class Form1
Inherits [Link]
Private sCadenaOriginal As String
Public Sub New()
'....
' inicializar la variable que contiene la cadena
' a mostrar en el label y asignarla
sCadenaOriginal = "Estamos visualizando una cadena"
[Link] = sCadenaOriginal
End Sub
'....
' este evento se produce cuando cambia el estado de la casilla
Private Sub chkMostrar_CheckStateChanged(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
Select Case [Link]
Case [Link]
[Link] = sCadenaOriginal
Case [Link]
[Link] = ""
Case [Link]
[Link] = [Link](0,([Link] / 2))
End Select
End Sub
La Figura muestra este ejemplo en ejecución.
Controles CheckBox en ejecución.
5.2.8. Control CheckedListBox
Es un nuevo control que antes se obtenía configurando la propiedad style del control
Listbox a checked. Como es similar al control ListBox solo mencionaremos las
características distintas que tiene el control CheckedListBox.
Propiedades
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 198
Propiedad
Descripción
Name Generalmente usaremos el prefijo ckl.
CheckOnClick Establece si el control podrá ser fijado la primera vez al dar click.
ThreeDCheckBox Indica si la apariencia de los items se mostrará en 3D o plano.
Métodos
Método
Descripción
GetItemChecked Devuelve true si un cierto item ha sido seleccionado o false si no.
GetItemCheckState Devuelve el valor de la propiedad CheckState de un cierto item.
SetItemChecked Establece o quita la selección de un cierto elemento.
SetItemCheckState Establece la propiedad CheckState de un cierto elemento.
Eventos
Evento
Descripción
ItemCheck Ocurre al seleccionar un elemento y poner el check en true.
SelectedIndexChange Ocurre al seleccionar otro elemento.
d
5.2.9.-Control RadioButton
Antes conocido como OptionButton, es un control en el que solo se puede
seleccionar uno por contenedor. Los controles RadioButton nos permiten definir
conjuntos de opciones autoexcluyentes, de modo que situando varios controles de este tipo
en un formulario, sólo podremos tener seleccionado uno en cada ocasión.
Propiedades
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 199
Propiedad
Descripción
Name Generalmente usaremos el prefijo rbn.
Appearance Controla la apariencia del control, puede ser: Normal (como
botón de opción) o Button (como botón de comando).
AutoCheck Cambia de estado cada vez que se da clic al botón.
CheckAlign Controla la alineación del botón. Hay 9 posiciones.
Checked Indica si el botón ha sido seleccionado o no.
Métodos
Método
Descripción
Focus Pone el foco sobre el radiobutton.
Hide Oculta el radiobutton, sin descargarlo de la memoria.
Show Pone visible el radiobutton.
Eventos
Evento
Descripción
CheckedChange Ocurre al cambiar la propiedad checked del radiobutton.
d
Click Se desencadena al dar clic con el mouse sobre el botón.
DoubleClick Se desencadena al dar doble clic con el mouse sobre el botón.
5.2.10-Control GroupBox
Antes conocido como Frame, es un contenedor que se utiliza para agrupar varias opciones,
que pueden ser: de opción única como los RadioButton o de opción múltiple como los
CheckBox.
Este control se utiliza como contenedor y por si solo no tiene mucha funcionalidad, es por
eso, que solo veremos sus principales propiedades, métodos y eventos.
Propiedades
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 200
Propiedad
Descripción
Name Generalmente usaremos el prefijo gbx.
Enabled Determina si el control estará habilitado o deshabilitado.
Text Indica el texto que se mostrará como encabezado del control.
Visible Muestra u oculta al control y todo su contenido.
Métodos
Método
Descripción
Focus Pone el foco sobre el control.
Hide Oculta el control, sin descargarlo de la memoria.
Show Pone visible el cuadro de grupo.
Eventos
Evento
Descripción
GotFocus Ocurre al ingresar el foco sobre el control.
LostFocus Ocurre al salir el foco del control.
Vamos a crear un proyecto de ejemplo con el nombre RadioButtonPru, en el que situaremos
dentro de un formulario, una serie de controles RadioButton y un TextBox, de modo
que mediante los RadioButton cambiaremos el tipo de fuente y color del cuadro de texto.
La Figura muestra un diseño inicial del formulario.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 201
Pruebas con el control RadioButton.
Al ejecutar el proyecto, sin embargo, no podemos conseguir establecer simultáneamente
un tipo de letra y color, puesto que al pulsar cualquiera de los botones de radio, se
quita el que hubiera seleccionado previamente.
Para solucionar este problema, disponemos del control GroupBox, que nos permite, como
indica su nombre, agrupar controles en su interior, tanto RadioButton como de otro tipo, ya
que se trata de un control contenedor.
Una vez dibujado un GroupBox sobre un formulario, podemos arrastrar y soltar sobre él,
controles ya existentes en el formulario, o crear nuevos controles dentro de dicho control. De
esta forma, podremos ya, en este ejemplo, seleccionar más de un RadioButton del formulario,
como vemos en la Figura .
Selección de varios RadioButton en un formulario.
El evento CheckedChanged, al igual que ocurría con los controles CheckBox, será el que
tendremos que escribir para ejecutar el código en respuesta a la pulsación sobre un
control RadioButton. El Código fuente muestra los eventos correspondientes a los
controles de radio de este ejemplo. Para cambiar el tipo de fuente, instanciamos un
objeto Font y lo asignamos a la propiedad Font del TextBox; mientras que para cambiar
el color, utilizamos la estructura Color y la propiedad BackColor, también del TextBox.
Private Sub rbtTahoma_CheckedChanged(ByVal sender As [Link], ByVal e
As [Link]) Handles [Link]
[Link] = New Font("Tahoma", 12)
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 202
Private Sub rbtGaramond_CheckedChanged(ByVal sender As [Link], ByVal
e As [Link]) Handles [Link]
[Link] = New Font("Garamond", 8)
End Sub
Private Sub rbtComic_CheckedChanged(ByVal sender As [Link], ByVal e
As [Link]) Handles [Link]
[Link] = New Font("Comic Sans MS", 15)
End Sub
Private Sub rbtVerde_CheckedChanged(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link] = [Link]
End Sub
Private Sub rbtAzul_CheckedChanged(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link] = [Link]
End Sub
Private Sub rbtAmarillo_CheckedChanged(ByVal sender As [Link], ByVal e
As [Link]) Handles [Link]
[Link] = [Link]
End Sub
5.2.11.- Controles VScrollBar, HScrollBar, TrackBar
Un control VScrollBar es una barra de desplazamiento que permite manipular rangos
de valores numéricos por medio de su propiedad Value, los cuales son establecidos por las
propiedades maximum (máximo valor) y minimum (mínimo valor). El control
HScrollBar realiza la misma función, sólo se diferencia en su forma de presentación.
Estos controles son utilizados para implementar el desplazamiento en los contenedores que
no proporcionan sus propias barras de desplazamiento, como PictureBox.
El objeto TrackBar es un control desplazable similar al control ScrollBar.
Para configurar los intervalos entre los que se desplaza el valor de la propiedad Value de
una barra de seguimiento, estableciendo la propiedad Minimum para especificar el extremo
inferior del intervalo y la propiedad Maximum para especificar el extremo superior del
intervalo.
7.3.1 Ejemplo práctico controles VScrollBar y TrackBar
Realizar una aplicación que permita a un usuario por medio de controles VScrollBar y
TrackBar visualizar un color al realizar un desplazamiento en cualquiera de los controles.
Crear la interfaz de usuario
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 203
Utilizando el cuadro de herramientas haga clic en el control VScrollBar y ubique 3
controles en el formulario en la posición deseada, además, seleccione el control TrackBar
y ubique 3 controles en el formulario. También seleccione el control Label y ubique 7
controles en el formulario. La figura 7.11., muestra la interfaz de usuario.
Establecer las propiedades de los objetos de la interfaz de usuario
Después de colocar los controles u objetos en el formulario, establezca las siguientes
propiedades a los controles:
Tabla 7.3 Propiedades de los controles de la aplicación BarrasdeDesplazamiento.
Nombre del proyecto :
Control Propiedad Valor
VScrollBar1, Name barra1, barra2, barra3
VScrollBar2, Maximum 255
VScrollBar3. Minimum 0
TrackBar1, Name desplazamiento1, desplazamiento2,
TrackBar2, desplazamiento3
TrackBar3 Maximum 255
Minimum 0
Label1 Name txtcolores
Text En blanco
BorderStyle FixedSingle
Label2 Name txttitulo
Text Colores Personalizados
TextAlign MiddleCenter
Font Microsoft Sans Serif, 8pt, style=Bold
Label3 Name txttrackbar
Text Colores con TrackBar
TextAlign MiddleCenter
Label4 Name txtvalores
Text Valores del color
TextAlign MiddleCenter
Label5 Name color1
Text En blanco
Label6 Name color2
Text En blanco
Label7 Name color3
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 204
Text En blanco
Form1 Name formulario
Text Controles VScrollBar y TrackBar
Interfaz de usuario (VScrollBar, TrackBar).
Escribir código
Seleccione el objeto barra1, dé doble clic para abrir el editor del procedimiento
barra1_Scroll y escriba el siguiente código:
[Link] = [Link]([Link], [Link], [Link])
[Link] = "Azul=" & [Link]
Seleccione el objeto barra2, dé doble clic para abrir el editor del procedimiento
barra2_Scroll y escriba el siguiente código:
[Link] = [Link]([Link], [Link],
[Link]) [Link] = "Verde=" & [Link]
Seleccione el objeto barra3, dé doble clic para abrir el editor del procedimiento
barra3_Scroll y escriba el siguiente código:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 205
[Link] = [Link]([Link], [Link],
[Link])
[Link] = "Rojo=" & [Link]
Para los controles TrackBar realice la misma programación, solamente es necesario
cambiar el nombre del control es decir barra? por desplazamiento?.
En el anterior código al control txtcolores se le modifica la propiedad Backcolor
asignándole el método FromArgb de la clase Color el cual define un color tomando como
parámetros los valores para rojo, verde y azul y opcionalmente el nivel de transparencia.
Al desplazarse sobre cada control se obtiene un valor el cual se asigna respectivamente a
cada color. Después por cada barra de desplazamiento se le asigna a los objetos Label
(color1, color2, color3) en su propiedad Text el nombre del color y el valor que toma el
control en su propiedad Value. Esta operación se realiza también en el control TrackBar.
Ejecutar el proyecto
Al ejecutar el proyecto en el entorno de desarrollo de visual [Link], se visualiza:
Ejecución aplicación Barras de Desplazamiento.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 206
Al dar realizar el desplazamiento de la barra sobre cada uno de los controles
VScrollBar el fondo del Label deberá ir cambiar de color. Al realizar esta operación se
visualizará la siguiente figura:
Ejecución aplicación Barras de Desplazamiento.
Esto mismo se puede realizar cambiando de posición la barra de seguimiento
(TrackBar) para obtener un color.
5.2.11.-Controles de tipo menú
El menú es uno de los tipos de control más frecuentemente utilizados en los formularios
Windows. Consiste en un conjunto de opciones, a través de las cuales, el usuario ejecutará
algunos procesos de la aplicación. Disponemos de tres tipos de control menú: MainMenu,
ContextMenu y MenuItem.
MainMenu y ContextMenu actúan como contenedores de grupos de controles
MenuItem, representando este último control, la opción de menú sobre la que el usuario pulsa
o hace clic.
El proyecto MenuPru que se acompaña como ejemplo, muestra los diferentes tipos de menú .
A continuación, describiremos los principales pasos a dar en el proceso de su construcción.
Menú Principal. MainMenu
Un control MainMenu, consiste en un conjunto de opciones que se sitúan horizontalmente
debajo del título del formulario. A partir de cada opción, podemos asociar a su vez,
grupos de opciones que se mostraran verticalmente al hacer clic en la opción principal o
situada en la barra horizontal.
Para crear un menú principal, seleccionaremos del cuadro de herramientas el control
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 207
MainMenu, y tras dibujarlo en el formulario, se añadirá una referencia del control al
panel de controles especiales situado bajo el diseñador. La Figura muestra un control
de este tipo al que le hemos dado el nombre mnuPrincipal.
Menú de tipo MainMenu añadido al diseñador del formulario.
La creación de las diferentes opciones que compondrán el menú es un proceso que se ha
mejorado y simplificado al máximo respecto a versiones anteriores de VB. El proceso
de edición del menú se realiza directamente en el formulario, en el mismo lugar en el
que el menú aparecerá en tiempo de ejecución.
Al hacer clic en la primera opción del menú, podemos dar nombre y propiedades a esa
opción. Al mismo tiempo, de un modo muy intuitivo, veremos las próximas opciones
disponibles, tanto las desplegables a partir de dicho menú, como las de la barra principal.
Sólo hemos de movernos en la dirección que necesitemos y dar nombre a las opciones, y
valores a sus propiedades. Ver Figura
Creación de las opciones de un menú principal de formulario.
Cada una de las opciones que componen el menú es a su vez un control MenuItem.
Si durante su creación sólo proporcionamos el nombre, el IDE va asignando a dicho
control valores por defecto en sus propiedades.
Para modificar las propiedades de una opción de menú, sólo hemos de seleccionarlo en la
estructura de menú que estamos creando en el diseñador del formulario, y pasar a la
ventana de propiedades. Entre las propiedades disponibles para un MenuItem, podemos
destacar las siguientes.
Text. Contiene una cadena con el literal o texto descriptivo de la opción de menú.
Enabled. Permite habilitar/deshabilitar la opción de menú. Cuando se encuentra
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 208
deshabilitada, se muestra su nombre en un tono gris, indicando que no puede ser
seleccionada por el usuario.
DefaultItem. Permite establecer opciones por defecto. En una opción de menú por
defecto, su texto se resalta en negrita.
Checked. Marca/desmarca la opción. Cuando una opción está marcada, muestra
junto a su nombre un pequeño símbolo de verificación o punteo.
RadioCheck. En el caso de que la opción de menú se encuentre marcada, si
asignamos True a esta propiedad, en lugar de mostrar el símbolo de verificación
estándar, se muestra uno con forma de punto.
ShortCut. Se trata de un atajo de teclado, o combinación de teclas que nos van
a permitir ejecutar la opción de menú sin tener que desplegarlo. Al elegir esta
propiedad, aparecerá una lista con todos los atajos disponibles para asignar.
ShowShortCut. Permite mostrar u ocultar la combinación de teclas del atajo de
teclado que tenga asignado una opción de menú.
Visible. Muestra u oculta la opción de menú.
MdiList. Esta propiedad se utiliza habitualmente en opciones situadas en la barra
de menú, y permite establecer que dicha opción al desplegarse, muestre, además
de las opciones de menú que le hayamos asignado, la lista de ventanas secundarias
MDI, en el caso de que el menú principal esté contenido en un formulario de
tipo MDI. Los formularios MDI serán tratados posteriormente.
Podemos adicionalmente, asignar una tecla de acceso rápido o hotkey a una opción
de menú, anteponiendo el carácter & a la letra que deseemos, de las que se encuentran en
la propiedad Text del control MenuItem. Al igual que sucede con los demás tipos de
controles, en el texto de la opción de menú, aparecerá subrayada la mencionada letra.
De este modo, cuando despleguemos un menú, no será necesario posicionarnos en una
de ellas para ejecutarla, sino que simplemente pulsando la tecla rápida, se ejecutará el
código de dicha opción.
También podemos establecer separadores entre las opciones de menú simplemente creando
una opción y asignando a su propiedad Text el carácter de guión ( - ).
En nuestro formulario de ejemplo, vamos pues a diseñar un menú con la estructura
del esquema mostrado en la Figura
Para todas las opciones se ha asignado una tecla de acceso rápido, y adicionalmente, para
las opciones que se indican a continuación, se han modificado algunas propiedades por
defecto.
Guardar. Deshabilitada.
Salir. Atajo de teclado en Ctrl. + S.
Copiar. Opción por defecto.
Pegar. Marcada con símbolo normal.
Cortar. Marcada con símbolo de círculo.
Elipse. Opción no visible.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 209
Esquema del menú de ejemplo.
La Figura muestra el formulario en ejecución con una parte del menú abierta.
Menú desplegado a varios niveles, mostrando opciones.
Una vez finalizada la fase de diseño del menú, debemos proceder a escribir el código
para sus opciones. El evento Click es el que permite a un control MenuItem ejecutar código
cuando la opción de menú es seleccionada. Abriendo por tanto, el menú desde el diseñador
del formulario, y haciendo doble clic en la opción correspondiente, nos situaremos en
el editor de código, dentro del procedimiento manipulador del evento Click para esa
opción. El Código fuente muestra el código que se ejecutará cuando seleccionemos las
opciones de menú Abrir y Salir de nuestro ejemplo.
Private Sub mnuAbrir_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link]("Opción Abrir del menú")
End Sub
Private Sub mnuSalir_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link]()
End Sub
Puesto que muchas de las propiedades de un control MenuItem son manipulables en
tiempo de ejecución, añadiremos al formulario varios botones, mediante los cuales
realizaremos operaciones sobre las opciones del menú tales como habilitar y deshabilitar,
mostrar y ocultar, cambiar el nombre, etc. La Figura muestra el formulario con estos
nuevos botones.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 210
Controles Button para manipular por código las propiedades de las opciones del menú.
En el Código fuente podemos ver los manipuladores de evento de estos botones.
Private Sub btnHabilitar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link] = Not [Link]
End Sub
Private Sub btnMarcar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link] = Not [Link]
End Sub
Private Sub btnMostrar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link] = Not [Link]
End Sub
Private Sub btnNombre_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
If [Link] = "A&brir" Then
[Link] = "HO&LA"
Else
[Link] = "A&brir"
End If
End Sub
Private Sub btnDefecto_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link] = Not [Link]
End Sub
Menú Contextual. ContextMenu
El control ContextMenu representa un menú contextual o flotante. Este tipo de menú se
asocia al formulario o a uno de sus controles, de modo que al hacer clic derecho, se mostrará
sobre el elemento al que se haya asociado.
El modo de añadir un control ContextMenu y sus correspondientes opciones al
formulario, es el mismo que para un MainMenu; situándose también una referencia del
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 211
menú contextual en el panel de controles especiales del diseñador. Antes de poder diseñar
las opciones de un ContextMenu, debemos pulsar la referencia de dicho menú que existe
en el panel de controles especiales, ya que por defecto, el formulario muestra el menú
principal en caso de que tenga uno definido.
La Figura muestra el menú contextual mnuContexto, que hemos añadido al
formulario. Para asociar este menú con un control o formulario, utilizaremos la
propiedad ContextMenu de que disponen la mayoría de los controles Windows. En este
ejemplo, insertaremos el control txtValor, de tipo TextBox, y le asociaremos el menú de
contexto que acabamos de crear.
Como resultado, cuando ejecutemos la aplicación, al hacer clic derecho sobre el TextBox,
aparecerá el menú contextual que hemos asignado, mediante el que cambiaremos el tipo
de fuente de la caja de texto, transformaremos el texto a mayúsculas y minúsculas. El
Código fuente muestra el código de los eventos Click correspondiente a las opciones del
menú contextual.
Private Sub mnuFuente_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim oFuente As New Font("Comic", 15)
[Link] = oFuente
End Sub
Private Sub mnuMayusculas_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link] = [Link]()
End Sub
Private Sub mnuMinusculas_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link] = [Link]()
End Sub
La Figura muestra el aspecto del menú contextual, cuando es utilizado desde el control
TextBox.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 212
Control ContextMenu asociado a un TextBox.
5.3.-Foco de entrada
Para que las pulsaciones de teclado puedan ser recibidas por un determinado control, dicho
control debe tener lo que se denomina el foco de entrada.
El modo de dar a un control el foco de entrada, consiste en hacer clic sobre él, o bien, pulsar
la tecla [TAB], pasando el foco hasta el control deseado. Cuando un control recibe el
foco, el sistema operativo lo remarca visualmente o en el caso de controles de escritura,
muestra el cursor de escritura en su interior.
Otra forma es realizar la codificación del foco de entrada, de la siguiente manera
Private Sub btnActivar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' utilizando la propiedad focus para el control textbox1
[Link]
End Sub
5.4.-Programacion de los eventos de controles
Windows es un sistema operativo orientado a eventos, por lo que cualquier mínima
interacción que realicemos sobre un formulario o control, generará el oportuno evento,
para el que si estamos interesados, deberemos responder.
Prosiguiendo con el control Button, cuando pulsamos sobre el mismo, se origina el
evento Click de dicho control. Si dibujamos un Button en un formulario y pulsamos en
él, no ocurrirá nada, ya que aunque el evento se produce, no existe código que le
proporcione respuesta.
Para dar oportuna respuesta a un evento emitido por un control, debemos escribir un
procedimiento manipulador del correspondiente evento. La creación de manipuladores de
evento es un aspecto que ya hemos visto en detalle en el tema Delegación de código y
eventos. De igual modo, los aspectos básicos de la escritura de código para un evento se
comentaron en el tema Una aplicación con funcionalidad básica; sugerimos por lo tanto
al lector, la consulta de estos temas para cualquier referencia básica que necesite al
respecto.
No obstante, en el presente apartado, y para reforzar conceptos, realizaremos un repaso del
proceso de creación del manipulador de evento para un control.
Como ejemplo, insertaremos en un formulario un control Button, al que daremos el
nombre btnMensaje, y en su propiedad Text asignaremos la cadena Mostrar mensaje.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 213
Seguidamente haremos doble clic sobre el Button; esta acción abrirá la ventana del editor
de código, creando al mismo tiempo, la declaración o esqueleto del procedimiento
manipulador de evento Click del botón, listo para ser codificado.
Ya que necesitamos que se muestre un mensaje al ser pulsado este control, utilizaremos
el objeto MessageBox de la plataforma, llamando a su método compartido Show( ), para
visualizar el mensaje. En definitiva, el manipulador de este evento quedaría como muestra el
Código fuente
Private Sub btnMensaje_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link]("Se acaba de pulsar el botón del formulario")
End Sub
El resultado en ejecución, sería el que muestra la Figura
Observando con más detalle el procedimiento del evento, vemos que al final de su
declaración, aparece la palabra clave Handles, que como vimos en el tema sobre eventos,
nos sirve para asociar esta rutina de código con un evento de un objeto. En el
ejemplo que nos ocupa, asociamos el procedimiento btnMensaje_Click( ), con el
evento Click del objeto btnMensaje, perteneciente a la clase Button.
Resultado de la ejecución del evento Click de un control Button, al ser pulsado.
Como ya sabemos, el enlace procedimiento-evento de objeto mediante la palabra Handles,
se producede modo estático. Esto requiere que en el código, el identificador que contenga
el objeto del control, deba ser declarado con ámbito a nivel de clase, y utilizando además
la palabra clave WithEvents.
Dicha tarea es realizada automáticamente por el diseñador del formulario cuando genera el
código del mismo. Veamos en el Código fuente , el fragmento de código generado por
el diseñador que realiza esta labor.
' esta declaración es situada a nivel del código de la clase del formulario, es decir,
' fuera de cualquier método
Friend WithEvents btnMensaje As [Link]
5.5.-Programando otros eventos de un control
En un control Button, el evento por defecto es Click; esto supone, como acabamos de ver,
que al hacer doble clic sobre el control en el formulario, el procedimiento de evento
sobre el que nos situará el editor será precisamente este. Sin embargo, un control Button,
al igual que el resto de controles de los formularios Windows, disponen de un gran número
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 214
de eventos que podemos codificar para adaptar a nuestras necesidades.
Por ejemplo, el evento MouseEnter, se produce cuando se detecta que el ratón entra en
el área de un control, en este caso Button. Como este no es el evento por defecto,
debemos buscar su declaración vacía manualmente en el editor. Para ello, abriremos la
lista desplegable Nombre de clase, situada en la parte superior izquierda del editor de
código, y seleccionaremos el nombre de nuestro control: btnMensaje. Ver Figura
Lista de clases del editor de código.
A continuación, abriremos la otra lista desplegable del editor de código: Nombre de método,
situada en la parte superior derecha del editor. En ella aparecerán los nombres de
todos los eventos de que dispone el control. Localizaremos el evento MouseEnter, y lo
seleccionaremos. Ver Figura
Lista de eventos de una clase-control en el editor de código.
De igual modo que sucedió con el evento Click en el apartado anterior, el editor de
código creará el procedimiento manipulador de evento vacío, para el evento que
acabamos de seleccionar. Lo que vamos a hacer a continuación, es escribir el código
que permita cambiar el color del botón cuando el ratón entre al mismo. Veamos el Código
fuente
Private Sub btnMensaje_MouseEnter(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
[Link] = [Link]
End Sub
Cuando al ejecutar, situemos el ratón en el botón, este cambiará su color, mostrando el
aspecto de la Figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 215
Resultado de la ejecución del evento MouseEnter sobre un Button.
5.6.-Orden de tabulación de controles
Los controles disponen de la propiedad TabIndex, que contiene un número que será
utilizado para pasar el foco entre ellos al pulsar la tecla [TAB] durante la ejecución del
programa. Según vamos añadiendo nuevos controles, el IDE va asignando automáticamente
nuevos números a esta propiedad; de forma que, cuando comencemos la ejecución, el primer
control que tomará el foco será el que tiene el menor número en su TabIndex.
En el ejemplo anterior, el primer control que tomaba el foco era el TextBox de la contraseña,
lo cual no era nada lógico, ya que dicho control era el último en el formulario para el que
debíamos introducir datos.
Para solucionar este problema, simplemente tenemos que cambiar los valores de la
propiedad TabIndex de los controles, de modo que el orden de tabulación sea el que mejor
se adapte a nuestras necesidades.
Podemos obtener un mapa del orden de tabulación de los controles del formulario
seleccionando el menú del IDE Ver + Orden de tabulación; esto mostrará los controles con
el número de TabIndex que les hemos asignado. Como ventaja adicional, en esa situación,
podemos hacer clic en los controles y cambiar también el número de tabulación. Ver Figura
Diseñador del formulario mostrando el orden de tabulación de controles.
Si por el contrario, no queremos dar el foco a un control pulsando [TAB], debemos
asignar a la propiedad TabStop de dicho control el valor False. Por defecto, TabStop
vale True, permitiendo de esta el paso de foco entre controles mediante la tecla [TAB].
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 216
5.7.-Funciones para presentar mensajes
Visual Basic posee 2 tipos de funciones para presentar mensajes, ellas son MsgBox e
InputBox.
5.7.1.-Función InputBox:
La función InputBox presenta un mensaje al usuario, permitiéndole ingresar un valor en
una caja de texto:
Como se dijo la función InputBox presenta un cuadro de diálogo donde el usuario puede
ingresar un texto y luego aceptar o cancelar dicho cuadro de diálogo.
Los parámetros principales de esta función son:
InputBox (Promt,Title, Default)
El parámetro Prompt específica la leyenda que mostrará la caja de mensajes.
El parámetro Title especifica el título que llevará el cuadro de diálogo.
El parámetro Default es el texto que mostrará la caja de texto.
El aspecto más importante de InputBox es que nos devuelve una cadena con lo que haya
ingresado el usuario en la caja de texto. Luego podemos realizar una tarea específica
dependiendo del valor devuelto.
Ejemplo:
Dim retorno As String
retorno = InputBox("Ingrese algo en la caja de texto", "Ejemplo")
MsgBox "Usted ingresó:" & retorno
En el ejemplo anterior, en la variable Retorno se almacenará el valor que haya ingresado el
usuario cuando haga Click en el botón de Aceptar.
Cuando el usuario presiona Candelar, el InputBox devuelve una cadena vacía. Esto es
importante tenerlo en cuenta para realizar una o tal acción
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 217
Si quiseramos por ejemplo desplegar un InputBox, y que este no se cierre hasta que el usuario
si o si haya ingresado un valor, podemos hacerlo de la siguiente forma, utilizando una
condición en un bucle Do Loop
Código fuente en el formulario
Private Sub Form_Load()
Dim Dato As String
'Hasta que no se ingrese un dato, el InputBox no se cerrará
Do
Dato = InputBox("Ingresar algun dato", " Ejemplo ")
Loop Until Dato <> ""
'Muestra el valor
MsgBox Dato, vbInformation
End Sub
5.7.2.-Función MsgBox:
La función MsgBox, es muy fácil de usar y se utiliza para mostrar distintos tipos de
mensajes. La sintaxis completa de la función MsgBox es:
MsgBox(mensaje[, botones][, título][, archivoAyuda, contexto])
Ejemplos de mensajes o cajas de texto con la función MsgBox que podemos mostrar:
Como se ve en los gráficos anteriores, con MsgBox podemos tener variedad a la hora de
mostrar un determinado mensaje, utilizando para ello las diferentes constantes que
incorpora la función.
Los parámetros más importantes son:
Title : Es la leyenda que aparecerá en el título del mensaje.
Texto : Es el Texto que mostrará el mensaje.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 218
Botones: En este parámetro se colocan las constantes que determinarán si la caja tiene
uno o varios botones y el tipo de mensaje: informativo, de exclamación de alerta etc...
Cuando escribimos la coma dentro de la función en el parámetro botones, Visual
Basic despliega una lista con las opciones o constantes que podemos utilizar.
Ejemplo de msgbox un poco más elaborado para entender un poco mejor esto; este ejemplo
envía un mensaje de alerta con dos botones como opciones: En vez de utilizarse las palabras
mensaje, estilo, etc se podrían utilizar otras, pero siempre hay que respetar el orden
Private Sub Command1_Click()
Dim Mensaje, Estilo, Título, Respuesta, MiCadena as String
Mensaje = "¿Estas totalmente seguro de lo que vas a hacer?"
' cuerpo del mensaje.
Estilo = vbYesNo + vbCritical
' Define el estilo, los botones, lo que está después del mas es el circulo rojo '
con la cruz.
Título = "error grave (mentira)" ' es el título.
Respuesta = MsgBox(Mensaje, Estilo, Título)
'el paréntesis se pone también
If Respuesta = vbYes Then ' El usuario eligió el botón Sí.
MiCadena = "Sí" ' Ejecuta una acción.
Else ' El usuario eligió el botón No.
MiCadena = "No" ' Ejecuta una acción.
[Link] = False 'Aca puse una acción que usted ya conoce
End If
End Sub
En estilo podrían ir por ejemplo las siguientes opciones:
VbOKOnly: Sólo muestra el botón Aceptar.
VbOKCancel: Muestra los botones Aceptar y Cancelar.
VbAbortRetryIgnore: Muestra los botones Anular, Reintentar e
Ignorar.
VbYesNoCancel: Muestra los botones Sí, No y Cancelar.
VbYesNo: Muestra los botones Sí y No.
VbRetryCancel: Muestra los botones Reintentar y Cancelar.
VbCritical: Muestra el icono Mensaje crítico.
VbQuestion: Muestra el icono Consulta de advertencia.
VbExclamation: Muestra el icono Mensaje de advertencia.
VbInformation: Muestra el icono Mensaje de información.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 219
5.8.- Controles avanzados de Visual Basic
5.8.1.-Control Temporizadores (Timer)
En [Link] disponemos al igual que en anteriores versiones, del control Timer, que nos
permite la ejecución de código a intervalos de tiempo predeterminados.
Este control ha sufrido una importante reestructuración, ya que internamente hace uso
de la clase Timer, perteneciente al conjunto de clases del sistema. El hecho de poder
acceder a esta clase, nos proporciona una gran flexibilidad en nuestros desarrollos, ya que,
a partir de ahora también crearemos temporizadores por código, sin necesidad de utilizar
el control Timer.
Ejemplo de reloj digital
Vamos a mostrar una forma simple y sencilla de crear en visual basic .net un reloj digital.
Lo haremos utilizando un label y un componente Timer.
El formulario debería tener una apariencia similar a la de la siguiente imagen>
Para este ejemplo donde solo mostraremos la hora, cambiaremos la fuente del control label
para darle más importancia. Yo estoy usando fuente Tahoma tamaño 28.
Ahora veamos las propiedades del componente timer. Para que se ejecute el codigo del evento
Tick del componente timer, este tiene que tener la propiedad enable en True. Y el codigo que
ingresemos se va a ejecutar cada n ticks. La cantidad de ticks de n se las indicamos con la
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 220
propiedad interval en milisegundo. Por lo tanto si colocamos dicha propiedad en 1000 ticks,
el código se ejecutará cada 1 segundo.
Ahora veamos el código, es muy sencillo:
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
[Link] =[Link]
End sub
Solo resta ejecutar (F5) la aplicación y tendremos nuestro reloj digital como se muestra en
la siguiente imagen>
Otro ejemplo
En el ejemplo TimerPru que comentamos a continuación, vamos a construir un formulario
en el que utilizaremos los dos tipos de temporizadores, el propio control Timer y un objeto
de la clase. El primer proceso a codificar, consistirá en traspasar a intervalos de
tiempo, el contenido de un TextBox del formulario, a otro control de este mismo tipo. El
formulario del proyecto se muestra en la Figura
Figura Formulario para ejemplo con temporizadores.
Tras incluir los controles de usuario en el formulario, añadiremos un control Timer, al que
daremos el nombre tmrTemporizador. Esta acción abrirá, bajo el diseñador del formulario,
un panel para controles especiales, como es el caso de Timer, en el que se mostrará dicho
control.
En este panel se depositan los controles del formulario que no tienen una interacción
directa con el usuario, o cuyo diseño es diferente al de los controles habituales.
Para especificar el espacio de tiempo en el que este control será ejecutado cuando lo
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 221
activemos, utilizaremos la propiedad Interval, a la que tenemos que asignar un valor
numérico, que establece dicho tiempo en milisegundos. En nuestro caso, asignaremos
500, con lo que el control se ejecutará cada medio segundo.
Panel para controles especiales del diseñador de formularios.
El control Timer lo activaremos llamando a su método Start( ), cosa que hacemos al
pulsar el botón btnTraspasar.
Private Sub btnTraspasar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' iniciar el temporizador
[Link]()
End Sub
Una vez activado un temporizador, cada vez que transcurre el tiempo indicado en Interval,
genera un evento Tick. Es precisamente en este evento en el que debemos escribir el código
que necesitamos que se ejecute a intervalos regulares de tiempo. Haremos, por consiguiente,
doble clic en el control Timer del diseñador, para acceder al procedimiento manipulador de
este evento, cuyo contenido lo podemos ver
' Este evento se produce en el intervalo especificado en el control Timer
Private Sub tmrTemporizador_Tick(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
' quitamos una letra del TextBox de origen...
Dim sLetra As String
sLetra = [Link](0, 1)
[Link] = [Link](0, 1)
' ...y lo pasamos al TextBox de destino
[Link] &= sLetra
' cuando se haya traspaso todo el texto detener el temporizador
If [Link] = 0 Then
[Link]()
[Link]("Traspaso finalizado")
End If
End Sub
5.8.2.-Control ImageList
Este control actúa como repositorio de imágenes, del que se alimentarán otros controles del
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 222
formulario que necesiten mostrar gráficos en su interior.
Una vez añadido este control en el formulario, se situará en el panel de controles
especiales del diseñador, y haciendo clic en su propiedad Images, se abrirá la ventana
de la Figura, en la que podremos añadir y quitar las imágenes que van a formar parte de
la lista del control, así como ver en el panel complementario, la información sobre cada
imagen asignada.
Ventana de administración de imágenes del control ImageList.
Las imágenes que insertamos en el control tienen un tamaño por defecto, en el
caso de que necesitemos modificarlo, expandiremos la propiedad ImageSize en la
ventana de propiedades y asignaremos nuevos valores en Width y Height.
Otra ventaja de este control es que nos permite manipular las imágenes por código, por
ejemplo, para añadir nuevas imágenes, debemos usar el método Add( ) de su propiedad
Images, como muestra el Código fuente
[Link](New Bitmap("[Link]"))
5.8.3.-Control ToolBar
Este control representa la barra de herramientas o botones de acceso rápido que facilitan
al usuario la ejecución de los procesos principales del programa, evitándole la
navegación por el menú del formulario.
Al ser dibujado, este control queda acoplado a la parte superior del formulario. Después
de ponerle tbrBarra como nombre, asignaremos a su propiedad ImageList, el control
de ese mismo tipo que acabamos de crear; esto nos permitirá asignar los gráficos de
la lista a los botones que vayamos creando en el ToolBar. Para establecer el tamaño de
los botones de la barra utilizaremos la propiedad ButtonSize de este control.
Seguidamente haremos clic en la propiedad Buttons, que abrirá una ventana con la
colección de botones de la barra, en la que podremos crear y configurar dichos botones.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 223
Editor de botones del control ToolBar.
Cada botón en un ToolBar es un objeto de tipo ToolBarButton, del que podemos
destacar las siguientes propiedades.
Text. Cadena con el texto que muestra el botón.
ImageIndex. En el caso de asociar el ToolBar con un control ImageList, en esta
propiedad asignamos para un botón una de las imágenes del ImageList, indicando el
número de orden de la imagen.
Style. Permite establecer el estilo del botón: de pulsación; separador; o de tipo
desplegable, que abre un subconjunto de opciones.
DropDownMenu. Si asociamos el botón con una opción de la barra de menú del
formulario, y configuramos su estilo como DropDownButton, al pulsar el botón
desplegable, se mostrarán las opciones de menú; el efecto será el mismo que si
hubiéramos desplegado directamente el menú del formulario.
La Figura muestra la ventana principal de la aplicación con la barra de herramientas
Formulario con ToolBar.
Una vez terminado el diseño del ToolBar, debemos codificar su evento ButtonClick,
que será provocado cada vez que se pulse un botón de la barra. Dentro del
procedimiento de este evento, comprobaremos qué botón ha sido pulsado y ejecutaremos
las acciones oportunas.
Tanto el botón Abrir como la opción de menú del mismo nombre realizan la misma tarea,
por lo que llaman al método AbrirArchivo( ), que es quien realmente muestra el
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 224
formulario necesario.
Private Sub tbrBarra_ButtonClick(ByVal sender As [Link], ByVal e As
[Link]) Handles
[Link]
' comprobar qué botón de la barra se ha pulsado
If [Link] Is [Link] Then
' llamamos al método que abre el formulario para abrir un archivo
[Link]()
End If
If [Link] Is [Link] Then
' cerrar la aplicación
[Link]()
End If
End Sub
Private Sub mnuAbrir_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' al seleccionar esta opción de menú llamar al método que
' abre el formulario que permite abrir un archivo
[Link]()
End Sub
Private Sub AbrirArchivo()
Dim ofrmAbrirArchivo As New frmAbrirArchivo()
[Link] = Me
[Link]()
End Sub
Al haber asignado al botón btnPersonal uno de los menús de la barra del formulario, no
será necesario escribir código para detectar este botón en el evento ButtonClick, ya que
se ejecutará directamente el código del evento Click de las opciones de menú. El
Código fuente 523 muestra el código perteneciente a la opción de menú Personal +
Datos.
Private Sub mnuDatos_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim ofrmPersonal As New frmDatosPersonal()
[Link] = Me
[Link]()
End Sub
5.8.4.-Control StatusBar
Para mostrar una barra informativa de estado recurriremos a este control, que al
dibujarse queda situado en la parte inferior del formulario; como nombre le daremos
sbrEstado. De forma similar al ToolBar, un control StatusBar está compuesto de una
colección de objetos Panel, que iremos añadiendo al control mediante la propiedad
Panels, la cual mostrará una ventana para la creación y configuración de tales paneles.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 225
Editor de paneles del control StatusBar.
Entre las propiedades destacables de un objeto Panel podemos mencionar las siguientes.
BorderStyle. Muestra el panel con efecto resaltado, hundido o normal.
Icon. Permite asociar un icono al panel.
AutoSize. Con esta propiedad podemos conseguir que el panel se redimensione
ajustándose a su contenido o que tenga un tamaño fijo.
En este ejemplo, hemos añadido dos paneles a la barra de estado del formulario. En uno
mostramos un texto fijo; mientras que en el otro, visualizamos la hora actual a través
de un objeto Timer que ponemos en marcha en el evento Load del formulario. Veamos
los métodos implicados, en el Código fuente 524.
Private Sub frmPrincipal_Load(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
' al cargar el formulario, creamos un temporizador
' le asociamos un manejador para su evento Tick y lo iniciamos
Dim oTiempo As New Timer()
[Link] = 1000
AddHandler [Link], AddressOf PonerHoraActual
[Link]()
End Sub
Private Sub PonerHoraActual(ByVal sender As Object, ByVal e As EventArgs)
' actualizamos a cada segundo la hora de un panel de la barra de estado
[Link](1).Text = [Link]("HH:mm:ss")
End Sub
La Figura muestra el formulario con la barra de estado.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 226
Formulario con StatusBar.
Finalizada la creación del StatusBar, añadiremos al proyecto un formulario con
el nombre frmDatosPersonal, en el dibujaremos un conjunto de nuevos controles que
iremos describiendo seguidamente.
5.8.5.-Control DateTimePicker
Este control permite la selección e introducción de fechas en una caja de texto con
capacidades extendidas, o bien mediante un calendario desplegable que se mostrará al
pulsar el botón de expansión que contiene. Ver Figura
Control DateTimePicker.
Para modificar la fecha en el cuadro de texto, debemos situarnos en la parte a modificar de
la fecha y teclear el nuevo valor, o bien, con las flechas de dirección arriba-abajo, cambiar
esa parte de la fecha. Si expandimos el calendario, podremos realizar la selección de un
modo más gráfico.
Por defecto el control muestra la fecha actual, pero con la propiedad Text podemos
cambiar la fecha por código, cosa que hacemos al cargar el formulario, asignando una
fecha distinta de la actual. Ver Código.
Private Sub frmDatosPersonal_Load(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
' modificar fecha del DateTimePicker
[Link] = "15/06/2002"
'....
End Sub
Podemos restringir el rango de fechas a mostrar por este control con las propiedades
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 227
MinDate y MaxDate. Si queremos, por otra parte, que la fecha se muestre con un
formato personalizado, aplicaremos dicho formato mediante la propiedad CustomFormat,
teniendo en cuenta que no se hará efectivo hasta que a la propiedad Format no le
asignemos el valor Custom.
El botón btnCambiosFecha del formulario realiza algunas modificaciones por código sobre
el control DateTimePicker dtpFNacim del formulario, que vemos en el Código
Private Sub btnCambiosFecha_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' configurar por código el control DateTimePicker
[Link] = "1/4/2002"
[Link] = "1/10/2002"
[Link] = "d-MMM-yy"
[Link] = [Link]
End Sub
5.8.6.-Control NumericUpDown
Control que muestra una caja de texto con un valor numérico que podremos ir
aumentando- disminuyendo al pulsar los botones para esta labor de que dispone el control.
La Figura muestra este control en nuestro formulario de pruebas.
Control NumericUpDown.
Entre las propiedades de este control destacaremos las siguientes.
Increment. Número en el que se incrementará el valor del control cuando
pulsemos sus botones o teclas de dirección.
InterceptArrowKeys. Permite que las flechas de dirección arriba-abajo tengan
el mismo efecto que si pulsamos los botones para incrementar o disminuir, de este
control.
Maximum, Minimun. Contienen los límites superior e inferior en cuanto al
número que podrá contener el control.
TextAlign. Permite alinear el número dentro la caja de texto del control.
UpDownAlign. Permite situar los botones del control a la izquierda o derecha de
la caja de texto que contiene el valor.
Entre los eventos de que dispone este control, ValueChanged se produce cada vez que
cambia el valor del control, de modo que en este caso, vamos a cambiar el color de fondo
en función del número que contenga.
Private Sub nupEdad_ValueChanged(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Select Case [Link]
Case 20 To 30
[Link] = [Link]
Case 30 To 40
[Link] = [Link]
Case Else
[Link] = [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 228
End Select
End Sub
5.8.7.-Control DomainUpDown
Este control nos permite desplazarnos por una lista de valores, al mismo estilo que el control
anterior. Dicha lista de valores la crearemos mediante la propiedad Items, en tiempo de
diseño o ejecución. El Código muestra como al cargar el formulario frmDatosPersonal,
con la propiedad Items y su método AddRange( ), añadimos los valores que
seleccionaremos en el control en tiempo de ejecución.
Private Sub frmDatosPersonal_Load(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
'....
' crear la lista del DomainUpDown
[Link](New String() {"Auxiliar", "Jefe
departamento","Coordinador"})
End Sub
La Figura muestra el control dudCategoría, de este tipo al ser utilizado en el formulario.
En el caso de que necesitemos los valores ordenados, asignaremos True a su propiedad
Sorted.
Control DomainUpDown.
5.8.8.-Control MonthCalendar
Este control muestra en modo gráfico un calendario por el que podemos desplazarnos para
seleccionar una fecha. El control DateTimePicker utiliza internamente un
MonthCalendar para mostrar su calendario desplegable.
Por defecto se visualiza un mes, pero si asignamos a su propiedad CalendarDimensions un
objeto Size, podemos expandir el tamaño del calendario para que muestre varios meses.
El Código muestra el código de un botón del formulario mediante el que cambiamos el
tamaño del calendario.
Private Sub btnTamCalendario_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link] = New Size(2, 2)
End Sub
En la Figura vemos el resultado de expandir el tamaño del control.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 229
Control MonthCalendar con el tamaño ampliado.
Para detectar la selección de una fecha utilizaremos el evento DateChanged. Debido
a que en un control MonthCalendar podemos seleccionar un rango de fechas, las
propiedades que tenemos que manipularpara averiguar la
fechas seleccionadas son: SelectionStart, SelectionEnd y SelectionRange, aunque en
muchas ocasiones sólo será necesario utilizar una de ellas.
Private Sub mclCalendario_DateChanged(ByVal sender As [Link], ByVal e
As [Link]) Handles
[Link]
' mostrar en un Label la fecha seleccionada en el control MonthCalendar
[Link] = [Link]
End Sub
5.8.9.-Control LinkLabel
Este control permite tener en un formulario Windows un enlace hacia una página de Internet,
con un comportamiento similar al que encontramos en un hiperenlace de una página web.
Su propiedad Text muestra un literal, de modo que al hacer clic sobre el mismo, se
provocará el evento LinkClicked en el que escribiremos el código a ejecutar.
En nuestro formulario de ejemplo, hemos creado un control de este tipo con el nombre
lnkEidos, que tiene el aspecto de la Figura 322, ya que además del enlace, le hemos asignado
una imagen.
Control LinkLabel.
Para conseguir que al hacer clic en este enlace, se abra Internet Explorer y navegue
hacia una determinada página, vamos a utilizar la clase Process, que como su nombre
indica, nos permite la gestión de procesos del sistema, tales como su inicio y finalización.
En este caso, el método compartido Start( ), de Process, va a ejecutar el navegador al
pasarle como parámetro una dirección web en forma de cadena. Veamos el Código
Private Sub lnkEidos_LinkClicked(ByVal sender As [Link], ByVal e As
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 230
[Link]) Handles
[Link]
' inicia Internet Explorer y navega hacia una página
[Link]("[Link]
End Sub
Creación y manipulación de elementos en ejecución
El conjunto de controles que acabamos de ver, al igual que los básicos permiten ser
creados no sólo mediante el diseñador de formularios, sino también desde código. Como
muestra de ello, la opción de menú Varios + Añadir botón y panel, añade dos imágenes
al control ImageList del formulario frmPrincipal, creando un nuevo botón para el
ToolBar y un panel para el StatusBar Ver el Código
Private Sub mnuAgregaElementos(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' añadir por código imágenes a la lista
[Link](New Bitmap("[Link]"))
[Link](New Bitmap("[Link]"))
Dim oBoton As New ToolBarButton()
[Link] = "TUTORIAS"
[Link] = 4
[Link](oBoton)
Dim oPanel As New StatusBarPanel()
[Link] = "BUSCAR"
[Link] = [Link]
[Link] = "Información sobre búsquedas"
[Link] = New Icon("[Link]")
[Link](oPanel)
End Sub
Para detectar la pulsación del nuevo botón de la barra de herramientas, añadimos el
siguiente código en su evento ButtonClick, que vemos en el Código
Private Sub tbrBarra_ButtonClick(ByVal sender As [Link], ByVal e As
[Link]) Handles
[Link]
'....
If [Link] = "TUTORIAS" Then
[Link]("Se ha pulsado el botón de tutorías")
End If
End Sub
La Figura muestra este formulario en ejecución tras añadir los nuevos elementos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 231
Nuevos controles añadidos al formulario en tiempo de ejecución.
5.8.10.-Control NotifyIcon
Este control permite añadir un icono asociado con nuestra aplicación en el panel de iconos
del sistema (Windows System Tray) situado en la parte derecha de la barra de tareas de
Windows. Tales iconos suelen utilizarse por aplicaciones que permanecen ocultas, y al
hacer clic derecho sobre su icono en este panel, aparece un menú contextual que permite
mostrar la aplicación.
En nuestro caso vamos a utilizar este control para ejecutar y parar la calculadora
del sistema empleando la clase Process, comentada en un apartado anterior.
Después de agregar un control de este tipo al formulario, asignaremos un icono a su
propiedad Icon y una cadena a su propiedad Text, que será mostrada al situar el ratón encima
de este control en tiempo de ejecución.
Crearemos después un menú contextual con las opciones Abrir y Cerrar, que
asignaremos a la propiedad ContextMenu del control NotifyIcon.
Para poder controlar la calculadora de Windows cuando esté en ejecución, declararemos una
variable de tipo Process a nivel de la clase. Al ejecutar la calculadora mediante el método
Start( ) de la clase Process, obtendremos un objeto de dicho tipo, que pasaremos a esta
variable, y nos permitirá posteriormente, cerrar el proceso en el que se está ejecutando la
calculadora mediante el método Kill( ). Veamos esta parte en el Código
Public Class frmPrincipal
Inherits [Link]
Private oCalculadora As Process
'....
Private Sub mnuCalcAbrir_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' iniciar la calculadora
oCalculadora = [Link]("[Link]")
End Sub
Private Sub mnuCalcCerrar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' cerrar la calculadora
[Link]()
End Sub
End Class
Al ejecutar el programa, se mostrará un nuevo icono en la lista del panel de iconos del
sistema de la barra de tareas, como muestra la Figura 324.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 232
Control NotifyIcon en el panel de iconos del sistema de la barra de tareas.
Como se puede comprobar, la clase Process amplía enormemente nuestra capacidad
de manipulación de los procesos del sistema.
5.8.11.-Controles de Diálogos
Controles OpenFileDialog
y SaveFileDialog
Estos controles se usan para facilitar el trabajo con archivos, el primero se refiere al
diálogo de “Abrir Archivo” y el segundo al diálogo “Guardar Archivo”, que en la
versión anterior estaban disponibles como Controles ActiveX.
Ambos tienen características similares que detallamos a continuación:
Propiedades
Propiedad
Descripción
Name Para el OpenFileDialog generalmente usaremos el prefijo odg.
Para el SaveFileDialog generalmente usaremos el prefijo sdg.
AddExtension Añade automáticamente la extensión al nombre del archivo.
CheckFileExits Chequea que exista el archivo antes de regresar del diálogo.
CheckPathExits Chequea que exista la ruta del archivo antes de regresar del
diálogo.
CreatePrompt Solo para el diálogo de Guardar. Si la propiedad ValidateName es
true pide confirmación al usuario cuando el archivo es creado.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 233
DefaultEx Indica la extensión por defecto del archivo.
FileName Indica el archivo escrito o seleccionado del diálogo.
Filter Especifica el tipo de archivo que se mostrará en el diálogo.
FilterIndex Determina el índice del filtro del diálogo. Este empieza en 1 y
depende de la lista de tipos de archivos configurada por Filter.
InitialDirectory Muestra un cierto directorio inicial para los archivos del diálogo.
Multiselect Solo para el diálogo de Abrir. Determina si se pueden seleccionar
varios archivos a la hora de abrir.
OverwritePrompt Solo para el diálogo de Guardar. Si la propiedad ValidateName es
true pide confirmación al usuario cuando un archivo creado existe.
ReadOnlyChecke Solo para el diálogo de Abrir. Determina el estado del checkbox
d ReadOnly en el diálogo de abrir.
RestoreDirectory Controla si el diálogo restaura el directorio actual antes de
cerrarse.
ShowHelp Visualiza o no el botón de Ayuda en el diálogo.
ShowReadOnly Solo para el diálogo de Abrir. Determina si se muestra o no el
checkbox ReadOnly en el diálogo de abrir.
Tile Indica el título a mostrarse en la barra de título del diálogo.
ValidateNames Controla que el nombre del archivo no tenga caracteres inválidos.
Métodos
Método
Descripción
OpenFile Devuelve un Stream indicando el archivo abierto en el diálogo de
abrir o grabado en el diálogo de guardar.
ShowDialog Muestra el diálogo de archivo, sea de abrir o de guardar.
Eventos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 234
Evento
Descripción
FileOk Ocurre al dar clic sobre el botón OK del diálogo de archivo.
5.8.12.-Control FontDialog
Este control se usa para mostrar el diálogo de fuente y poder acceder a sus
características como tipo de fuente, tamaños, estilos, efectos, etc.
Propiedades
Propiedad
Descripción
Name Generalmente usaremos el prefijo fdg.
AllowScriptChang Controla si el conjunto de caracteres de fuente puede ser
e cambiado.
Color Devuelve el color de fuente seleccionado en el diálogo.
Font Determina la fuente seleccionada en el diálogo. Es un objeto.
FontMustExist Indica si se mostrará un reporte de error al no existir una fuente.
MaxSize Máximo tamaño de la fuente en puntos.
MinSize Mínimo tamaño de la fuente en puntos.
ScriptsOnly Controla si excluirá los caracteres OEM y símbolos.
ShowApply Determina si se verá el botón de Aplicar en el diálogo.
ShowColor Indica si se mostrará el color elegido del diálogo.
ShowEffects Muestra el cuadro de efectos que trae: subrayado, tachado y
color.
ShowHelp Visualiza o no el botón de Ayuda en el diálogo.
Métodos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 235
Método
Descripción
ShowDialog Muestra el diálogo de fuente.
Eventos
Evento
Descripción
Apply Ocurre al dar clic sobre el botón de aplicar del diálogo de fuente.
5.8.13.-Control ColorDialog
Este control se usa para mostrar el diálogo de colores y poder acceder a sus
características como seleccionar un color sólido o personalizado.
Propiedades
Propiedad
Descripción
Name Generalmente usaremos el prefijo cdg.
AllowFullOpen Habilita o no el botón de personalizar colores.
AnyColor Controla si cualquier color puede ser seleccionado.
Color Indica el color seleccionado en el diálogo.
FullOpen Determina si la sección de colores personalizados será
inicialmente vista.
ShowHelp Visualiza o no el botón de Ayuda en el diálogo.
SolidColorOnly Controla si solo los colores sólidos pueden ser seleccionados.
Métodos
Método
Descripción
ShowDialog Muestra el diálogo de colores.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 236
Eventos
Evento
Descripción
HelpRequested Ocurre al dar clic sobre el botón de ayuda del diálogo de color.
5.9- Interfaces
Introducción
Una interface es el medio de comunicación entre 2 entidades, en nuestro caso, la
interface sirve de enlace entre el usuario y la aplicación.
En la evolución de la computación se inicia con interfaces de texto o de consola, las
cuales predominan desde los inicios de la computación hasta casi la mitad de la
década del 80, luego aparecen las interfaces gráficas.
Desde que trabajamos en ambiente Windows, las interfaces han ido evolucionando
de acuerdo a la facilidad del usuario para acceder a los elementos de la aplicación,
y entre las principales interfaces tenemos:
SDI (Single Document Interface): Interface de Simple Documento, muestra una
sola ventana con un cierto documento en la aplicación; el acceso a las ventanas
es secuencial, por lo que no es tan recomendable. Algunas aplicaciones con SDI
son los accesorios de Windows: Bloc de notas, Paint, Wordpad, etc.
MDI (Multiple Document Interface): Interface de Múltiples Documentos,
muestra varios documentos en sus respectivas ventanas, las cuales aparecen
sobre una ventana principal; el acceso a las ventanas es directo porque
generalmente en la ventana padre existe un menú. Algunas aplicaciones con
MDI son los programas de Office: Word y Excel.
TreeView - ListView (Vistas Árbol – Lista): Muestra los elementos de la
aplicación en un árbol (TreeView) y en el lado derecho muestra una lista con los
detalles (ListView); puede mostrarse junto a un SDI como en el caso del
Explorador de archivos de Windows o puede mostrarse junto a un SDI como en
el caso del Enterprise Manager de SQL Server 6 o superior.
Con la evolución de Internet también se distinguen diferentes tipos de interfaces en
el browser, pero que no se tocan en este capítulo, si no que nos centraremos en la
creación de interfaces para aplicaciones Windows.
5.10.-Creando Aplicaciones MDI
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 237
Una aplicación MDI consta de 2 partes: un Formulario MDI Padre y uno o mas
Formularios MDI Hijos, la creación de ambos es muy sencilla en VB .NET y se
explica a continuación:
Creando un Formulario MDI Padre
Para crear un Formulario MDI padre solo hay que configurar la propiedad
IsMDIContainer del formulario a True.
A diferencia de la versión anterior de Visual Basic, esta versión permite colocar
cualquier control WinForm dentro del formulario MDI, pero esto hará que los
formularios hijos se muestren en segundo plano, ya que en primer plano se verán
los controles del formulario MDI padre.
Creando un Formulario MDI Hijo
Para crear un Formulario MDI hijo solo hay que configurar la Propiedad Parent
(disponible solo en tiempo de ejecución) del formulario hijo apuntando al formulario
padre y luego usar el método Show para mostrarlo.
El siguiente código muestra como mostrar un formulario hijo desde un menú:
Protected Sub mnuArchivo_Nuevo_Click(ByVal sender As Object, …)
Dim X As New frmHijo()
[Link] = frmPadre
[Link]()
End Sub
Organizando Formularios MDI Hijos
Si es que desea organizar los formularios MDI hijos se debe usar el método
LayoutMDI del formulario MDI padre junto con una constante de tipo MDILayaout,
que tiene 4 valores: ArrangeIcons, Cascade, TileHorizontal y TileVertical.
A continuación se muestra como ordenar en Cascada los formularios MDI hijos de
un formulario MDI Padre llamado frmPadre:
[Link]([Link])
5.11.- Control de Excepciones - Manejo de errores en Visual –Basic
5.11.1.-Tipos de Errores
Los errores o excepciones se pueden clasificar en 3 tipos:
Errores de Sintaxis: Suceden al escribir código en la aplicación; como por ejemplo una
instrucción mal escrita, omisión de un parámetro obligatorio en una función, etc.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 238
Visual Basic notifica de cualquier error de sintaxis mostrando una marca de subrayado azul
(por defecto) con un comentario indicando la causa del error.
Una ayuda para corregir errores de sintaxis, es usar la sentencia Option Explicit que
fuerce a declarar variables y evitar expresiones inválidas.
Errores Lógicos: Ocurren una vez usada la aplicación y consiste en resultados
inesperados o no deseados; por ejemplo una función que debe devolver el sueldo neto
está devolviendo un valor de cero o negativo, o una subrutina que debe eliminar un
archivo temporal no lo está borrando.
Para corregir este tipo de errores se hace uso de las herramientas de depuración, como
por ejemplo un seguimiento paso a paso, o inspeccionar el valor de una variable o
expresión.
También podemos disminuir errores o excepciones de tipos de datos no deseados usando
la sentencia Option Strict que evita la conversión forzosa y verifica que el tipo de dato
asignado sea del mismo tipo que la variable o función, o que un parámetro pasado sea del
mismo tipo, etc.
Errores en Tiempo de Ejecución: Este tipo de errores suceden en plena ejecución de la
aplicación, después de haber sido compilado el código. No son errores de mala escritura
ni de lógica, sino mas bien de alguna excepción del sistema, como por ejemplo tratar de
leer un archivo que no existe o que está abierto, realizar una división entre cero, etc.
Para controlar los errores en tiempo de ejecución disponemos de los Manipuladores o
Controladores de Error, que evitan la caída del programa y permiten que siga
funcionando. A continuación veremos las formas de implementar el control de este tipo
de errores.
5.11.2.-Formas de Controlar Excepciones
Existen dos formas de controlar errores o excepciones en Visual Basic .NET:
[Link]-Control No Estructurado:
Se implementa usando la sentencia On Error GoTo.
Es la forma como se controla errores en las versiones anteriores a Visual Basic .NET y
consiste en el uso de etiquetas, es decir recurrir a la programación etiquetada, cuando
ocurre algún error toma el control el código que se encuentra a continuación de la
etiqueta.
Existen varias sintaxis o formas de usar la sentencia On Error, tal como se define:
1. On Error Resume Next: Indica que si ocurre un error en tiempo de ejecución el flujo
continúe en la siguiente línea después de la que originó el error.
2. On Error GoTo 0: Deshabilita cualquier Controlador de error, previamente
declarado en el procedimiento actual, configurando este a Nothing.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 239
3. On Error GoTo –1: Deshabilita cualquier error o excepción que ocurra en cualquier
línea del procedimiento actual, configurando este a Nothing.
4. On Error GoTo Etiqueta: Si un error en tiempo de ejecución ocurre envía el control
a la instrucción que está debajo de la etiqueta definida. Es la mejor forma no
estructurada de controlar errores, ya que se puede personalizar mensajes. La forma
de implementar esta sentencia en un procedimiento es:
Inicio Procedimiento()
On Error GoTo <Etiqueta>
<Instrucciones>
Exit Sub
<Etiqueta>:
<Instrucciones>
[Resume ¦ Resume Next ¦ Resume Etiqueta]
Fin Procedimiento
Para salir de la etiqueta, generalmente se usa la instrucción Resume, de 3 formas:
Resume: Vuelve a la instrucción que produjo el error.
Resume Next: Regresa el flujo a la siguiente instrucción después de la que
produjo el error.
Resume Etiqueta: Bifurca el control a una etiqueta definida por el usuario.
Al usar la sentencia On Error GoTo si un error en tiempo de ejecución ocurre el control
es tomado por el código de la Etiqueta y la información del error ocurrido es almacenada
en el Objeto Err, tal como el número del error, su descripción y el origen.
[Link]-Control estructurado
Manejo de excepciones estructuradas
Las excepciones en Visual Basic las podemos controlar usando las instrucciones Try / Catch
/ Finally. Estas instrucciones realmente son bloques de instrucciones, al estilo de If / Else.
Cuando queramos controlar una parte del código que puede producir un error lo incluimos
dentro del bloque Try, si se produce un error, éste lo podemos detectar en el bloque Catch,
por último, independientemente de que se produzca o no una excepción, podemos ejecutar
el código que incluyamos en el bloque Finally, para indicar el final del bloque de control de
excepciones lo haremos con End Try.
Inicio Procedimiento()
Try
<Instrucciones Try>
[Exit Try]
[Catch 1 [<Excepción> [As <Tipo Dato>]] [When <Expresión>]]
<Instrucciones Catch 1>
[Exit Try]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 240
[Catch 2 [<Excepción> [As <Tipo Dato>]] [When <Expresión>]]
<Instrucciones Catch 2>
[Exit Try]
:
:
[Catch n [<Excepción> [As <Tipo Dato>]] [When <Expresión>]]
<Instrucciones Catch n>
[Exit Try]
Finally
<Instrucciones Finally>
End Try
Fin Procedimiento
Cuando creamos una estructura de control de excepciones no estamos obligados a usar los
tres bloques, aunque el primero: Try si es necesario, ya que es el que le indica al compilador
que tenemos intención de controlar los errores que se produzcan. Por tanto podemos crear
un "manejador" de excepciones usando los tres bloques, usando Try y Catch o usando Try y
Finally. Veamos ahora con más detalle cada uno de estos bloques y que es lo que podemos
hacer en cada uno de ellos.
Bloque Try
En este bloque incluiremos el código en el que queremos comprobar los errores.
El código a usar será un código normal, es decir, no tenemos que hacer nada en especial, ya
que en el momento que se produzca el error se usará (si hay) el código del bloque Catch.
Bloque Catch
Si se produce una excepción, ésta la capturamos en un bloque Catch.
En el bloque Catch podemos indicar que tipo de excepción queremos capturar, para ello
usaremos una variable de tipo Exception, la cual pude ser del tipo de error específico que
queremos controlar o de un tipo genérico. Por ejemplo, si sabemos que nuestro código
puede producir un error al trabajar con ficheros, podemos usar un código como este:
Try
' código para trabajar con ficheros, etc.
Catch ex As [Link]
' el código a ejecutar cuando se produzca ese error
End Try
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 241
Si nuestra intención es capturar todos los errores que se produzcan, es decir, no queremos
hacer un filtro con errores específicos, podemos usar la clase Exception como tipo de
excepción a capturar. La clase Exception es la más genérica de todas las clases para manejo de
excepciones, por tanto capturará todas las excepciones que se produzcan.
Try
' código que queremos controlar
Catch ex As Exception
' el código a ejecutar cuando se produzca cualquier error
End Try
Aunque si no vamos usar la variable indicada en el bloque Catch, pero queremos que no se
detenga la aplicación cuando se produzca un error, podemos hacerlo de esta forma:
Try
' código que queremos controlar
Catch
' el código a ejecutar cuando se produzca cualquier error
End Try
Varias capturas de errores en un mismo bloque Try/Catch
En un mismo Try podemos capturar diferentes tipos de errores, para ello podemos incluir
varios bloques Catch, cada uno de ellos con un tipo de excepción diferente.
Es importante tener en cuenta que cuando se produce un error y usamos varios bloques Catch,
Visual Basic buscará la captura que mejor se adapte al error que se ha producido, pero siempre
lo hará examinando los diferentes bloques Catch que hayamos indicado empezando por el
indicado después del bloque Try, por tanto deberíamos poner las más genéricas al final, de
forma que siempre nos aseguremos de que las capturas de errores más específicas se
intercepten antes que las genéricas.
Evaluación condicional en un bloque Catch
Además de indicar la excepción que queremos controlar, en un bloque Catch podemos añadir
la cláusula When para evaluar una expresión. Si la evaluación de la expresión indicada después
de When devuelve un valor verdadero, se procesará el bloque Catch, en caso de que devuelva
un valor falso, se ignorará esa captura de error.
Esto nos permite poder indicar varios bloques Catch que detecten el mismo error, pero cada
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 242
una de ellas pueden tener diferentes expresiones indicadas con When.
En el siguiente ejemplo, se evalúa el bloque Catch solo cuando el valor de la variable y es
cero, en otro caso se utilizará el que no tiene la cláusula When:
Dim x, y, r As Integer
Try
x = CInt(InputBox(“Introduzca un numero “))
y = CInt(InputBox(“Introduzca otro numero “))
r =x\y
[Link]("El resultado es: " & r)
Catch ex As Exception When y = 0
[Link]("No se puede dividir por cero.")
Catch ex As Exception
[Link]([Link])
End Try
Bloque Finally
En este bloque podemos indicar las instrucciones que queremos que se ejecuten, se produzca
o no una excepción. De esta forma nos aseguramos de que siempre se ejecutará un código, por
ejemplo para liberar recursos, se haya producido un error o no.
Nota:
Hay que tener en cuenta de que incluso si usamos Exit Try para salir del bloque de control de
errores, se ejecutará el código indicado en el bloque Finally.
Captura de errores no controlados
Como es lógico, si no controlamos las excepciones que se puedan producir en nuestras
aplicaciones, estas serán inicialmente controladas por el propio runtime de .NET, en estos
casos la aplicación se detiene y se muestra el error al usuario. Pero esto es algo que no
deberíamos consentir, por tanto siempre deberíamos detectar todos los errores que se
produzcan en nuestras aplicaciones, pero a pesar de que lo intentemos, es muy probable que
no siempre podamos conseguirlo. Por suerte, en Visual Basic tenemos dos formas de
interceptar los errores no controlados:
La primera es iniciando nuestra aplicación dentro de un bloque Try/Catch, de esta forma,
cuando se produzca el error, se capturará en el bloque Catch.
La segunda forma de interceptar los errores no controlados es mediante el evento:
UnhandledException, disponible por medio del objeto [Link].
Este evento se "dispara" cuando se produce un error que no hemos interceptado, por tanto
podríamos usarlo para prevenir que nuestra aplicación se detenga o bien para guardar en un
fichero .log la causa de dicho error para posteriormente actualizar el código y prevenirlo. Ya
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 243
que cuando se produce el evento UnhandledException, podemos averiguar el error que se ha
producido e incluso evitar que la aplicación finalice. Esa información la obtenemos mediante
propiedades expuestas por el segundo parámetro del evento, en particular la propiedad
Exception nos indicará el error que se ha producido y por medio de la propiedad
ExitApplication podemos indicar si terminamos o no la aplicación.
Nota:
Cuando ejecutamos una aplicación desde el IDE, los errores no controlados siempre se
producen, independientemente de que tengamos o no definida la captura de errores desde el
evento UnhandledException. Ese evento solo se producirá cuando ejecutemos la aplicación
fuera del IDE de Visual Basic
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 244
6.- Programación Orientada a Objeto (POO) en Visual Basic página 170
6.1.- Que es una clase
6.2.- Crear la primea clase
6.3.- Propiedades de solo lectura y escritura
6.4.- Agregar métodos a una clase
6.5.- Agregar evento a una clase
6.6.- Crear una instancia de clase
6.7.- Como utilizar los constructores
6.8.- Como utilizar los destructores
6.9.- Como utilizar los miembros datos compartidos
6.10.- Como utilizar los métodos compartidos
6.11.- Polimorfismo en Visual Basic NET
6.12.- Probar controladores de eventos
6.13.- Herencia de clases en Visual Basic NET
7.- Impresión en Visual Basic página 210
7.1.- La solución: Como imprimir en .NET
7.2.- Las clases para imprimir en .NET
Clase PrintDocument
Clase PrintSetting
Clase PrintDialog
Clase PrintPreviewDialog
Clase PrintPreviewControl
7.4.- Conclusión para imprimir en VB net
7.5.-Hacer Crystal Report con DataSet en Visual [Link]
7.6.- Reportes en visual [Link] con Crystal Report
7.7.- Como crear un reporte (ReportViewer)
7.8.- Reportes con datos agrupados (Reporting Service)
7.9.- Dar formato a un reporte (Reporting Service)
8.- Formularios de interfaz múltiple (MDI) página 258
8.1.- Aplicaciones estilo SDI
8.2.- Aplicaciones estilo MD
8.3.- Creación de menú de tipo ventana en formularios MDI
8.4.- Bloqueo de opciones de menús en formularios MDI
8.5.- Recorrer formularios hijos de un MDI
8.6.- Comportamiento no modal
8.7.- Modal de un formulario
8.8.- Controles de cuadro de diálogos de sistema
8.9.- Formularios dependientes
8.10.- Validación de controles.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 245
6.- PROGRAMACIÓN ORIENTADA A OBJETOS (POO) DE
VISUAL [Link]
Introducción:
Todo .NET Framework está basado en clases (u objetos). A diferencia de las versiones
anteriores de Visual Basic, la versión .NET de este lenguaje basa su funcionamiento casi
exclusivamente en las clases contenidas en .NET Framework, además casi sin ningún tipo de
limitación.
La POO es una evolución de la programación por procedimientos llamada también
estructurada. Se basaba en funciones y procedimientos y el código que controlaba el flujo de
las llamadas a estos. En Visual Basic, sobre todo en versiones anteriores se sigue
programando mucho así. A veces por desconocimiento y otras por "miedo" no se da el salto
a la POO, aunque un programador con experiencia en VB puede hacer magníficas
aplicaciones sin utilizar la POO (y sin aprovecharse de sus ventajas), y sobre todo, en un
tiempo relativamente reducido.
6.1.-¿Qué es una clase?
Los programas de Visual Basic se generan con objetos como formularios y controles. Los
objetos también se pueden utilizar para representar cosas reales como personas, equipos
informáticos o incluso algo más abstracto, como una cuenta bancaria.
Una clase es simplemente una representación de un tipo de objeto. Se puede pensar en ella
como un plano que describe el objeto. Así como un plano puede utilizarse para construir
varios edificios, una clase podemos usarla para crear varias copias de un objeto.
Por ejemplo, el control TextBox lo define una clase TextBox, que define su aspecto y sus
funciones. Cada vez que arrastramos un control TextBox a un formulario, realmente está
creando una nueva instancia de la clase TextBox.
Cada control TextBox es una copia exacta, aunque distinta, de la clase que lo define, la clase
TextBox. Puesto que cada objeto es una "instancia" independiente de una clase, la acción de
crear una clase se denomina creación de instancias.
Hasta ahora hemos agregado los controles TextBox a su formulario arrastrándolos desde el
Cuadro de herramientas, pero también puede crear instancias de un objeto TextBox en su
código si utiliza la palabra clave New.
Dim Textbox1 As New TextBox
¿Qué hay dentro de una clase?
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 246
Todos los objetos tienen propiedades que describen sus atributos, métodos que definen sus
acciones y eventos que definen sus respuestas. Igualmente, la clase que define un objeto tiene
sus propias propiedades, métodos y eventos (a veces llamados miembros) que se pasan a
todas las instancias de esa clase.
Por ejemplo, una clase que representa una cuenta bancaria podría tener propiedades como:
NumeroCuenta
BalanceCuenta
CtaBancaria
NumeroCuenta
Métodos como: CambioBalanc
BalanceCuenta
CalculaInteres () e
Eventos : Hacer click
CalculaInteres()
CambioBalance.
Una vez creada la instancia de un objeto de cuenta bancaria, puede tener acceso a sus
propiedades, métodos y eventos de igual manera que si se tratara de un objeto TextBox.
Algunos miembros de una clase son privados; sólo se tiene acceso a ellos mediante código
dentro de la clase. Por ejemplo, una clase de cuenta bancaria puede tener un método para
calcular un saldo. Lo lógico es permitir que un programa lea ese balance pero no que pueda
cambiarlo directamente.
Puede ocultar los miembros de una clase si los declara como Private o exponerlos si los
declara como Public. También puede permitir el acceso a una propiedad y a la vez impedir
que el programa cambie su valor declarándolo como ReadOnly.
El código siguiente muestra cómo podría ser una ejemplo de clase llamada CuentaBanco:
'Declaramos la clase CuentaLimpia
Class CuentaLimpia
'La hacemos privada
Private NumeroCuenta As String
Private BalanceCuenta As Decimal
'Y la ponemos publica para que calcule el balance
Public Sub ActualizaBalance()
End Sub
ReadOnly Property Balance() As Decimal
Get
Return BalanceCuenta
End Get
End Property
End Class
6.2.- Crear la primera clase
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 247
Una de las mejores razones para utilizar clases es que una vez que ha creado una clase para
cierto tipo de objeto, se puede reutilizar esa clase en cualquier proyecto.
Por ejemplo, muchos de los programas que escribimos pueden involucrar personas: Un
programa de administrador de contactos para los contactos comerciales o un programa para
realizar un seguimiento de empleados. Aunque los programas pueden ser considerablemente
diferentes, los atributos que se aplican a cada persona serían los mismos. Todas tienen
nombre, edad, dirección, número de teléfono, etc.
Para empezar a ver mejor crear clases,y usarlas crearemos una clase que represente a una
persona; Podemos guardar esta clase y utilizarla en otros programas que escribamos en el
futuro.
Las clases se pueden crear de tres maneras: como parte del código en un módulo de
formulario en un proyecto de aplicación para Windows, como un módulo de clase separado
agregado a un proyecto de aplicación para Windows o como un proyecto de bibliotecas de
clase independiente.
Crear clases
Al hacer doble clic en un formulario y abrir el Editor de código se ve algo parecido a lo
siguiente:
Public Class Form1
Private Sub Form1_Load...
…
End Sub
End Class
Podemos observar que el formulario realmente es una clase, marcada por instrucciones
Class y End Class y cualquier código que se haya escrito entre las dos instrucciones es parte
de la clase. Aunque de manera predeterminada un módulo de formulario contiene sólo una
clase única, puede crear módulos adicionales agregando código debajo de la instrucción End
Class, tal como se ilustra a continuación:
Public Class Form1
' El código de nuestro Form va AQUI
End Class
Public Class MiPrimeraClase
' El código de nuestra clase va AQUI
End Class
La desventaja de crear clases de esta manera es que sólo están disponibles dentro del proyecto
donde se crearon. Si deseamos compartir una clase con otros proyectos, puede colocarla en
un módulo de clase.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 248
Módulos de clase
Un módulo de clase es un archivo de código, separado del resto, que contiene una o más
clases. Como es un archivo independiente, se puede reutilizar en otros proyectos.
Los módulos de clase se pueden crear de dos maneras:
Como un módulo agregado a un proyecto de aplicación para Windows.
Como un proyecto de bibliotecas de clase independiente
Puede agregar un nuevo módulo de clase a un proyecto existente seleccionando Clase en el
cuadro de diálogo Agregar nuevo elemento, disponible en el menú Proyecto. Para trabajar
en durante el tutorial, crearemos un proyecto de bibliotecas de clases independientes.
Cómo crear un proyecto de de biblioteca de clases:
En el menú Archivo, seleccionamos Nuevo proyecto.
En el panel Plantillas, del cuadro de diálogo Nuevo proyecto, hacemos clic en
Biblioteca de clases.
En el cuadro Nombre, escribimos Persons y hacemos clic en Aceptar.
Se abrirá un nuevo proyecto de bibliotecas de clase y el Editor de código mostrará el
módulo de clase [Link].
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 249
En el Explorador de soluciones, hacemos clic con el botón secundario del ratón en
[Link] y seleccionamos Cambiar nombre y, a continuación, cambiamos el nombre
a "[Link]".
Observamos que el nombre en el Editor de código también cambia a [Link].
En el menú Archivo, elegimos Guardar todo.
En el cuadro de diálogo Guardar proyecto, hacemos clic en Guardar.
Nota: En lugar de guardar el proyecto en la ubicación predeterminada, podríamos crear un
directorio en el cual podemos almacenar todas las clases para reutilizarlas mas tarde. Se
puede especificar esa carpeta en el campo Location del cuadro de diálogo Guardar proyecto
antes de guardar.
De momento, mantendremos el proyecto abierto, porque lo utilizaremos durante todo el
tutorial, e iremos ampliando la información.
Agregar propiedades a una clase
Todos los objetos tienen atributos y las propiedades representan atributos. Antes, hicimos la
clase "Persons", que representa a una persona; las personas tienen atributos como el nombre
y la edad, por lo que la clase Persons necesita propiedades que representen dichos atributos.
Se pueden agregar propiedades a una clase de dos maneras:
Como campo.
Como procedimiento de propiedad.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 250
También podemos determinar cómo funciona una propiedad utilizando los modificadores
Public, ReadOnly o WriteOnly.
Campos y procedimientos de propiedad
Los campos son variables públicas dentro de una clase que se pueden establecer o leer desde
fuera de la clase. Resultan de utilidad para propiedades que no se tienen que validar, por
ejemplo, un valor "Boolean" (True o False).
En el caso de la clase Personas, se puede tener una propiedad Boolean denominada Casado,
que especifica si una persona está soltera o casada, puesto que hay sólo dos valores posibles.
Para agregar un campo a una clase, el código podría ser como el que sigue.
Public Casado As Boolean
La mayoría de las propiedades, sin embargo, son más complejas; en la mayor parte de los
casos utilizaremos procedimientos de propiedad para agregar una propiedad a una clase.
Los procedimientos de propiedad tienen tres partes:
Una declaración de una variable privada para almacenar el valor de la propiedad.
Un procedimiento Get que expone el valor.
Un procedimiento Set que, como indica su nombre, establece el valor en la clase.
Por ejemplo, un procedimiento de propiedad para una propiedad Name, de la clase Personas,
podría ser como el que sigue:
Private ValorNombre As String
Public Property Nombre() As String
Get
Nombre = ValorNombre Recibe el dato en la variable ValorNombre
End Get de
Set(ByVal valor As String) La clase
ValorNombre = valor
End Set
End Property
Devuelve el contenido de la variable
ValorNombre
La primera línea de código declara una variable String privada, ValorNombre que almacenará
el valor de la propiedad. El procedimiento de propiedad en sí comienza con Public Property
y termina con End Property.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 251
El procedimiento Get contiene el código que se ejecutará cuando desee leer su valor; por
ejemplo, si lee la propiedad [Link], el código devolverá el valor almacenado en
la variable ValorNombre
El procedimiento Set contiene código que se utiliza para asignar un nuevo valor a la variable
ValorNombre usando un valor pasado como argumento Valor. Por ejemplo, si escribimos el
código
[Link] = "Carlos"
El valor String Carlos se pasará como argumento Valor; el código del procedimiento Set lo
asignará a la variable ValorNombre para su almacenamiento.
¿Por qué complicarnos tanto, en lugar de utilizar un campo que represente la propiedad
Nombre? En el mundo real, hay ciertas reglas para los nombres: por ejemplo, los nombres
normalmente no contienen números. Puede agregar código al procedimiento Set para
comprobar el argumento Valor y devolver un error si contiene números.
Siguiendo con la Clase Personas, ahora agregaremos un campo y tres propiedades:
1. Abrimos el proyecto Personas que hicimos en la sección anterior. Si no lo guardaste,
primero deberás regresar a la sección anterior, crear la primera clase, y realizar hasta
el final los procedimientos de esa sección.
2. En el Explorador de soluciones, seleccionamos [Link] y en el menú Ver
elegimos Código.
3. Agregamos el siguiente código de declaración debajo de la línea Public Class
Personas.
Private ValorPrimerNombre As String
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 252
Private ValorSegundoNombre As String
Private ValorApellido As String
Public Casado As Boolean
4. Agregamos los siguientes procedimientos de propiedad debajo del código de
declaración anterior.
Public Property PrimerNombre() As String
Get
PrimerNombre = ValorPrimerNombre
End Get
Set(ByVal valor As String)
ValorPrimerNombre = Valor
End Set
End Property
Public Property SegundoNombre() As String
Get
SegundoNombre = ValorSegundoNombre
End Get
Set(ByVal valor As String)
ValorSegundoNombre = Valor
End Set
End Property
Public Property Apellido() As String
Get
Apellido = ValorApellido
End Get
Set(ByVal valor As String)
ValorApellido = Valor
End Set
End Property
Quedará así:
5. En el menú Archivo, elegimos Guardar todo para guardar el trabajo.
Propiedades de sólo lectura y escritura
A veces una propiedad se establece una vez y no cambia nunca mas durante la ejecución del
programa. Por ejemplo, una propiedad que representa un número de empleado nunca debe
cambiar, de modo que otro programa si lo pueda leer, pero no se permitirá que ese programa
cambie su valor.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 253
La palabra clave ReadOnly se utiliza para especificar que un valor de propiedad se pueda
leer pero no modificar.
Nota: Si intentamos asignar un valor a una propiedad ReadOnly, aparecerá un error en el
Editor de código.
Para crear una propiedad de sólo lectura, deberemos crear un procedimiento de propiedad
con un procedimiento Get, pero sin procedimiento Set, como se muestra a continuación.
Private IDValue As Integer
ReadOnly Property ID() As Integer
Get
ID = IDValue
End Get
End Property
De igual forma, la palabra clave WriteOnly permite establecer un valor de propiedad pero
no permite que se lea; por ejemplo, no permite que otros programas lean una propiedad de
contraseña. Podemos utilizar ese valor para realizar acciones dentro de la clase, pero deseará
que sigan siendo privadas.
Para crear una propiedad de sólo escritura, se creará una propiedad con un procedimiento Set
pero sin procedimiento Get, como a continuación:
Private passwordValue As String
WriteOnly Property Password() As String
Set(ByVal value As String)
passwordValue = value
End Set
End Property
Los procedimientos de propiedad ReadOnly y WriteOnly también son útiles cuando
deseamos tomar un valor de propiedad y convertirlo en un valor diferente. Por ejemplo,
pensemos en la edad de una persona. A diferencia del nombre, la edad cambia con el tiempo,
si ha asignado la edad a una clase y la lee de nuevo un año después, sería incorrecta.
En la clase Persons, podemos evitarlo agregando dos propiedades: una propiedad "WriteOnly
BirthYear" que representa el año de nacimiento, que nunca cambia, y una propiedad
"ReadOnly Age" que devuelve un valor calculando la diferencia entre el año en curso y el
año de nacimiento.
Siguiendo con la Clase Persons, ahora agregaremos propiedades ReadOnly y WriteOnly a
la clase:
1. Agregamos el siguiente código de declaración debajo de las otras declaraciones en la
parte superior del módulo de clase.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 254
Private birthYearValue As Integer
2. Introducimos los siguientes procedimientos de propiedad debajo del código de
declaración.
WriteOnly Property BirthYear() As Integer
Set(ByVal value As Integer)
birthYearValue = value
End Set
End Property
ReadOnly Property Age() As String
Get
Age = [Link] – birthYearValue
End Get
End Property
3. En el menú Archivo, elegimos Guardar todo para guardar el trabajo.
6.4.- Agregar métodos a una clase
Agregaremos métodos a una clase, para que puedan realizar acciones. Vimos que la mayoría
de los objetos tienen acciones que pueden realizar; estas acciones se conocen como
métodos.
La clase Persons que creamos en la sección anterior,tiene muchas acciones que pueden
realizar las personas y, estas acciones se pueden expresar como métodos de clase.
Métodos de una clase
Los métodos de una clase son simplemente procedimientos Sub o Function, declarados en la
clase.
Por ejemplo, una clase Cuenta puede tener un procedimiento Sub denominado Recalcular,
que actualizará el balance o un procedimiento Function denominado CurrentBalance para
devolver el último balance.
El código para declarar esos métodos puede ser similar al siguiente:
Public Sub Recalcular()
'Aqui el codigo para recalcular Cuenta.
End Sub
Ejemplo:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 255
Public Function BalanceCuenta(ByVal AccountNumber As Integer) As Double
'Codigo para volver a Balance
End Function
Si bien la mayoría de los métodos de clase son públicos, también se pueden agregar métodos
que sólo la clase en sí puede utilizar. Por ejemplo, la clase Personas puede tener su propia
función para calcular la edad de una persona. Si declara la función como Private, no se puede
ver o llamar desde fuera de la clase.
El código para una función privada puede ser similar a éste otro:
Private Function CalcuEdad(ByVal year As Integer) As Integer
CalcuAge = [Link] - year
End Function
Más tarde podremos cambiar el código que calcula el valor CalcAge y el método seguirá
funcionando bien sin cambiar ningún código que utilice el método. Ocultar el código que
realiza el método, se conoce como la "encapsulación", ya explicada al comienzo.
Ahora, para agregar un método a la clase Persons, hacemos lo siguiente:
Abrimos el proyecto Personas (si no lo tenemos abierto ya de antes) que hicimos en
las secciones anteriores. Si no lo guardaste, o no lo creaste, primero deberás volver a
las secciones anteriores, agregar propiedades a la clase, y completar los
procedimientos.
En el Explorador de soluciones, seleccionamos [Link] y, en el menú Ver,
hacemos clic en Código. Agregamos el siguiente código bajo los procedimientos de
propiedad.
Public Function NombreCompleto() As String
If ValorSegundoNombre <> "" Then
NombreCompleto = ValorPrimerNombre & " " &
ValorSegundoNombre & " " & ValorApellido
Else
NombreCompleto = ValorPrimerNombre & " " &
ValorApellido
End If
End Function
Private Function CalcuEdad(ByVal year As Integer) As Integer
CalcuEdad = [Link] - year
End Function
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 256
Modificamos el código en el procedimiento de la propiedad Age para utilizar la
función privada:
ReadOnly Property Age() As String
Get
'Age = [Link] – birthDateValue
Age = CalcuEdad(birthYearValue)
End Get
End Property
Antes, el código era así:
ReadOnly Property Age() As String
Get
Age = [Link] – birthYearValue
End Get
End Property
En el menú Archivo, hacemos clic en Guardar todo para guardar el trabajo.
6.5.- Agregar eventos a una clase
Un programa puede responder a eventos externos, como por ejemplo, un usuario que hace
clic en un botón. En esta sección, obtendremos información sobre cómo agregar eventos a
una clase.
Primero, debemos declarar el evento.
A continuación, debemos provocarlo.
Provocar un evento significa que estamos señalizando la aparición del evento. Para agregar
un evento a una clase, lo declaramos con la instrucción Event. Ésto indica que el objeto
puede provocar el evento que especificamos.
Por ejemplo, quizás deseemos agregar un evento AgeCalculated a la clase Persons que
hicimos. Podemos provocar a continuación el evento en el método CalcAge. Después de
hacer esto, cuando se llama al método, podemos ejecutar algún código adicional en cuanto
se haya calculado la edad de la persona.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 257
Para agregar un evento a la clase Persons
Abrimos el proyecto Persons.
En el Explorador de soluciones, seleccione [Link] y, en el menú Ver, hacemos
clic en Código.
Agregamos el siguiente código encima de los procedimientos de propiedad.
Public Event AgeCalculated(ByVal Age As Single)
En el método CalcAge, reemplazamos el código existente por el siguiente código para
provocar el evento.
Private Function CalcAge(ByVal year As Integer) As Integer
Dim Age = [Link] - year
RaiseEvent AgeCalculated(Age)
CalcAge = [Link] - year
End Function
En el menú Archivo, hacemos clic en Guardar todo para guardar el trabajo.
Probar una clase
Creamos una clase llamada "Persons" y le proporcionamos propiedades, métodos y eventos.
Lo que hemos hecho hasta ahora es agregar código, ahora es el momento de utilizar la clase
Persons y asegurarse de que funciona según lo esperado.
6.6.- Crear una instancia de una clase
Los formularios y controles son en realidad clases; cuando arrastramos un control Button a
un formulario, estamos creando realmente una instancia de la clase Button.
También podemos crear instancias de cualquier clase en el código utilizando una declaración
con la palabra clave New. Por ejemplo, para crear una nueva instancia de la clase Button,
agregaremos el código siguiente.
Dim aButton As New Button
Otro ejemplo:
'Declarar e iniciar objeto
Dim objEmpleado As Empleado
objEmpleado = New Empleado()
Para utilizar y probar la clase Persons, debemos crear primero un proyecto de prueba y
agregar una referencia al módulo de clase.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 258
Vemos como crear un proyecto de prueba para la clase Persons
Abrimos el proyecto Persons que creamos en las secciones anteriores.
En el menú Archivo, elegimos Agregar y, a continuación, hacemos clic en Nuevo
proyecto.
En el panel Plantillas, en el cuadro de diálogo Nuevo proyecto, hacemos clic en
Aplicación de Windows Forms.
En el cuadro Nombre, escribimos PersonsTest y hacemos clic en Aceptar.
Se agregará un nuevo proyecto de Windows Forms al Explorador de soluciones y
aparecerá un nuevo formulario.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 259
En el Explorador de soluciones, seleccionamos el proyecto PersonsTest y, en el menú
Proyecto, hacemos clic en Establecer como proyecto de inicio.
En el Explorador de soluciones, seleccionamos el proyecto PersonsTest y, en el menú
Proyecto, hacemos clic en Agregar referencia.
Aparecerá el cuadro de diálogo Agregar referencia.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 260
Hacemos clic en la ficha Proyectos, seleccionamos Personas y hacemos clic en
Aceptar.
Hacemos doble clic en el formulario para abrir el editor de código y escribimos la
siguiente declaración justo debajo de la línea Public Class Form1.
Dim person1 As New [Link]()
Esto declara una nueva instancia de la clase Persons.
Quizás se preguntén por qué tuvimos que escribir dos veces Persons, pues porque la
primera instancia es el módulo de clase [Link] y la segunda instancia es la clase
Persons de ese módulo.
En el menú Archivo, hacemos clic en Guardar todo.
El siguiente paso es agregar una interfaz de usuario y un código que utilice la clase Persons.
Agregaremos cuadros de texto donde el usuario especificará los valores para cada una de las
propiedades (excepto la propiedad de sólo lectura "Age"), una casilla para el campo
"Married" y botones para probar cada uno de los métodos públicos.
Para probar la clase Personas:
En el Explorador de soluciones, seleccionamos Form1 y, en el menú Ver, hacemos
clic en Diseñador.
En el Cuadro de herramientas, arrastramos cuatro controles TextBox, un control
CheckBox y dos controles Button al formulario.
Seleccionamos el primer control Button y, a continuación, en la ventana Propiedades
establecemos la propiedad Text en Update.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 261
Seleccionamos el segundo control Button y en la ventana Propiedades establecemos
la propiedad Text en Full Name.
Hacemos doble clic en el primer botón (Update) para abrir el Editor de código y en
el controlador de eventos Button1_Click, agregamos el siguiente código:
[Link] = [Link]
[Link] = [Link]
[Link] = [Link]
[Link]ños = [Link]
[Link] = [Link]
En el controlador de eventos Button2_Click, agregamos lo siguiente:
MsgBox([Link])
MsgBox(CStr([Link]) & " años")
If [Link] = True Then
MsgBox([Link] & " es casado")
Else
MsgBox([Link] & " es soltero")
End If
Presionamos F5 para ejecutar el proyecto y mostrar el formulario:
-En el primer cuadro de texto, escribimos nuestro nombre.
-En el segundo cuadro de texto, escribimos nuestro segundo nombre.
-En el tercer cuadro de texto, escribimos nuestro apellido.
-En el cuarto cuadro de texto, escribimos el año de nuestro nacimiento con
cuatro dígitos (por ejemplo, 1983).
-Activamos la casilla de si estamos casados/as.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 262
Hacemos clic en el botón "Update" para establecer las propiedades de la clase y clic
en el botón "Full Name".
Se muestran tres cuadros de mensaje. Estos cuadros de mensaje muestran su nombre
completo, edad y estado civil.
En el menú Archivo, hacemos clic en Guardar todo.
Segundo ejemplo completo de programa de uso de clase en Visual Basic
NET
Ejemplo Calcular el salario de un empleado, información a sacar por pantalla Nombre del
empleado y Salario semanal, datos conocidos: nombre, número de horas trabajadas y pago
por hora del empleado
El salario se calcula de la manera siguiente:
Si el número de horas trabajadas es mayor que 40, el excedente de 40 se paga al doble de la
cuota por hora, en caso de no ser mayor que 40 se paga a la cuota por hora normal.
Realicemos la solución de acuerdo al modelo-vista-controlador
Solución:
1.- programamos la clase empleado en el módulo de clase
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 263
Public Class Empleado
'Declaraciones de Datos
Private NombreEmpleado As String
Private HorasTrabajadas As Integer
Private PagoHora As Double
Private Salario As Double
Public ReadOnly Property obtenerNombre() As String
' bloque Get obtener para devolver el valor de la propiedad
Get
Return NombreEmpleado
End Get
End Property
Public WriteOnly Property establecerNombre() As String
' bloque Set (Establecer) para asignar valor a la propiedad
Set(ByVal Value As String)
NombreEmpleado = Value
End Set
End Property
Public ReadOnly Property obtenerHoras() As Integer
' bloque Get para devolver el valor de la propiedad
Get
Return HorasTrabajadas
End Get
End Property
Public WriteOnly Property EstablecerHoras() As Integer
' bloque Set para establecer valor a la propiedad
Set(ByVal hora As Integer)
HorasTrabajadas = hora
End Set
End Property
Public WriteOnly Property EstablecerPago() As Double
' bloque Get para devolver el valor de la propiedad
Set(ByVal value As Double)
PagoHora = value
End Set
End Property
End class
2.- Programamos el form como clase principal. la clase Ejecuta
Rem Clase Ejecuta Empleado (Esta se encuentra en el Form)
Public Class Form1
Public NEmple As String
Dim HT As Double
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 264
Dim PagoH As Double
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
'Declarar e iniciar objeto
Dim objEmpleado As Empleado
objEmpleado = New Empleado()
'Trasladar datos a las variables
NEmple = [Link]
HT = Val([Link])
PagoH = Val([Link])
'Metodos establecer
[Link] = NEmple
[Link] = PagoH
[Link] = HT
'Metodo Calcular
[Link]()
'Metodos obtener datos
[Link] = "Empleado " & UCase([Link])
[Link] = "Pago por hora " & [Link]
[Link] = "Salario " & [Link]
End Sub
Private Sub Button2_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
End
End Sub
End Class
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 265
6.7.-Cómo utilizar los constructores
Introducción
En Visual Basic .NET, la inicialización de nuevos objetos se controla utilizando
constructores. Para crear un constructor para una clase, se crea un procedimiento denominado
Sub New en cualquier lugar de la definición de la clase.
Características de Sub New
El constructor Sub New tiene las siguientes características:
El código del bloque Sub New siempre se ejecutará antes de cualquier otro código de una
clase.
El constructor Sub New solo se ejecutará una vez, cuando se cree un objeto.
Ejemplo de Sub New
El siguiente ejemplo muestra cómo utilizar el constructor Sub New:
Public Sub New( )
' Perform simple inicialización
intValue = 1
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 266
La siguiente línea de código crea un objeto desde una clase denominada BankAccount, ya
definida en la aplicación.
Dim myAccount As New BankAccount( )
Podemos sobrecargar New y crear tantos constructores de clases como sean necesarios. Esto
resulta útil si deseamos inicializar nuestro objeto cuando lo creemos.
Sobrecarga de constructores
Podemos sobrecargar constructores del mismo modo que se sobrecarga cualquier otro
método de una clase. No obstante, no podemos utilizar la palabra clave Overloads cuando
sobrecargamos constructores. El siguiente ejemplo muestra cómo sobrecargar New y crear
múltiples constructores de clase:
Class CuentaBanco
Private balance as Double
Sub New( )
' Inicializar balance
balance = 0.0
End Sub
Sub New(ByVal cantidad As Double)
balance = cantidad
End Sub
End Class
Uno de los constructores del ejemplo anterior toma un parámetro. Si estamos creando un
objeto desde tal clase, podemos incluir sus parámetros en la declaración. El siguiente ejemplo
muestra cómo invocar el método New que toma un parámetro.
Dim miCuenta As New CuentaBanco(120.00)
Para escribir nuestros propios constructores de clase, crearemos un método con el nombre
New( ), como vemos en el Código. En dicho ejemplo, al instanciarse un objeto de
la clase Empleado, se asignará a una de sus propiedades la fecha actual.
Interfase grafica cliente
Public class form1…..
Private Sub Botton_Click …
Dim loEmp As Empleado
loEmp = New Empleado()
MsgBox("El objeto se ha creado el día " & [Link])
End Sub
End class
Public Class Empleado
Private mdtFechaCrea As Date
Public Property FechaCrea() As Date
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 267
Get
Return mdtFechaCrea
End Get
Set(ByVal Value As Date)
mdtFechaCrea = Value
End Set
End Property
' método constructor
Public Sub New()
' asignamos un valor inicial a una variable de propiedad
[Link] = Now
End Sub
End Class
Al igual que ocurre en un método normal, New( ) admite parámetros; esto nos sirve
para asignar valores de inicio al objeto en el momento de su instanciación. La
denominación para este tipo de métodos es constructor parametrizado. El Código nos
muestra una variación del fuente anterior, utilizando un constructor de este tipo.
Interfase grafica cliente
Public class form1…..
Private Sub Botton_Click …
Dim loEmp As Empleado
loEmp = New Empleado("5/7/2002")
MsgBox("El objeto se ha creado el día "& [Link])
' este es otro modo de instanciar un objeto con un constructor
parametrizado
Dim loEmp2 As New Empleado("08/4/2002")
End Sub
End Class
Public Class Empleado
Private mdtFechaCrea
Public Property FechaCrea() As Date
Get
Return mdtFechaCrea
End Get
Set(ByVal Value As Date)
mdtFechaCrea = Value
End Set
End Property
' método constructor con parámetro
Public Sub New(ByVal ldtFecha As Date)
' asignamos el valor del parámetro a una variable de propiedad
[Link] = ldtFecha
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 268
End Class
Combinando las características de métodos constructores junto a las de sobrecarga,
podemos crear un conjunto de constructores sobrecargados para la clase.
Public Class Empleado
Public psNombre
Public psApellidos
Public psCiudad
Private mdtFechaCre
' en este constructor sin parámetros, asignamos la fecha actual
Public Sub New()
mdtFechaCrea = Now()
End Sub
' en este constructor, asignamos valores a todos los campos de la clase
Public Sub New(ByVal lsNombre As String, ByVal lsApellidos As String, ByVal
lsCiudad As String)
psNombre = lsNombre
psApellidos = lsApellidos
psCiudad = lsCiudad
End Sub
End Class
6.8.-Cómo utilizar los destructores
Introducción
En Visual Basic .NET, podemos controlar qué ocurre durante la destrucción de objetos
utilizando procedimientos denominados destructores.
Finalize y Dispose
El sistema invoca al destructor Finalize antes de liberar el objeto. Puede utilizarse para
limpiar recursos abiertos, como conexiones a bases de datos, o para liberar otros recursos.
Sin embargo, existe una demora entre el momento en que un objeto pierde su alcance y el
momento en que se invoca al destructor Finalize.
La ejecución de Sub Finalize provoca una ligera pérdida en el rendimiento, por ello
únicamente debería definirse un método Sub Finalize cuando sea necesario liberar objetos
explícitamente.
Visual Basic .NET permite un segundo tipo de destructor, denominado Dispose, que puede
ser invocado explícitamente en cualquier momento para liberar recursos de forma inmediata.
Dispose no se incluye en el ámbito de este curso. Si desea más información sobre Dispose,
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 269
puede consultar “Duración de los objetos: cómo se crean y destruyen” en la documentación
de Visual Studio .NET.
Nota
Ejemplo de Sub Finalize
El siguiente ejemplo muestra cómo utilizar el destructor Finalize:
Protected Overrides Sub Finalize( )
' Puedo cerrar conecciones u otros recursos
[Link]
End Sub
Protected es un modificador de acceso que establece el nivel de accesibilidad.
6.9.-Cómo utilizar miembros de datos compartidos
Introducción
En Visual Basic .NET, los miembros de datos compartidos pueden utilizarse para permitir
que múltiples instancias de una clase hagan referencia a una única variable a nivel de clase.
Sintaxis: Utilizaremos la siguiente sintaxis para declarar miembros de datos compartidos:
NiveldeAcceso Shared MiembrodeDatos As TipodeDatos
Niveles de acceso
Los miembros de datos compartidos están directamente enlazados a la clase, y podemos
declararlos como públicos o privados. Si declaramos los miembros de datos como públicos,
estarán accesibles para cualquier código que pueda acceder a la clase. Si declaramos los
miembros de datos como privados, proporcionaremos propiedades compartidas públicas para
acceder a la propiedad compartida privada.
El siguiente ejemplo muestra cómo crear una clase de cuenta de ahorro (SavingsAccount) que
utilice un miembro de datos compartido público para mantener los tipos de interés para una
cuenta de ahorro:
Class GuardaCuenta
Public Shared TasaInteres As Double
Public Function CalculaInteres( ) As Double
...
End Function
End Class
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 270
El valor del miembro de datos TasaInteres de la clase GuardaCuenta puede establecerse
globalmente con independencia del número de instancias de la clase que estén en uso. El
valor se utiliza para calcular el interés del saldo actual.
Invocar miembros de datos compartidos desde un cliente
Después de crear una clase que utilice miembros de datos compartidos públicos, podemos
invocar los miembros de datos de esa clase desde una aplicación cliente. El siguiente código
muestra cómo invocar la clase GuardaCuenta y sus miembros de datos desde una aplicación
cliente:
Sub Test( )
[Link] = 0.03
Dim miCuenta As New GuardaCuenta( )
Dim tuCuenta As New GuardaCuenta( )
[Link]([Link]( ))
[Link]([Link]( ))
End Sub
En el examen de este código, se observa lo siguiente:
TasaInteres puede establecerse antes y después de la creación de cualquier instancia de la
clase GuardaCuenta. Cualquier modificación a TasaInterest se aplicará a todas las
instancias de la clase GuardaCuenta
Propiedades compartidas
También pueden crearse propiedades compartidas en las clases. El siguiente ejemplo muestra
cómo declarar una propiedad compartida denominada Tasa en la clase GuardaCuenta:
Class GuardaCuenta
Private Shared TasaInteres As Double
Shared Property Tasa( ) As Double
Get
Return TasaInteres
End Get
Set(ByVal Value As Double)
TasaInteres = Value
End Set
End Property
End Class
Invocar propiedades compartidas desde un cliente
Una vez declarada la propiedad compartida Tasa, puede utilizarse en una aplicación cliente
en lugar de acceder directamente al miembro de datos compartido TasaInteres. Podemos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 271
invocar una propiedad compartida cualificándola con el nombre de clase o con el nombre de
variable de una instancia específica de la clase.
El siguiente código muestra cómo invocar una propiedad compartida cualificándola con el
nombre de la clase:
[Link] = 0.03
6.10.-Cómo utilizar los métodos compartidos
Introducción
Podemos utilizar los miembros de procedimiento compartidos para diseñar funciones que
pueden ser invocadas sin crear una instancia de la clase. Los procedimientos compartidos son
métodos de una clase que no están asociados a una instancia específica de una clase. Los
miembros de procedimiento compartidos únicamente pueden acceder a datos marcados con
la palabra clave Shared. Por ejemplo, un método compartido no puede hacer referencia a un
miembro de la instancia de una clase.
Ejemplo del uso de un miembro de procedimiento compartido
El siguiente ejemplo muestra cómo una función utilizada habitualmente, como
ObtenerNombrePC, puede crearse como un miembro de procedimiento compartido de
forma que una aplicación cliente puede utilizarla fácilmente. El cliente únicamente necesita
hacer referencia al método prefijado por el nombre de la clase, ya que no se requiere ninguna
instancia de la clase.
' Codigo de la clase TestClass
Public Shared Function ObtenerNombrePC ( ) As String
...
End Function
' Codigo Cliente
[Link](TestClass. ObtenerNombrePC ( ))
Observaremos también que, en el código anterior, Show es un método compartido de la clase
MessageBox.
6.11.-¿Qué es el polimorfismo?
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 272
Introducción
La mayoría de sistemas de programación orientada a objetos proporcionan polimorfismo
mediante herencia. El polimorfismo basado en herencia implica la definición de métodos en
una clase base y sobrecargarlos con nuevas implementaciones en clases derivadas.
Definición
Polimorfismo hace referencia a la capacidad de definir múltiples clases con diferentes
funcionalidades pero con métodos o propiedades de nombres idénticos que pueden utilizarse
de forma intercambiable por el código cliente en tiempo de ejecución. El nombre del método
reside en la clase base. Las implementaciones de métodos residen en las clases derivadas.
Para gestionar esto, únicamente puede declararse en la clase base el nombre del método (no
el código que proporciona la funcionalidad del método).
La función getBonificacion sobrecargada en el ejemplo de l grafica
Otro Ejemplo de polimorfismo
Supongamos que definimos una clase denominada ImpuestoGeneral que proporciona
funcionalidad básica para calcular el impuesto sobre las ventas de un estado. Las clases
derivadas de ImpuestoGeneral, como ImpuestoRegion o ImpuestoCiudad, podrían
implementar métodos como CalculaImpuesto.
Polimorfismo hace referencia al hecho de que la implementación del método
CalculaImpuesto podría ser distinta en cada una de las clases derivadas. Por ejemplo, el tipo
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 273
impositivo de una ciudad (ImpuestoCiudad) podría ser distinto del tipo impositivo de una
region (ImpuestoRegion). Las clases que hereden de ImpuestoGeneral tendrán un método
CalculaImpuesto, pero el modo como se calcule realmente el impuesto podría variar en cada
una de las clases derivadas.
Sobrecarga de métodos o polimorfismo, en una misma clase
La sobrecarga de métodos, es una técnica que consiste en crear varios métodos con
idéntico nombre dentro de la misma clase, distinguiéndose entre sí por su lista de
parámetros.
Métodos sobrecargados
Para crear un método sobrecargado, agregamos dos o más procedimientos Sub o Function a
la clase, cada uno con el mismo nombre. En las declaraciones de procedimiento, el conjunto
de argumentos para cada procedimiento debe ser distinto o se producirá un error.
El siguiente ejemplo muestra un método con dos sobrecargas, una que acepta una String y la
otra que acepta un Integer como argumentos.
Public Sub TestFunction(ByVal input As String)
MsgBox(input)
End Sub
Public Sub TestFunction(ByVal input As Integer)
MsgBox(CStr(input))
End Sub
Si se debe llamar a este método desde el código y pesarle una cadena, se ejecutaría la primera
sobrecarga y un cuadro de mensaje mostraría la cadena; si se le pasó un número, se ejecutaría
la segunda sobrecarga y el número se convertiría en una cadena y aparecería en el cuadro de
mensaje.
Podemos crear tantas sobrecargas como sean necesarias y cada una de ellas puede contener
un número diferente de argumentos.
Analicemos el siguiente ejemplo:
Interfase grafica cliente
Public class form1…..
Private Sub Botton_Click …
Dim loEmpleado As New Empleado()
Dim ldbResultadoIncent As Double
[Link] = 1020.82
'llamada al primer método sobrecargado
[Link]()
'llamada al segundo método sobrecargado
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 274
MsgBox("El sueldo se transferirá el día " & [Link](29))
'llamada al tercer método sobrecargado
ldbResultadoIncent = [Link](50.75, "Extras")
MsgBox(“El incentivo a pagar será " & ldbResultadoIncent)
End Sub
End Class
Ahora veamos el codigo de la clase empleado con el uso de la sobrecarga
Public Class Empleado
Private mdbSalario As Double
Public Property Salario() As Double
Get
Return mdbSalario
End Get
Set(ByVal Value As Double)
mdbSalario = Value
End Set
End Property
' Métodos sobrecargados
Public Overloads Sub Sueldo()
' aquí mostramos en consola el importe del sueldo formateado
MsgBox("El sueldo es " & Format([Link], "#,#.##"))
End Sub
Public Overloads Function Sueldo(ByVal liDia As Integer) As String
' Aquí mostramos la fecha del mes actual en la que se
' realizará la transferencia del sueldo al banco del empleado
Dim ldtFechaActual As Date
Dim lsFechaCobro As String
ldtFechaActual = Now()
lsFechaCobro = CStr(liDia) & "/" & _
CStr(Month(ldtFechaActual)) & "/" & _
CStr(Year(ldtFechaActual))
Return lsFechaCobro
End Function
Public Overloads Function Sueldo(ByVal ldbImporteIncentivo As Double,ByVal
lsTipoIncentivo As String) As Double
' aquí calculamos la cantidad de incentivo que se añadirá al
' sueldo del empleado,en función del tipo de incentivo
Dim ldbIncentivo As Double
' según el tipo de incentivo, se descuenta un importe de la cantidad del
‘ incentivo
Select Case lsTipoIncentivo
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 275
Case "Viajes"
ldbIncentivo = ldbImporteIncentivo - 30
Case "Extras"
ldbIncentivo = ldbImporteIncentivo - 15
End Select
Return ldbIncentivo
End Function
End Class
6.13.- Herencia en Visual Basic NET
La Herencia especifica una relación “es un tipo de”
Múltiples clases comparten los mismos atributos y operaciones, permitiendo una eficaz
reutilización del código
Persona Clase base
Cliente Empleado Clase Derivada
Introducción
En Visual Basic .NET, la herencia puede utilizarse para derivar una clase de una clase
existente. La clase derivada puede heredar todas las propiedades, métodos, miembros de
datos, eventos y controladores de eventos de la clase base, facilitando la reutilización de la
clase base por toda la aplicación.
Definición
Herencia es el concepto de reutilizar atributos y operaciones comunes de una clase base en
una clase derivada.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 276
Cómo heredar de una clase
Una clase derivada hereda de una clase base
Pueden heredarse propiedades, métodos, miembros de datos, eventos y controladores de
eventos (dependiendo del ámbito)
La palabra clave Inherits
La palabra clave Inherits se utiliza para definir una clase derivada que heredará de una
clase base existente.
Ejemplo: El siguiente ejemplo muestra cómo utilizar la palabra clave Inherits:
Public Class VefirificaCuenta
Inherits CuentaBanco
Private Sub ProcesarCheque( )
' Agregar codigo para procesar uncheque en su cuenta
End Sub
End Class
Observacion Podemos utilizar la palabra clave MyBase para invocar métodos en una clase
base cuando invalidan métodos en una clase derivada. También podemos utilizar la palabra
clave MyBase para invocar el constructor y el destructor de la clase base en nuestra clase
derivada.
Observemos el siguiente ejemplo:
'Crear clase derivada en dos líneas
Public Class Administrativo
Inherits Empleado
' Crear clase derivada en la misma línea
Public Class Administrativo : Inherits Empleado
La palabra clave NotInheritable
La palabra clave NotInheritable se utiliza para definir una clase que no puede utilizarse
como clase base para herencia. Si otra clase intenta heredar de esta clase, se generará un error
de compilación.
Ejemplo: El siguiente ejemplo muestra cómo utilizar la palabra clave NotInheritable:
Public NotInheritable Class TestClass
...
End Class
Public Class DerivedClass
' La linea de abajo genera un error del compilador
Inherits TestClass
...
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 277
End Class
La palabra clave MustInherit
La palabra clave MustInherit se utiliza para definir clases que no están pensados para ser
utilizados directamente como objetos instanciados. La clase resultante debe ser heredada
como una clase base para utilizarla en el objeto de una clase derivada instanciada.
Ejemplo: El siguiente ejemplo muestra cómo utilizar la palabra clave MustInherit:
Public MustInherit Class ClaseBase
...
End Class
...
Si el código cliente intenta crear una instancia de este tipo de clase, se generará un error de
compilación, como se muestra en el siguiente ejemplo:
' Codigo Cliente
' La linea de abajo genera un error del compilador
Dim x As New BaseClass( )
La palabra clave Protected
Utilizamos el acceso Protected para limitar el ámbito de una propiedad, método, miembro
de datos, evento o controlador de eventos a la clase que los define y cualquier clase derivada
basada en esa clase base.
Ejemplo
El siguiente ejemplo muestra cómo utilizar la palabra clave Protected:
Public Class BaseClass
' Accesible en todo
Public counter As Integer
' Accessible solo en esta lcase o en clases derivadas
Protected nombre As String
...
End Class
Generar una clase a partir de una clase existente: Herencia de clases
Muchos objetos de la vida real tienen atributos y comportamientos en común, por ejemplo,
todos los coches tienen ruedas y motores, y pueden avanzar y detenerse. Sin embargo,
algunos automóviles tienen atributos que no son comunes, por ejemplo, un descapotable tiene
una parte superior que se puede subir/bajar electrónica o manualmente.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 278
Si se creó un objeto para representar un automóvil, se pueden incluir propiedades y métodos
para todos los atributos y comportamientos comunes, pero no se podrían agregar atributos
como la cubierta de un descapotable, puesto que dicho atributo no es generalizable a todos
los automóviles.
Mediante el uso de la herencia, se puede crear una clase "descapotable" que deriva de la clase
"automóvil". Ésta hereda todos los atributos de la clase automóvil y puede agregar los
atributos y comportamientos que son únicos de un auto descapotable.
Heredar a partir de una clase existente
La instrucción Inherits se utiliza para declarar una nueva clase, denominada clase derivada,
basada en una clase existente conocida como clase base. Las clases derivadas heredan todas
las propiedades, los métodos, los eventos, los campos y las constantes definidos en la
clase base.
El siguiente código muestra la declaración de una clase derivada.
Class DerivedClass
Inherits BaseClass
…
End Class
Se pueden crear instancias de la nueva clase DerivedClass, se puede tener acceso a sus
propiedades y métodos como BaseClass y se pueden agregar nuevas propiedades y métodos
que son específicos de la nueva clase. Para ver un ejemplo, nos fijaremos en la clase Persons
que tenemos creada.
Supongamos que deseamos tener una clase que represente jugadores de béisbol: los jugadores
del béisbol tienen todos los atributos definidos en la clase Personas, pero también tienen
atributos únicos, como su número y posición. En lugar de agregar esas propiedades a la clase
Personas, se creará una nueva clase derivada que se hereda de Personas, a la que se agregaran
las nuevas propiedades.
Pasos para crear una clase derivada de la clase Personas:
Abrimos el proyecto Personas que llevamos todo el tutorial usando.
En el Explorador de soluciones, seleccionamos el nodo del proyecto Personas.
En el menú Proyecto, elegimos Agregar clase.
En el cuadro de diálogo Agregar nuevo elemento, escribimos Jugadores en el cuadro
Nombre, a continuación, hacemos clic en Agregar.
Se agregará un nuevo módulo de clase al proyectollamado Jugadores.
En el Editor de código, agregamos lo siguiente justo debajo de la línea Public Class
Jugadores.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 279
Inherits Personas
Agregamos también el siguiente código para definir las dos nuevas propiedades.
Private Vnumero As Integer
Private Vposicion As String
Public Property Numero() As Integer
Get
Numero = Vnumero
End Get
Set(ByVal value As Integer)
Vnumero = value
End Set
End Property
Public Property Posicion() As String
Get
Posicion = Vposicion
End Get
Set(ByVal value As String)
Vposicion = value
End Set
End Property
En el menú Archivo, hacemos clic en Guardar todo.
Probar la clase Jugadores
Hemos creado una clase Jugadores, derivada de la clase Personas. Ahora haremos una nueva
aplicación para probar la clase Jugadores.
Para crear un proyecto de prueba para la clase:
1. En el menú Archivo, elegimos Agregar y, a continuación, hacemos clic en Nuevo
proyecto.
2. En el cuadro de diálogo Agregar nuevo proyecto, en el panel Plantillas,
seleccionamos una Aplicación de Windows Forms.
3. En el cuadro Nombre, escribimos PruebaJugadores y hacemos clic en Aceptar.
4. Se agregará un nuevo proyecto de Windows Forms al Explorador de soluciones y
aparecerá un nuevo formulario.
5. En el Explorador de soluciones, seleccionamos el proyecto PruebaJugadores y, en el
menú Proyecto, hacemos clic en Establecer como proyecto de inicio.
6. En el Explorador de soluciones, seleccionamos el proyecto PruebaJugadores y, en el
menú Proyecto, haga clic en Agregar referencia.
7. Se abrirá el cuadro de diálogo Agregar referencia.
8. Hacemos clic en la ficha Proyectos, elegimos Personas y hacemos clic en Aceptar.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 280
9. Hacemos doble clic en el formulario para abrir el Editor de código y escribimos la
siguiente declaración justo debajo de la línea Public Class Form1.
Dim player1 As New [Link]
Dim player2 As New [Link]
Esto declara dos nuevas instancias de la clase Players.
10. En el menú Archivo, hacemos clic en Guardar todo.
Para probar la clase derivada:
1. En el Explorador de soluciones, seleccionamos Form1 en el proyecto
PruebaJugadores y, a continuación, en el menú Ver, hacemos clic en Código.
2. En el Editor de código, agregamos el siguiente código al procedimiento de evento
Form1_Load.
[Link] = "Marvin"
[Link] = "Garcia"
[Link] = 13
[Link] = "Shortstop"
player2 .FirstName = "Jose"
[Link] = "Black"
player2..Number = 51
player2 .Position = "Catcher"
3. En el Explorador de soluciones, seleccionamos Form1 en el proyecto
PruebaJugadores y, a continuación, en el menú Ver, hacemos clic en Diseñador.
4. En el Cuadro de herramientas, arrastramos dos controles Button al formulario.
5. Seleccionamos el primer control Button y en la ventana Propiedades establecemos su
propiedad Text : Al bate.
6. Seleccionamos el segundo control Button y en la ventana Propiedades establecemos
su propiedad Text : En el banco
7. Hacemos doble clic en el primer botón (Al bate) para abrir el Editor de código y
escribimos el siguiente código en el controlador de eventos Button1_Click.
MsgBox([Link] & " " & [Link] & ", #" &
CStr([Link]) & " esta ahora al bate.")
Observamos que estamos utilizando el método FullName que se heredó de la clase
base Persons.
8. En el controlador de eventos Button2_Click, agregamos el siguiente código.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 281
MsgBox([Link] & " " & [Link] & ", #" &
CStr([Link]) & " esta en el banco.")
9. Presionamos F5 para ejecutar el programa. Hacemos clic en cada botón para ver los
resultados.
9.1 Clic al Boton1(Al bate):
9.2. Clic al Boton2 (en el banco):
10. En el menú Archivo, elegimos Guardar todo.
Hemos visto, qué son y cómo crear clases, agregarle propiedades, métodos y eventos, las
hemos heredado, etc. la mejor forma de aprender y de que las cosas se entiendan, es
haciéndolo uno mismo, es decir escribir programas utilizando todas las herramientas
posibles…
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 282
7.- Impresión en Visual Basic .NET
Introducción
Lo primero que debemos tener en cuenta es que todo lo que queramos hacer en .NET
debemos hacerlo usando las clases que este entorno nos ofrece y el tema de imprimir no es
una excepción.
En .NET ha cambiado un poco la forma de hacer todo lo que hacíamos en VB6, ya no existen
"objetos" que nos permitan imprimir ni colecciones que nos permitan saber las impresoras
disponibles, bueno, un poco sí, pero como veremos de una forma más ordenada y algo
diferente. En los siguientes puntos veremos que puede ser más soportable e incluso más fácil
si aprendemos a manejar las clases de .NET que nos permiten imprimir y configurar las
opciones de impresión.
7.1.-La solución: Cómo imprimir en .NET
Básicamente para imprimir en .NET solamente necesitamos una clase: PrintDocument la
cual está definida en el espacio de nombres [Link]. Con esta clase
tenemos todo lo necesario para imprimir (en la impresora predeterminada) cualquier tipo de
documento.
Simplemente necesitamos llamar al método Print y asunto arreglado. Seguramente el lector
se preguntará que si esto es así, ¿dónde está el problema? Problema, lo que se dice problema,
realmente no hay ninguno, lo que ocurre es que esta clase, particularmente el método Print,
se utiliza sin tener que indicar qué es lo que queremos imprimir, y aquí es donde podría estar
ese problema. El método Print de la clase PrintDocument lo que realmente hace es
"despertar a la bestia", es decir, dar las instrucciones pertinentes al motor de .NET para que
se inicie el proceso de impresión, dicho proceso se lleva a cabo básicamente utilizando el
evento PrintPage de la clase PrintDocument, en este evento es donde tendremos que hacer
todo lo necesario para que se imprima lo que queramos imprimir.
Por tanto, para poder controlar lo que se va a imprimir, debemos escribir todo nuestro código
en ese evento, el cual se produce para cada página que deba imprimirse en el evento
PrintPage, por tanto podemos decir que en .NET es más fácil imprimir y sobre todo controlar
cómo y dónde se imprime cada cosa, ya que, si lo simplificamos al máximo, todo se hace en
un solo sitio: el evento PrintPage de la clase PrintDocument.
Ejemplo de impresión
En el listado podemos ver un ejemplo de la forma más simple de imprimir en .NET, en este
ejemplo mostramos la cadena "Hola, Mundo" en la parte superior de la página usando una
fuente Arial de 24 puntos en negrita.
Private Sub btnImprimirSimple_Click(ByVal sender As Object, _
ByVal e As EventArgs)Handles [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 283
' ejemplo simple para imprimir en .NET
' Usamos una clase del tipo PrintDocument
Dim printDoc As New PrintDocument
' asignamos el método de evento para cada página a imprimir
AddHandler [Link], AddressOf print_PrintPage
' indicamos que queremos imprimir
[Link]()
End Sub
Private Sub print_PrintPage(ByVal sender As Object, _
ByVal e As PrintPageEventArgs)
'Este evento se producirá cada vez que se imprima una nueva página
' imprimir HOLA MUNDO en Arial tamaño 24 y negrita
' imprimimos la cadena en el margen izquierdo
Dim xPos As Single = [Link]
' La fuente a usar
Dim prFont As New Font("Arial", 24, [Link])
' la posición superior
Dim yPos As Single = [Link]([Link])
' imprimimos la cadena
[Link]("Hola, Mundo", prFont, [Link], xPos, yPos)
' indicamos que ya no hay nada más que imprimir
' (el valor predeterminado de esta propiedad es False)
[Link] = False
End Sub
Ejemplo simple de impresión
Como podemos comprobar el proceso es bien simple:
Primero tenemos el código usado para dar la orden de imprimir, (este código puede
estar en el evento Click de un botón), en el que creamos un nuevo objeto del tipo
PrintDocument al que asignamos el procedimiento de evento a usar cuando se vaya a
imprimir cada página, cosa que ocurrirá después de llamar al método Print de esta
clase.
En el evento PrintPage le indicamos a .NET que es lo que queremos imprimir, en
nuestro caso sólo la cadena "Hola, Mundo", para imprimir dicho texto utilizamos el
método DrawString del objeto Graphics, (una propiedad del segundo parámetro
pasado al evento).
Esta simpleza es en parte porque tampoco hacemos demasiadas cosas en el código del evento
PrintPage, aunque aquí mostramos algunas de las cosas necesarias, como por ejemplo indicar
el tipo de fuente a usar para la impresión, la cual se puede cambiar en cada una de las líneas
a imprimir (e incluso en distintas partes de esa línea), ya que cada línea se "dibuja" por medio
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 284
del método DrawString del objeto Graphics obtenido del segundo parámetro pasado a este
método.
Como vemos en DrawString debemos indicarle que es lo que queremos imprimir, con qué
tipo de fuente y en qué posición. Por último indicaremos si quedan más páginas a imprimir,
esto lo haremos asignado un valor verdadero o falso a la propiedad HasMorePages del objeto
recibido como segundo parámetro del evento, si el valor asignado es True estaremos
indicando que queremos seguir imprimiendo, por el contrario, asignando un valor False
terminaremos la impresión, cosa que también ocurrirá si no le asignamos expresamente nada
a esa propiedad.
7.2.-Configurar la impresión
Pero para ser claros esta no será la forma "habitual" de usar este evento, ya que en la mayoría
de los casos imprimiremos más de una página y seguramente querremos asignar otros valores
a la impresora, como los márgenes, el número de copias, el tamaño del papel, la orientación
de la impresión (vertical o apaisada) e incluso, lo más importante, qué impresora usar.
Todos estos valores los podremos indicar usando un objeto del tipo PrinterSettings, el cual,
entre otras cosas, nos permite saber cuáles son las impresoras que tenemos disponibles en el
equipo actual. Por tanto, lo habitual será que usemos un objeto de esta clase en conjunto con
el de la clase principal para imprimir: PrintDocument.
Seleccionar la impresora a usar
Otra de las tareas que seguramente nos veremos en la necesidad de ofrecer a los usuarios de
nuestras aplicaciones es que puedan seleccionar de una manera fácil qué impresora usar y
darles la posibilidad de que ajusten sus preferencias de impresión.
Todo esto lo podríamos hacer manualmente creando un formulario que utilice un objeto del
tipo PrinterSettings y que le ofrezca a los usuarios las opciones que creamos conveniente,
pero para que todo sea, digamos, más homogéneo y no tengamos que reinventar la rueda,
podemos hacer que toda esta configuración y selección de la impresora a usar la ofrezcamos
mediante los mismos cuadros de diálogo que utiliza el resto de aplicaciones, los cuales se
basan en los cuadros de diálogos comunes del sistema operativo, si esta es nuestra elección,
nos resultará fácil, ya que podemos usar la clase PrintDialog.
Con un objeto de esta clase, tal como hemos comentado, podemos mostrar el mismo cuadro
de diálogo que utilizan el resto de aplicaciones de Windows, con la ventaja añadida de que
podemos configurar las opciones que se mostrarán, de forma que lo configuremos para que
se adapte, en la medida de lo posible, a las preferencias de nuestra aplicación.
En breve veremos cuáles son las opciones que podemos usar para ajustar este cuadro de
diálogo a nuestras preferencias o a la de nuestra aplicación.
7.3.-Las clases para imprimir en .NET
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 285
Como hemos comentado en los párrafos anteriores, existen varias clases que nos permitirán
tanto imprimir como configurar la impresión. Todo esto es posible gracias a las clases que
.NET Framework pone a nuestra disposición para poder realizar esta tarea.
Echando mano del comodín que los que nos dedicamos a escribir artículos o libros, tenemos
que decir que en este artículo no disponemos del espacio suficiente para enumerar en detalle
todas las clases, delegados y enumeraciones que tanto el espacio de nombres
[Link] como [Link] pone a nuestra disposición para
realizar tareas relacionadas con la impresión, por tanto haremos una pequeña criba para
mostrar solamente los tipos que desde nuestro punto de vista pueden resultarnos más útiles,
particularmente porque serán los que utilicemos en la mayoría de los casos.
La clase PrintDocument
Esta es la clase elemental o principal si queremos imprimir en .NET, como hemos comentado
anteriormente, de los miembros que esta clase ofrece principalmente usaremos tres:
El método Print es el que iniciará el proceso de impresión, haciendo que se produzcan
los eventos necesarios para controlar lo que queremos imprimir.
El evento PrintPage, el cual se producirá cada vez que tengamos que imprimir una
página. Dentro de este evento es donde haremos todo lo que tengamos que hacer para
imprimir cada una de las páginas, desde aquí podemos controlar si quedan más
páginas por imprimir, etc.
La propiedad PrinterSettings a la que podemos asignarle un objeto del mismo nombre
en el que indicamos la impresora a usar y otros valores como el rango de página, el
número de copias, el tamaño del papel, la orientación, etc.
Del resto de miembros de esta clase podemos destacar la propiedad DocumentName a la que
podemos asignar el nombre del documento que estamos imprimiendo y que será el que se
muestre en el estado de la impresión. También tenemos el evento QueryPageSettings el cual
se produce justo antes del evento PrintPage y que nos permite asignar valores "particulares"
a cada una de las páginas a imprimir antes de que se produzca el evento PrintPage.
La clase PrinterSettings
Tal y como hemos estado indicando en los párrafos anteriores, esta clase nos permite
especificar características de impresión como la impresora a usar, el número de copias a
imprimir, el rango de páginas, etc. Realmente no necesitamos indicar nada, al menos de
forma explícita para usar un objeto de esta clase, ya que al crear una nueva instancia los
valores predeterminados serán los que tengamos asignado en la impresora, valga la
redundancia, predeterminada de nuestro sistema. Pero si queremos modificar esos valores,
tendremos que asignarlos a las propiedades de esta clase, entre las que podemos destacar las
siguientes:
Copies indica el número de copias a imprimir.
FromPage indica la página a partir de la que queremos imprimir.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 286
MaximunPage indica el número máximo de copias que se pueden indicar.
MinimunPage es el número mínimo de copias que podemos indicar.
ToPage indica la página hasta la que queremos imprimir.
Tanto MaximunPage como MinimunPage se utilizarán para indicar los valores máximo y
mínimo de las páginas disponibles y se usarán con una clase del tipo PrintDialog.
Del resto de propiedades también podemos destacar las colecciones:
InstalledPrinters es una propiedad compartida y por tanto podemos usarla sin
necesidad de crear una instancia de la clase PrinterSettings, esta colección devuelve
un array de tipo String con el nombre de cada una de las impresoras instaladas en el
sistema.
PaperSizes es una colección con elementos del tipo PaperSize que nos permite saber
los tamaños de papel que la impresora soporta. Cada elemento del tipo PaperSize nos
proporciona información sobre el tamaño (ancho y alto), el nombre y la "clase" de
papel, que no es ni más que una enumeración del tipo PaperKind.
PrinterResolutions es una colección con elementos del tipo PrinterResolution, de
forma que podamos averiguar las resoluciones (y calidades) permitidas por la
impresora. Cada uno de estos elementos nos indicará tanto la resolución horizontal
como la vertical, además de la calidad de impresión, especificada con uno de los
valores de la enumeración PrinterResolutionKind, cuyos valores pueden ser: Custom,
Draft, High, Low y Medium.
De los métodos, posiblemente el que más nos puede interesar es:
CreateMeasurementGraphics el cual nos permite conseguir un objeto del tipo
Graphics con el cual podemos averiguar ciertas características de la impresora sin
necesidad de tener que imprimir, ya que el objeto devuelto por este método es igual
al que se incluye en la clase PrintPageEventArgs, usada como segundo parámetro en
los eventos producidos por la clase PrintDocument.
Como regla general deberíamos tener una variable del tipo PrinterSettings para usarla como
almacenamiento de las preferencias de impresión de nuestros usuarios, ya que esta clase se
utiliza tanto con PrintDocument como con PrintDialog.
La clase PrintDialog
Esta clase nos servirá para que nuestros usuarios seleccionen la impresora a usar así como
para que indiquen ciertas características relacionadas con la impresión, como la calidad del
papel, el número de copias, etc., con la ventaja de que todo esto lo haremos usando el mismo
cuadro de diálogo común incluido en Windows y que es el que la práctica totalidad de
aplicaciones de este sistema operativo utilizarán, tal como podemos comprobar en la figura
1.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 287
Figura 1. El cuadro de diálogo para seleccionar la impresora
En la figura 1 podemos comprobar que hay ciertos elementos que puede que no nos interese
mostrar o dejar habilitados, por ejemplo, si nuestra aplicación no permite imprimir el código
seleccionado no tiene mucho significado ofrecerle la opción "Selección", (la figura está
capturada de un Windows XP en inglés, por eso se muestran las opciones en inglés), lo mismo
ocurre con el botón de ayuda o con las cajas de texto que permiten indicar el rango de páginas
a imprimir. Todas estas características las podemos habilitar o deshabilitar mediante algunas
de las propiedades de la clase PrintDialog, tales como: AllowPrintToFile, AllowSelection,
AllowSomePages, PrintToFile, ShowHelp y ShowNetwork.
La ayuda del cuadro de diálogo de imprimir
Como curiosidad, decir que la propiedad ShowHelp nos permite indicar si se debe mostrar o
no el botón de ayuda, (no la interrogación de la barra de títulos que siempre estará funcional),
pero entre las propiedades de esta clase no tenemos ninguna a la que indicarle que ayuda se
debe mostrar si pulsamos en ese botón, en lugar de eso, de lo que disponemos es de un evento:
HelpRequest el cual se producirá cuando el usuario pulse en dicho botón, por tanto si
queremos mostrar algún tipo de ayuda, tendremos que usar ese evento para mostrar la
información que creamos conveniente para nuestro cuadro de diálogo.
Al igual que en el resto de cuadros de diálogos de .NET, tenemos el método ShowDialog que
será el que nos permita mostrar el cuadro de diálogo y saber si el usuario ha pulsado en el
botón OK (Aceptar) o Cancelar, para que de esta forma sepamos si debemos seguir con el
proceso de impresión o no.
La propiedad PrinterSettings será la que nos permita saber lo que el usuario ha seleccionado,
además de ser la que usemos para asignar los valores predeterminados o bien los que
tengamos almacenado de ocasiones anteriores; tal como indicamos anteriormente, lo habitual
será que tengamos una variable del tipo de esta propiedad con las preferencias del usuario,
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 288
por tanto antes de llamar al método ShowDialog deberíamos asignar a esta propiedad la
variable que tengamos con las preferencias del usuario y si no se ha cancelado, debemos
asignar nuevamente el resultado de dichas preferencias, tal como mostramos en el listado 2.
Private Function seleccionarImpresora() As Boolean
Dim prtDialog As New PrintDialog
If prtSettings Is Nothing Then
prtSettings = New PrinterSettings
End If
With prtDialog
.AllowPrintToFile = False
.AllowSelection = False
.AllowSomePages = False
.PrintToFile = False
.ShowHelp = False
.ShowNetwork = True
.PrinterSettings = prtSettings
If .ShowDialog() = [Link] Then
prtSettings = .PrinterSettings
Else
Return False
End If
End With
Return True
End Function
La clase PrintPreviewDialog
Esta clase nos permitirá mostrar una ventana con la vista preliminar del documento que
queremos imprimir, de forma que los usuarios de nuestra aplicación pueden ver lo que se
imprimirá. Debido a que esta clase al estar derivada de Form tiene todas las propiedades,
métodos y eventos de cualquier formulario además de los relacionados con la
previsualización del documento a imprimir, veamos solamente los dos miembros que nos
interesarán más:
El método ShowDialog será el que se encargue de mostrar el formulario con la vista
preliminar.
A la propiedad Document le asignaremos un objeto del tipo PrintDocument que será
el que utilicemos para saber qué es lo que queremos imprimir.
NOTA:
Por regla general deberíamos asignar a la propiedad Document de la clase
PrintPreviewDialog el mismo objeto PrintDocument usado para imprimir, ya que la
clase PrintPreviewDialog se encargará de que se produzcan los mismos eventos que
si hubiésemos llamado al método Print del objeto PrintDocument asignado, de forma
que lo que se muestre mediante este diálogo sea lo mismo que se imprima, que es al
fin y al cabo lo que queremos conseguir.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 289
Tal como hemos resaltado en la nota, tanto el método Print de la clase PrintDocument como
la clase PrintPreviewDialog utilizan los mismos eventos del objeto PrintDocument, por tanto
podríamos usar un método genérico que sea el encargado de mostrar una vista preliminar de
lo que queremos imprimir o de mandarlo a la impresora, de esta forma podemos usar de
forma común las opciones ofrecidas al usuario, como por ejemplo permitir la selección de la
impresora antes de imprimir, etc.
En el listado podemos ver cómo podría ser ese método genérico para elegir entre imprimir o
previsualizar lo que deseamos imprimir.
Private Sub imprimir(ByVal esPreview As Boolean)
' imprimir o mostrar el PrintPreview
If prtSettings Is Nothing Then
prtSettings = New PrinterSettings
End If
If [Link] Then
If seleccionarImpresora() = False Then Return
End If
If prtDoc Is Nothing Then
prtDoc = New [Link]
AddHandler [Link], AddressOf prt_PrintPage
End If
' la línea actual
lineaActual = 0
' la configuración a usar en la impresión
[Link] = prtSettings
If esPreview Then
Dim prtPrev As New PrintPreviewDialog
[Link] = prtDoc
[Link] = "Previsualizar documento"
[Link]()
Else
[Link]()
End If
End Sub
Tal como podemos ver en la figura, el formulario (o cuadro de diálogo) de previsualización
nos permite seleccionar el número de página a mostrar, si queremos ver una o más páginas a
un mismo tiempo, el porcentaje de ampliación e incluso imprimir lo que estamos viendo,
todos estas características ya están incluidas en ese formulario.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 290
El formulario de previsualización
La clase PrintPreviewControl
Si nuestra intención es crear nuestro propio formulario de previsualización, también podemos
hacerlo si usamos el control PrintPreviewControl que es el que la clase PrintPreviewDialog
utiliza, si bien todos los botones y opciones tendremos que crearlos nosotros, para ello
podemos usar los miembros específicos de este control, tales como:
AutoZoom lo usaremos para que al cambiar el tamaño del control se cambie también
la página mostrada.
Columns indica el número de páginas a mostrar cuando se elija la orientación
horizontal (apaisada).
Document es donde asignaremos el objeto PrintDocument a imprimir.
Rows indica el número de páginas a mostrar cuando elijamos la orientación vertical.
Zoom para indicar la ampliación con la que queremos mostrar los documentos.
StartPageChanged en un evento que se producirá cada vez que cambiemos la página
de inicio (este evento nos servirá para crear un equivalente al NumericDropDown
usado en la clase PrintPreviewDialog).
Si también quisiéramos implementar un botón para imprimir, tendremos que manejar
nosotros mismos la impresión, pero realmente resultaría fácil, ya que lo único que tendríamos
que hacer es llamar al método Print del objeto PrintDocument asignado a la propiedad
Document.
Como siempre la última palabra la tendremos nosotros y dependiendo de lo que queramos
hacer usaremos una clase u otra.
7.4.- Conclusión para imprimir en VB net
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 291
Tal como hemos podido comprobar, imprimir en .NET no es tan complicado como en un
principio pudiera parecer, además de que tenemos valores añadidos que nos permiten un
mayor control sobre la impresión y, especialmente, sobre las opciones que podemos ofrecer
a los usuarios de nuestras aplicaciones, ya que como hemos visto, hacer algo como la
presentación preliminar, que en otros lenguajes nos obligaría a escribir bastante código, es
tan sencillo como crear un nuevo objeto en la memoria y asignar un par de propiedades.
Por supuesto, lo que no es totalmente sencillo ni automático es la presentación o impresión
de los datos que necesitamos mostrar, al menos si queremos darle un toque, digamos,
profesional a nuestra impresión, ya que seremos nosotros los que debamos "afinar" en la
forma de mostrar esos resultados; pero de todas formas eso es algo que siempre nos tocará
hacer, utilicemos el entorno de programación que utilicemos, la ventaja de usar lo que .NET
nos ofrece es que tenemos ciertas posibilidades de hacerlo de una forma más o menos fácil y
que de alguna forma nos facilita bastante la tarea, aunque para la mayoría de situaciones será
más que suficiente e incluso podemos automatizar, principalmente porque podemos
aprovechar las posibilidades que nos da la programación orientada a objetos de crear nuestras
propias clases e implementar métodos de impresión que se adapten a los datos que tengamos
que mostrar, ya que una de las claves de la POO es la abstracción y que mejor forma de
abstracción que crear un método que se encargue de manejar los datos que la propia clase
mantiene y que "sepa" cómo mostrar esos datos e incluso qué formato deben aplicarse a la
hora de presentar esos datos por la impresora. Posiblemente tengamos que quemar unas
cuantas neuronas más a la hora de "concebir" esa clase, pero a la larga ese esfuerzo habrá
valido la pena ya que puede suponernos una forma de "olvidarnos" de esos pequeños detalles
de ajustar cada una de las líneas que vamos a imprimir.
De seguro que el lector puede pensar que tampoco es necesario ese "esfuerzo" extra para
imprimir una línea, y seguramente tenga razón, pero precisamente si cuando diseñamos
nuestras clases para manejar datos tenemos en cuenta estos detalles, seguramente nos
resultará más fácil realizar cambios en ocasiones futuras. Por ejemplo, si tenemos una clase
en la que hay datos de cadena y de tipo numérico y queremos mostrar esos datos, la forma de
tratar cada uno de esos datos será diferente, ya que con toda seguridad los datos numéricos
querremos ajustarlos a la derecha y los de cadena a la izquierda, además de que si debemos
recortar la información que tenemos que mostrar, con total seguridad preferiremos "truncar"
los datos de cadena antes que los numéricos.
En este tipo de situaciones si dejamos que el código de la clase sea el que decida estos
truncamientos, (realmente el código de la clase no va a decidir nada, ya que tendremos que
ser nosotros los que hagamos esa decisión), siempre será preferible que tener que hacerlo en
el propio evento de impresión, sobre todo si ese mismo evento es el que usaremos para
imprimir datos de diferentes tipos, que pueden proceder de diferentes clases, pero si las clases
usadas para contener los datos están "preparadas" para imprimir el contenido de cada línea,
entonces resultará tan sencillo como llamar a un método de cada una de esas clases... En el
listado podemos ver cómo quedaría el evento PrintPage si hiciéramos algo de lo que
acabamos de comentar.
' El evento usado mientras se imprime el documento
Private Sub prt_PrintPage(ByVal sender As Object, ByVal e As PrintPageEventArgs)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 292
' Este evento se produce cada vez que se va a imprimir una página
Dim lineHeight As Single
Dim yPos As Single = [Link]
Dim leftMargin As Single = [Link]
Dim printFont As [Link]
' Asignar el tipo de letra
printFont = prtFont
lineHeight = [Link]([Link])
Dim fontTitulo As New Font("Arial", 20, [Link])
[Link]("Listado de " & Título, fontTitulo, _
[Link], leftMargin, yPos)
yPos += [Link]([Link])
' imprimir la cabecera de la página
yPos = Datos(0).CabeceraImpresión(e, printFont, yPos)
' imprimir cada una de las líneas de esta página
Do
yPos += lineHeight
[Link](Datos(lineaActual).LineaImpresión, _
printFont, [Link], leftMargin, yPos)
lineaActual += 1
Loop Until yPos >= [Link] _
OrElse lineaActual >= [Link]
If lineaActual < [Link] Then
[Link] = True
Else
[Link] = False
End If
End Sub
7.5.-Como crear un reporte (Reportviewer)
Mostraremos en esta oportunidad cómo crear un reporte en visual basic .net utilizando
reporting services y el control reportView.
Lo primero que necesitamos es crear una conexión a una base de datos, y lo haremos de
la siguiente manera: Desde el explorador de servidores (si no lo ves podes activarlo desde
el menú Ver/Explorador de Servidores [Crtl+Alt+S]), creamos una nueva conexión.
Seleccionamos SQL Server como se ve ne la imagen:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 293
Luego debemos proporcionar los datos de conexión a nuestro servidor (Puedes presionar
el botón [Probar Conexión] para asegurarte de que los datos son correctos). Puedes usar
cualquier base de datos para el ejemplo:
Cuando finalices la conexión se verá como en la siguiente imagen:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 294
Ahora debemos agregar un nuevo origen de datos a nuestra aplicación:
Los origenes de datos pueden ser desde una base de datos, un servicio web o un objeto.
Para este ejemplo usamos una base de datos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 295
Seleccionamos la conexión que creamos anteriormente.
Damos nombre a la conexión y seleccionamos siguiente:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 296
Puede que nuestra base de datos tenga varias tables, seleccionamos la tabla que
utilizaremos:
Al finalizar se verá como en la imagen siguiente, si no lo ves, selecciona el menú
Datos/Mostrar Origenes de Datos [Shift+Alt+D]:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 297
Ya tenemos nuestro Origen de DAtos listo para ser utilizado. Ahora agregaremos un
informe (report) a nuestro proyecto:
Seleccionamos Informe:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 298
Se mostrará el diseñador de informes. Agrega una tabla al informe.
Se verá más o menos así:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 299
Podemos agregar o quitar columnas haciendo clic con el botón derecho del mouse sobre
alguna columna.
Desde el panel Origenes de Datos arrastramos los campos sobre fila del medio de la tabla.
Como se ve en la imagen:
Luego en el Formulario Windows agregamos un control ReportView.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 300
Desde la etiqueta inteligente del control seleccionamos nuestro reporte ([Link]):
Luego, desde la misma etiqueta, seleccionamos Acoplar en el contenedor principal:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 301
Notaremos que al seleccionar el informe, como el informe ya tenía una tabla con datos de
un origen de datos, se han creado en forma automática los componentes Dataset,
TableAdapter y Binding Sources correspondientes.
Bueno, solo nos queda ejecutar la aplicación. El resultado debería parecerse al de la
siguiente imagen:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 302
Los reportes ofrecen varias funcionalidades mas que no he comentado por falta de
tiempo. Lo haré en futuros post. Espero que les sirva este ejemplo. hasta la próxima
entrega.
7.5.1.- Reportes con datos agrupados (Reporting Service)
Mostraremos como podemos hace un reporte con datos agrupados en visual basic .net.
Nuestro reporte tiene el siguiente aspecto:
Seleccionamos la fila de los datos (la del medio) y haciendo clic con el botón derecho del
mouse, desplegamos el menú contextual y seleccionamos Insertar Grupo.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 303
Esto nos abrirá una ventana de propiedades de agrupación y ordenación. Para crear un
grupo (en mi caso voy a agrupar los productos por marca) seleccionamos el campo que
contiene el dato desde la lista desplegable de Expresión para la sección Agrupar por:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 304
Al presionar aceptar en el cuadro anterior, vemos que nos agregó una fila antes y otro
despues de la fila de los datos. Estas filas son el encabezado y pie de grupo.
En mi caso me pareció útil combinar las celdas del encabezado de grupo por si alguna
marca tiene un nombre muy largo.
Sobre la fila de los encabezados de grupo arrastro y suelto el campo marca desde el panel
de origenes de datos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 305
Para el pie de grupo, en la columna precio arrastro y suelto desde elk panel origenes de
datos el campo precio. La diferencia es que al soltarlo sobre una celda de grupo le coloca
automaticamente la función SUM por lo que el resultado será la suma de los precios de los
artículos de ese grupo. Para que el total del grupo tenga el mismo formato que los precios
individuales, puedo agregar la funcion FORMAT igual que en la celda de arriba.
Bueno, aquí esta el reporte… la verdad que quedó bastante lindo…
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 306
Espero que les guste y por sobre todo que lo puedan usar en sus proyectos
7.5.2.- Dar formato a un reporte (Reporting service)
En base al ejemplo anterior (8.7.Cómo crear un reporte), quiero mostrarles como
podemos “formatear” ese reporte para conseguir un presentación mucho más profesional
utilizando reporting services desde visual basic .net.
Abrimos el reporte sobre el cual trabajaremos, se verá más o menos como este:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 307
Lo primero que tenemos que hacer es verificar si tenemos visibles las dos barras de
herramientas que necesitaremos para darle formato al informe, ellas son: “Bordes del
informe” y “Formato del informe”. Si no están visibles las podemos habilitar desde
Ver/Barras de Herramientas.
Para cambiar el color de alguna celda de la tabla, seleccionamos la celda y desplegamos la
ventana Color de fondo desde la barra de herramientas Formato del informe. En ella
tenemos atodos los colores web que usamos normalmente en los formularios windows.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 308
También podemos aplicarle formato de borde a cualquier celda de la tabla desde la barra
de herramientas Bordes del informe.
Podemos aplicar el tipo de letra a varias celdas al mismo tiempo seleccionando varias
celdas y aplicando el formato.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 309
Es muy útil la opción de combinar celdas. Seleccionamos más de una celda de una misma
fila y desde el menu contextual (el que se abre al presionar clic con el botón derecho del
mouse) seleccionamos la opción Combinar celdas.
Para cualquier texto que querramos que aparesca en el informe utilizamos un Cuadro de
Texto.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 310
Por defecto, al colocar en la tabla un campo numérico, este se alinea hacia la derecha. Si
lo deseamos esto se puede cambiar utilizando la barra de formato. En nuestro caso
utilizaremos la función Format para dar formato numérico al precio. Botónderecho sobre
la celda Precio y seleccionamos Expresión…
El cuadro Editar expresión es muy completo, te recomiendo que le des una mirada,
Usamos la función Format con el formato “Fixed” que nos monstrará los números con dos
decimales.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 311
Así se debería ver el informe terminado:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 312
7.6.-Trabajar Crystal Report con DataSet en Visual [Link]
La mayoría de las veces que trabajamos con Visual Basic .Net y Crystal Report, solemos
conectarnos a SQL Server u Oracle como fuente de datos, debido a que tienen integración
con el IDE de Visual Studio, para facilitar la creación de los mismos.
Cuando hablamos de motores como PostgreSQL, MySQL, Firebird, Teradata y otros, no
tenemos la integración del IDE con el servidor de base de datos, esto hace que no podamos
crear tan sencillamente los reportes como los hacemos como con los otros motores, pero no
lo hace imposible, sólo se debe seguir unos pasos distintos, que también sirve para los 2
primeros motores mencionados anteriormente.
Lo siguiente sirve en muchos casos para proyectos pequeños de la universidad, a pesar de
que utlizaré Visual Studio 2008 esto sirve muy bien para Visual Studio 2005 también, asi que
comencemos:
1.- Procederé a crear un proyecto en Visual Basic 2008, con el Framework 2.0, y le pondré
de nombre EjemploReporteCrystal, obviamente si ya tienen el proyecto creado no deben
de hacerlo.
2.- Después lo que hacemos es insertar un DataSet de nuestra base de datos, si no sabes
como hacerlo da clic aquí.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 313
3.- Luego de eso agregamos un nuevo elemento, para esto damos clic derecho en nuestro
proyecto –> Agregar –> Nuevo
Elemento.
4.- Tendremos un formulario como el siguiente en donde escogeremos la opción de la
izquierda, seleccionamos Reporting –> Seleccionamos ahora Crystal Report –> Le ponemos
un nombre –> y damos clic en Adjuntar.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 314
5.- Ahora lo que veremos será un wizard o ayudante que nos permitirá crear un reporte de
manera sencilla, deberán entonces de ver una imagen como la siguiente y darle clic en ok.
Dejen las opciones tal como las tengo en mi imagen.
6.- Lo siguiente es escoger de donde sacaremos los datos que mostraremos, para esto en la
siguiente pantalla que se les mostrará que deberá ser como la imagen que coloco abajo,
ustedes deberán escoger Datos del Proyecto –> [Link] DataSets –>
EjemploReporteCrystal.BD_EjemploProcedimientosDataSet (Este es mi dataset que puse
enante, entonces aquí colocan el de ustedes) –> y escogen las tablas que utilizarán en su
reporte, en mi caso escogí 2, ya que utilizaré datos de las 2 tablas –> Presionamos el boton
“>” para cada tabla que queramos utilizar en el reporte y una vez hecho esto damos en
siguiente.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 315
7.- En la siguiente pantalla veremos como están relacionadas las tablas, no hay
practicamente nada que explicar asi que damos clic en siguiente.
8.- Ahora en esta pantalla siguiente si hay que poner asunto, porque es aquí en donde
diremos que campos de que tablas y en qué lugar los queremos en nuestro reporte,
entonces vemos como tengo mis 2 tablas y escojo los datos que necesito de las 2, sin
preocuparme de como estén relacionadas ni nada por el estilo, como ven en esta parte lo
que hago es darle sentido a la forma de presentar mis datos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 316
9.- Luego de esto vendrán ciertas opciones como la que utilizaré a continuación que es de
agrupar los datos en un cierto orden, y la forma que escogi de agruparlos es por géneros
iguales, esto lo hago especificando en la parte de agrupamiento qué campo es el que quiero
agrupar.
10.- Lo que sigue son más opciones como les dije, pero en este momento yo ya le di en
finalizar, ya que no necesito hacerle más cosas a mi reporte, por ahora. Luego de dar clic en
finalizar tendré una imagen como la que está abajo, la parte que tengo tachada es una parte
que no quiero mostrar en ejecución por tanto para ocultarlas les damos clic derecho en la
parte gris y al desplegarse un menú de opciones seleccionamos ocultar.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 317
11.- Bien ahora regresamos y abrimos nuestro form, y buscamos nuestro origen de datos,
si no lo vemos por ahi, damos clic en el menú de Visual Studio en la opción de Datos –>
Seleccionamos ver Origenes de Datos y listo, tendrán que poder ver su dataset con las tablas
al lado como en la imagen. Pero bueno lo que debemos hacer con esto es arrastrar esas 2
tablas a mi formulario, y esto para qué es? pues es para colocar esos controles que ven
abajo junto con el dataset que están encerrados en el rectángulo verde, son controles que
ya vienen cargados con datos necesarios y que no tendremos que ponerlos nosotros, por
ejemplo ruta de la base de datos o metodos de conexión y desconexión, etc.
12.- Después de poner esas tablas las sacamos junto con la barra que se pone en la parte
superior, y deberá quedarnos tener algo como lo que sigue.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 318
13.- Luego de lo que hicimos vamos a la caja de herramientas y buscamos un control
llamado CrystalReportViewer, lo arrastramos y colocamos en el formulario, este control
será el que nos permita vizualizar nuestro reporte hecho anteriormente.
14.- Entonces una vez hecho esto damos doble clic en el borde del form para entrar al
metodo load del mismo y poner el codigo que sigue a continuación. Aclarando un poco
sobre ese código, lo que hacen las 2 primeras líneas es filtrar los datos de las tablas
indistintamente si están relacionadas, las otras 3 líneas sirven para cargar nuestro reporte
en el reportviewer que pusimos en el form, para esto cree un objeto llamado rpt del
reporte(), que fue mi reporte que creamos hace rato, y en su propiedad SetDataSource le
envie el dataset del proyecto que obviamente ya tiene los datos filtrado gracias a las 2 líneas
primeras, por último mande a cargar este reporte al control del form con su propiedad
ReportSource.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 319
15.- Luego de esto si lo ejecutan deberán ver algo como esto.
16.- Ahora abramos el DataSet para crear algo extra, a continuación lo que haremos es crear
un método que nos filtree solo los datos de las personas de género masculino. Para esto
demos doble clic sobre el dataset o clic derecho y Open.
17.- Damos clic derecho sobre la tabla en la que crearemos el filtro –> Adjuntar –> Query.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 320
18.- Lo que haremos a las siguientes 2 pantallas es simplemente darles clic en siguiente.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 321
19.- Luego tendremos esto y lo que haremos es agregar otra tabla para relacionarla con la
actual, para esto damos clic derecho en la parte blanca al lado de la tabla y en las opciones
que se despliegan seleccionamos Adjuntar Tabla.
20.- Ya que nuestra Base de Datos solo posee 2 tablas solo podremos escoger 1, que es la
tabla TGenero que es la que no tenemos puesta, la seleccionamos y damos clic en Adjuntar
y luego en Cerrar.
21.- Como vemos a continuación ya nos aparece la tabla que agregamos relacionada con la
primera que teniamos, esto es debido a que ya desde que las creamos hicimos esta relación;
lo que sigue el como se ve en la imagen poner en la parte del medio o directamente en el
query que necesitamos de la tabla TGenero el campo nombre_genero y que este nos servirá
como filtro, por eso colocamos en la parte de filtro la palabra =@nombre_genero además
debemos de sacar este campo de área Select, ya que si lo dejamos ahí no nos mostrará
datos en nuestro reporte, o por lo menos eso es lo que me ha sucedido en la práctica,
porque si lo ejecutamos en ese instante con el botón Execue Query si funciona
normalmente pero con el Crystal Report encontre esa falla.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 322
22.- Ya al haberle dado clic en OK debe de presentarnos la siguiente imagen en la
cual veremos ya hecha nuestra sentencia query de consulta, damos clic en siguiente para
continuar.
23.- Ahora le pondremos un nombre tanto en la parte donde dice Fill a DataTable como
en Return a DataTable, damos clic en siguiente.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 323
24.- Lo que viene es que ejecutará lo que hicimos en el DataSet y guardará los cambios,
solo le damos clic en Finalizar.
25.- Ahora en el código modificaremos la línea que hacia el filtro en la tabla TPersona, en
mi caso la puse como comentario, y coloqué la que cree recién, pueden ver que después
del DataSet le pongo una coma y le envio un parámetro, esto es debido a que en mi query
le puse el @nombre_genero, entonces por cada parámetro así que pongamos en el query
que hicimos debemos enviarlo aquí es esa línea después del DataSet en el orden que nos lo
pide la instrucción; en ese código yo puse la opción masculino directamente, si nosotros la
colocaramos o escogieramos desde un textbox o un combobox este sería el que pondríamos
ahí con su propiedad text.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 324
26.- Ya lo que queda es ejecutar la aplicación y podremos ver que solo nos filtrará los
datos de las personas de género masculino.
7.7.- Ejemplo de Reportes en visual [Link] con Crystal
Reports
En esta ocasión veremos cómo generar reportes en visual [Link] usando Crystal Reports.
Antes que nada, realizar la conexión a la base de datos .
Una vez que tenemos lo anterior, procederemos a crear la parte de reportes.
Primeramente, agregaremos 2 botones más al formulario que creamos en la conexión a la
base de datos, uno para realizar consultas y otro para generar el reporte
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 325
Los botones se llamaran btnReporte y btnConsulta respectivamente
Después agregaremos un nuevo formulario, al que llamaremos frmReporte, y dentro de
este agregaremos un CrystalReportViewer, que tendrá como nombre crvMiReporte
Ahora tenemos que agregar un nuevo componente Crystal Report (Project->add New
Item) y lo llamaremos rptAlumnos
Después de esto nos aparecerá un cuadro de diálogo para seleccionar la forma en la que
queremos crear nuestro reporte. Escogeremos la opción de Using the Report Wizard
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 326
A continuación, debemos seleccionar la base de datos que queremos mostrar en nuestro
reporte. Para esto iremos a la opción Create New Connection->Access/Excel(DAO) y
debemos indicar la ruta de la base de datos.
Posteriormente seleccionaremos la o las tablas que queremos agregar y los campos que
queremos que aparezcan en el reporte
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 327
Después de esto podemos seleccionar otras opciones como por cual campo queremos
agrupar los registros y el estilo del reporte.
Ahora vamos a la parte del código. Primeramente, vamos a implementar la parte de
consultas dentro del evento clic del botón de consultas.
Private Sub btnConsulta_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
dt = [Link]("SELECT * FROM usuarios WHERE usuario = '" + [Link] + "'")
[Link] = dt
End Sub
Este código sólo realiza consultas de acuerdo al valor colocado en el txtUsuario (nombre
del usuario).
Ahora, debemos mostrar los resultados de la consulta en el reporte, para esto
agregaremos el siguiente código en el evento clic del del botón Reporte (btnReporte)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 328
Private Sub btnReporte_Click(ByVal sender As [Link], ByVal e As [Link])
Handles [Link]
Dim rpt As New rptAlumnos
[Link](dt)
[Link] = rpt
[Link]()
End Sub
Y con esto ya tendremos nuestro reporte generado
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 329
8.- Formularios de interfaz múltiple (MDI)
8.1.-Aplicaciones de estilo SDI
Una aplicación de tipo o estilo SDI (Single Document Interface), Interfaz de Documento
Sencillo, está compuesta fundamentalmente de un único formulario, a través del cual,
el usuario realiza toda la interacción con el programa. Como ejemplos de este tipo de
aplicación tenemos el Bloc de Notas o la Calculadora de Windows.
Un programa SDI puede tener más de un formulario, aunque no sea algo habitual. Cuando
eso ocurre, los formularios se ejecutan independientemente, sin un elemento contenedor que
los organice.
8.2.-Aplicaciones de estilo MDI
Una aplicación de tipo o estilo MDI (Multiple Document Interface), Interfaz de Documento
Múltiple, se compone de un formulario principal, también denominado formulario MDI,
que actuará como contenedor de otros formularios (documentos) abiertos durante el
transcurso del programa, denominados formularios hijos o secundarios MDI. Como
ejemplos de este tipo de aplicación tenemos PowerPoint o Access.
A diferencia de lo que ocurría en versiones anteriores de VB, un formulario MDI admite
los mismos controles que un formulario normal, aunque dada su orientación de
formulario contenedor, se recomienda limitar los controles en un MDI a los estrictamente
necesarios. El menú es el ejemplo más identificativo de control idóneo para un formulario
MDI, ya que a través de sus opciones, podremos abrir los formularios hijos de la
aplicación.
Seguidamente describiremos el proceso de creación de un proyecto que contenga un
formulario MDI y dos formularios hijos, así como el comportamiento de estos últimos
cuando son abiertos dentro del formulario padre MDI.
Una vez creado el nuevo proyecto, cambiaremos el nombre del formulario por defecto a
frmPrincipal. Para conseguir que este formulario tenga el comportamiento de un contenedor
MDI, debemos asignar el valor True a su propiedad IsMdiContainer. También debemos
establecer a este formulario como inicial en las propiedades del proyecto.
Ahora pasaremos a la creación de los formularios hijos del MDI. El primero, frmCarta,
permite la escritura en un TextBox multilínea, cuyo contenido podremos grabar a un archivo
en disco. La Figura muestra este formulario.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 330
Formulario hijo de MDI para escribir un texto largo.
El código del botón que realiza la grabación del texto lo podemos ver en el Código
fuente . Debemos importar el espacio de nombres [Link], ya que en esta clase del
formulario hacemos uso de los tipos File y StreamWriter.
Private Sub btnGrabar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' escribir en un archivo el contenido del TextBox
Dim oEscritor As StreamWriter
oEscritor = [Link]([Link])
[Link]([Link])
[Link]()
End Sub
El otro formulario hijo, frmInfo, muestra la fecha y hora actual; esta última es actualizada
a través del control Timer tmrTiempo. Ver la Figura
Formulario hijo de MDI para mostrar fecha y hora actuales.
El Código fuente muestra las instrucciones que se ejecutan en el evento Tick del control
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 331
Timer.
Private Sub tmrTiempo_Tick(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim dtFecha As Date
dtFecha = [Link]
Dim dtHora As Date
dtHora = [Link]
[Link] = [Link]("d/MMM/yyyy")
[Link] = [Link]("h:m:s")
End Sub
El siguiente paso consiste en crear un menú para poder abrir los formularios hijos a
través de sus opciones. Ver Figura
Menú del formulario MDI.
En las opciones Carta e Información del menú, instanciaremos un objeto del
formulario correspondiente, teniendo en cuenta que para conseguir que dichos
formularios se comporten como hijos del MDI, debemos asignar a su propiedad
MdiParent, la instancia actual del formulario en ejecución, es decir, Me. Veamos este
punto en el Código fuente
Private Sub mnuCarta_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim ofrmCarta As New frmCarta()
' con la siguiente línea conseguimos que el
' formulario se comporte como hijo del actual
[Link] = Me
[Link]()
End Sub
Private Sub mnuInformacion_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim ofrmInfo As New frmInfo()
' con la siguiente línea conseguimos que el
' formulario se comporte como hijo del actual
[Link] = Me
[Link]()
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 332
En la Figura mostramos el formulario MDI en ejecución, conteniendo a los
formularios hijos dependientes.
Aplicación MDI en
ejecución.
8.3.- Creación de menús de tipo Ventana, en formularios MDI
Es probable que el lector haya observado, en algunas aplicaciones Windows de tipo MDI,
que existe en la barra de menús de la ventana principal, un menú con el nombre Ventana o
Window (depende del idioma del programa), que nos muestra los nombres de los formularios
hijos abiertos, permitiéndonos cambiar de formulario activo al seleccionar una de esas
opciones.
n nuestras aplicaciones MDI también podemos disponer de un menú de este tipo,
añadiendo una nueva opción al menú principal del formulario MDI, y asignando a su
propiedad MdiList el valor True.
Adicionalmente, y para darle un aspecto más profesional a este menú, podemos añadir
los MenuItem correspondientes a la organización de los formularios hijos en Cascada,
Mosaico Horizontal, etc. Para organizar los formularios abiertos en la aplicación en
alguno de estos modos, deberemos ejecutar el método LayoutMdi( ) del formulario
MDI, pasándole como parámetro uno de los valores correspondiente a la
enumeración MdiLayout. El Código fuente muestra las opciones correspondientes
a la organización en cascada y en mosaico horizontal de nuestro ejemplo.
Private Sub mnuCascada_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link]([Link])
End Sub
Private Sub mnuHorizontal_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link]([Link])
End Sub
La Figura muestra el mencionado menú Ventana de este proyecto, en cual contiene en
este caso los nombres de los formularios abiertos que acaban de ser organizados en mosaico
vertical.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 333
Menú ventana en formulario MDI.
8.4.-Bloqueo de opciones de menú en formularios MDI
En la aplicación de ejemplo que estamos desarrollando, podemos abrir tantas copias de los
formularios hijos como necesitemos.
Respecto al formulario que nos permite escribir un texto para grabar a un archivo, es útil
poder tener varios formularios de este tipo, ya que podemos trabajar con diversos archivos a
la vez.
Del formulario hijo que muestra la fecha y hora actual sin embargo, tener más de una copia
no parece algo muy lógico, ya que se trata simplemente de disponer de una información
visualizada, y repetirla a través de la apertura de varios formularios iguales no tiene mucho
sentido.
Para conseguir que de un determinado formulario hijo sólo podamos abrir una instancia,
debemos hacer dos cosas: en primer lugar, en el manipulador de evento correspondiente
a la opción de menú que abre dicho formulario, asignaremos False a la propiedad True
de la mencionada opción de menú. Veámoslo en el Código fuente
Private Sub mnuInformacion_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' deshabilitamos esta opción de menú
[Link] = False ' <-----
Dim ofrmInfo As New frmInfo()
' con la siguiente línea conseguimos que el
' formulario se comporte como hijo del actual
[Link] = Me
[Link]()
End Sub
En segundo lugar, dentro del código del formulario hijo, en nuestro caso frmInfo, debemos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 334
escribir el manipulador para el evento Closed del formulario. Este evento se produce
cuando se ha cerrado el formulario, por lo que desde aquí volveremos a activar la opción
de menú del formulario padre, que habíamos deshabilitado.
Para acceder desde un formulario hijo a su MDI contenedor, disponemos de la propiedad
MdiParent, que nos devuelve una referencia de dicho formulario padre. Observe el lector
en el Código fuente cómo además de utilizar la mencionada propiedad, la potencia de la
función CType( ) nos permite en una sola línea de código, llevar a cabo esta acción.
' al cerrar este formulario, activamos de nuevo
' la opción de menú del formulario padre que
' permite crear instancias de este formulario
Private Sub frmInfo_Closed(ByVal sender As Object, ByVal e As [Link])
Handles [Link]
' utilizando la función CType(), moldeamos
' la propiedad MdiParent del formulario al tipo
' correspondiente a la clase del formulario MDI;
' con ello obtenemos acceso a sus miembros, y en
' particular a la opción de menú que necesitamos habilitar
CType([Link], frmPrincipal).[Link] = True
End Sub
La Figura muestra el resultado al ejecutar. Mientras que el formulario de información esté
abierto, su opción de menú en el MDI estará deshabilitada.
Opción de formulario hijo deshabilitada.
8.5.-Recorrer los formularios hijos de un MDI
La clase Form tiene la propiedad MdiChildren, que devuelve un array con todos los
formularios hijos abiertos hasta el momento.
Esto nos permite recorrer todo este conjunto de formularios para realizar operaciones con
alguno de ellos o todos.
El Código fuente muestra un ejemplo de uso de esta propiedad, en el que mostramos el
título de cada formulario hijo, y además, cambiamos su color de fondo.
Dim oFormHijos() As Form
oFormHijos = [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 335
Dim oForm As Form
For Each oForm In oFormHijos
[Link]("Título de ventana: " & [Link])
[Link] = [Link]
Next
8.6.- Comportamiento No Modal (Modeless) de formularios
Un formulario de comportamiento no modal, permite el libre cambio de foco entre
el resto de formularios de la aplicación.
Una clara muestra la hemos visto en el proyecto de ejemplo realizado durante los últimos
apartados del texto. En dicha aplicación, podíamos abrir varios formularios hijos dentro
del formulario MDI principal, y pasar de uno a otro sin restricciones.
Otra característica de los formularios no modales reside en que una vez creados y
visualizados, el resto del código de la aplicación continúa su ejecución. Ver Código fuente
Dim ofrmCarta As New frmCarta()
' crear formulario hijo de un mdi
[Link] = Me
[Link]()
' después de mostrar el formulario hijo se muestra a continuación este mensaje
[Link]("Se acaba de abrir un formulario hijo")
8.7.- Modal de formularios
Como contrapartida al anterior apartado tenemos los formularios de comportamiento modal,
también denominados cuadros o ventanas de diálogo.
Un formulario modal, al ser visualizado, bloquea el paso a otros formularios de la aplicación
hasta que no es cerrado (aceptado o completado) por el usuario.
Como ejemplo de estos formularios se acompaña el proyecto FormDialogos, del que
pasamos a describir su proceso de creación.
Este proyecto contiene un formulario MDI llamado frmPrincipal, y uno hijo con el
nombre frmHijo, que abrimos mediante una opción de menú; la creación de este tipo de
formularios se ha descrito en apartados anteriores.
A continuación añadimos un nuevo formulario al proyecto con el nombre frmDialogo,
que también abriremos a través de la correspondiente opción de menú del formulario
MDI.
Para que este formulario tenga un comportamiento modal, debemos mostrarlo ejecutando
el método ShowDialog( ) de la clase Form. En el Código fuente 505 tenemos las
instrucciones necesarias. Observe también el lector, cómo hasta que el formulario de
diálogo no es cerrado, no se mostrará el mensaje que hay a continuación de la llamada
a ShowDialog( ). Si además intentamos pasar al formulario hijo, en el caso de que esté
abierto, no podremos.
Private Sub mnuDialogo_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' instanciar el formulario que mostraremos como un diálogo
Dim ofrmDialogo As New frmDialogo()
' dar una posición al formulario
[Link] = [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 336
' mostrarlo de forma modal, como cuadro de diálogo
[Link]()
[Link]("Se ha cerrado el diálogo")
End Sub
Para cerrar un formulario modal podemos, al igual que para cualquier formulario, ejecutar
su método Close( ). No obstante, un formulario de diálogo suele proporcionar, aunque
esto no es obligatorio, los típicos botones para aceptar, cancelar, reintentar, etc.; de modo
que una vez cerrado el formulario, podamos averiguar qué botón pulsó el usuario.
Podemos proporcionar este comportamiento en nuestros formularios modales,
asignando a la propiedad DialogResult de la clase Form, uno de los valores del tipo
enumerado DialogResult. Esto tendrá como efecto adicional el cierre del cuadro de
diálogo.
Por lo tanto, vamos a añadir a nuestro formulario frmDialogo, dos controles Button:
btnAceptar y btnCancelar, en los que escribiremos las instrucciones del Código fuente
Private Sub btnAceptar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' asignar un valor a esta propiedad, cierra al mismo tiempo el formulario
[Link] = [Link]
End Sub
Private Sub btnCancelar_Click(ByVal sender As Object, ByVal e As
[Link])
Handles [Link]
' asignar un valor a esta propiedad, cierra al mismo tiempo el formulario
[Link] = [Link]
End Sub
Como ayuda en la construcción de formularios modales de diálogo, la clase Form
dispone de las propiedades AcceptButton y CancelButton, a las que podemos asignar
sendos controles Button que serán ejecutados al pulsar las teclas [INTRO] y [ESCAPE]
respectivamente.
Esto es lo que haremos en el formulario frmDialogo, asignando a AcceptButton el control
btnAceptar, y en CancelButton asignaremos btnCancelar.
Finalmente, en el evento de la opción de menú que abre este formulario modal,
correspondiente a frmPrincipal, añadiremos, tras la llamada a ShowDialog( ), el código
que comprobará el resultado de la ejecución del formulario de diálogo. Ver el Código
fuente
Private Sub mnuDialogo_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' instanciar el formulario que mostraremos como un diálogo
Dim ofrmDialogo As New frmDialogo()
' dar una posición al formulario
[Link] = [Link]
' mostrarlo de forma modal, como cuadro de diálogo
[Link]()
' comprobar lo que ha hecho el usuario en el cuadro de diálogo
Dim Resultado As DialogResult
Resultado = [Link]
If Resultado = [Link] Then
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 337
[Link]("Datos del diálogo: " & _
[Link] & " " & _
[Link])
Else
[Link]("Se ha cancelado el diálogo")
End If
End Sub
La Figura muestra el programa en ejecución. Como puede comprobar el lector, el
formulario modal, debido a su comportamiento, no se encuentra limitado a los bordes del
formulario MDI; pero depende de este último, ya que si intentamos pasar el foco a un
formulario hijo, no podremos.
Formulario modal de diálogo en ejecución.
8.8.-Controles de cuadros de diálogo del sistema
Del conjunto de controles que nos ofrece la ventana Cuadro de herramientas del IDE,
existe un grupo que nos permite el acceso a los cuadros de diálogo estándar del sistema
operativo, esto es, los cuadros de selección de color, tipo de letra o fuente, apertura-
grabación de archivo, etc.
Para ilustrar el uso de algunos de estos controles, vamos a crear un proyecto de ejemplo con
el nombre DialogosSistema , en el que describiremos su modo de uso en los aspectos de
diseño y codificación.
Crearemos pues, un nuevo proyecto de tipo aplicación Windows, y en su formulario,
insertaremos un menú, añadiendo las siguientes opciones: Abrir, Guardar, Color y
Fuente. Cada opción mostrará un tipo de diálogo del sistema.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 338
Seguidamente insertaremos un TextBox, que acoplaremos con la propiedad Dock a todo el
espacio del formulario, y que nos servirá como base para las operaciones a realizar
mediante los controles de diálogo. La Figura 298 muestra el aspecto de este formulario.
Formulario de pruebas para controles de diálogo estándar.
Una vez dibujado un control de cuadro de diálogo en el formulario, dicho control quedará
ubicado en el panel de controles especiales, al igual que sucede con los menús. Para abrir
un control de este tipo en tiempo de ejecución, emplearemos su método ShowDialog( ).
A continuación describiremos cada uno de los controles de diálogo utilizados en este
ejemplo.
ColorDialog
Este control muestra el cuadro de diálogo del sistema para la selección de colores.
Entre sus propiedades podemos destacar las siguientes.
Color. Contiene un tipo de la estructura Color, que nos permite obtener el color
seleccionado por el usuario mediante este cuadro de diálogo, para poder
aplicarlo sobre alguno de los elementos del formulario.
AllowFullOpen. Contiene un valor lógico que permite habilitar y deshabilitar el
botón que muestra el conjunto de colores personalizados del cuadro de diálogo de
selección de colores.
Al seleccionar en el formulario, la opción de menú Color, ejecutaremos el Código fuente
que nos permitirá, utilizando el control dlgColor, de tipo ColorDialog, elegir un
color y aplicarlo a la propiedad BackColor, del control TextBox.
Private Sub mnuColor_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link]()
[Link] = [Link]
End Sub
La Figura muestra esta aplicación con el formulario y el cuadro de selección de color
abiertos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 339
Cuadro de diálogo estándar para selección de colores.
FontDialog
Este control muestra el cuadro de diálogo del sistema para la selección del tipo de fuente.
Entre sus propiedades podemos destacar las siguientes.
Font. Contiene un tipo de la clase Font. Una vez seleccionada una fuente por el
usuario en el cuadro de diálogo, podremos cambiar el fuente de los controles del
formulario.
ShowApply. Contiene un valor lógico que permite mostrar-ocultar el botón
Aplicar, que nos permitirá asignar el tipo de letra sin cerrar el diálogo. Al pulsar este
botón se desencadenará el
evento Apply de este control de diálogo, en el que podremos escribir el código
necesario para
aplicar la nueva fuente seleccionada.
Al seleccionar en el formulario la opción de menú Fuente, ejecutaremos el Código fuente
509 que nos permitirá, utilizando el control dlgFuente, de tipo FontDialog, elegir un tipo
de letra, y aplicarlo a la propiedad Font del control TextBox; con la particularidad de que
el cambio de letra lo haremos tanto al pulsar el botón Aceptar, como Aplicar del cuadro
de diálogo.
' al hacer clic en este menú, mostramos el cuadro de selección de fuente
Private Sub mnuFuente_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link] = True
[Link]()
[Link]()
End Sub
' este método cambia el fuente del TextBox
Private Sub AplicarFuente()
[Link] = [Link]
End Sub
' al pulsar el botón Aplicar del diálogo de
' selección de fuente, se produce este evento
Private Sub dlgFuente_Apply(ByVal sender As Object, ByVal e As
[Link])
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 340
Handles [Link]
[Link]()
End Sub
La Figura muestra el cambio de fuente sobre el texto del formulario.
Cuadro de diálogo del sistema para selección de tipo de letra.
SaveFileDialog
Este control muestra el cuadro de diálogo del sistema, mediante el que escribimos un
nombre de archivo, y elegimos un directorio, sobre el cual grabaremos información.
Es importante precisar que el control no se ocupa del proceso de grabación de datos; su
cometido es el permitirnos navegar por la estructura del sistema de archivos del equipo, y
la selección de un nombre para el archivo a grabar.
Entre las propiedades del control, podemos destacar las siguientes.
Title. Contiene una cadena con el título que aparecerá en el cuadro de diálogo.
InitialDirectory. Ruta inicial que mostrará el control al abrirse.
Filter. Cadena con el tipo de archivos que mostrará el cuadro de diálogo al
navegar por el sistema de archivos. El formato de esta cadena es el
siguiente: NombreArchivo
(*.Extensión)|*.Extensión; pudiendo situar varios filtros separados por el
carácter de barra vertical ( | ).
FilterIndex. Número que corresponde a alguno de los tipos de archivo
establecidos en la propiedad Filter.
FileName. Nombre del archivo en el que se realizará la escritura
DefaultExt. Cadena con la extensión por defecto a aplicar sobre el nombre del
archivo.
CheckFileExists. Valor lógico que nos permite comprobar si el archivo sobre el
que vamos a grabar ya existe.
ValidateNames. Valor lógico que comprobará si el nombre de archivo
proporcionado contiene caracteres especiales, es decir, si se trata de un nombre
válido.
Al seleccionar en el formulario la opción de menú Grabar, ejecutaremos el Código fuente
510, que nos permitirá, utilizando el control dlgGrabar, de tipo SaveFileDialog,
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 341
seleccionar el nombre de un archivo, y grabar el TextBox del formulario sobre el mismo,
mediante un StreamWriter.
Private Sub mnuGuardar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' configurar por código el diálogo de grabación de archivos
[Link] = "Documento (*.doc)|*.doc|Texto (*.txt)|*.txt"
[Link] = 2
[Link] = True
[Link]() ' abrir el cuadro de diálogo
' si todo es correcto, escribir mediante un objeto Stream
' el contenido del TextBox en el archivo indicado por
' las propiedades del cuadro de diálogo
Dim swEscritor As [Link]
swEscritor = New [Link]([Link])
[Link]([Link])
[Link]()
[Link]("Texto grabado en archivo")
End Sub
La Figura muestra el cuadro de dialogo de grabación de archivo.
Cuadro de diálogo para la grabación de archivos.
OpenFileDialog
Este control muestra el cuadro de diálogo del sistema, mediante el que seleccionamos un
archivo para poder abrirlo posteriormente, y realizar sobre el mismo operaciones de lectura-
escritura.
Al igual que en el control anterior, la lectura y escritura de información es algo que
deberemos realizar por código, una vez que hayamos elegido el archivo mediante este
cuadro de diálogo
Las propiedades de este control son prácticamente las mismas que las de SaveFileDialog,
con algunas excepciones como las siguientes.
Multiselect. Contiene un valor lógico, que nos permitirá la selección de múltiples
archivos.
ShowReadOnly. Permite mostrar la casilla de verificación para mostrar los
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 342
archivos de sólo lectura.
ReadOnlyChex. Permite obtener y establecer el valor para la casilla de
verificación de sólo lectura del cuadro de diálogo.
Al seleccionar en el formulario la opción de menú Abrir, ejecutaremos el Código fuente
que nos permitirá, utilizando el control dlgAbrir, de tipo OpenFileDialog, seleccionar un
archivo existente, y pasar su contenido al TextBox del formulario, utilizando un
StreamReader.
Private Sub mnuAbrir_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' configurar el cuadro de diálogo por código
[Link] = "Seleccionar archivo a leer"
[Link] = "C:\CUBO"
[Link] = "Código fuente (*.vb)|*.vb|Texto (*.txt)|*.txt"
' abrir el diálogo
[Link]()
' si se han seleccionado varios archivos mostrar su nombre
If [Link] > 1 Then
Dim sArchivo As String
For Each sArchivo In [Link]
[Link]("Archivo seleccionado: " & sArchivo)
Next
End If
' abrir el primer archivo con un Stream
' y volcarlo al TextBox
Dim srLector As New [Link]([Link])
[Link] = [Link]()
End Sub
La Figura muestra este cuadro de diálogo en ejecución
Cuadro de diálogo de apertura de archivos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 343
8.9.-Formularios dependientes
Formularios dependientes y fijos en primer plano
Un formulario dependiente, también denominado owned form, consiste en un formulario
que es abierto por otro, denominado formulario dueño (owner form), permaneciendo ambos
abiertos, sin que el formulario dependiente requiera ser cerrado, en el caso de que
necesitemos pasar el foco al formulario dueño.
No necesitamos ir muy lejos para encontrar un ejemplo de este tipo de formularios, en el
propio IDE de Visual Studio tenemos muchos casos. En la ventana del editor de código,
cuando abrimos la ventana de búsqueda de texto tecleando [CTRL + F], quedan ambas
visibles en todo momento, aunque no efectuemos ninguna búsqueda y el foco lo tengamos en
el editor de código. En este caso, la ventana Buscar es dependiente de la ventana del editor
de código. Ver Figura
Este comportamiento en los formularios contrasta claramente con el que tienen los
formularios de diálogo, en los cuales, hasta que no es cerrado el diálogo, no podemos
retornar el foco a la ventana que abrió el diálogo.
En versiones anteriores de VB, conseguir un formulario con tal funcionamiento era una
ardua tarea, que requería de conocimientos sobre el API de Windows; sin embargo, el nuevo
motor de formularios de la plataforma .NET, nos permite a través de una serie de
propiedades, que la configuración de formularios dependientes sea un trabajo realmente fácil
y rápido de conseguir.
Editor de código de Visual Studio con ventana de búsqueda.
Por otra parte, un formulario fijo en primer plano, también denominado topmost form,
consiste en un formulario que siempre aparece en primer plano respecto al resto de
formularios de la aplicación. Se trata de una ligera variación de comportamiento respecto
al formulario dependiente; mientras que este último, en algunas ocasiones puede ser
tapado por otros formularios del programa, un formulario topmost siempre permanece
visible en primer plano.
Para ilustrar el modo de creación y funcionamiento de este tipos de formularios, se
acompaña el proyecto de ejemplo FormDependiente , del que comentaremos los
pasos principales para su creación.
Una vez creado este proyecto, eliminaremos su formulario por defecto, y añadiremos el
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 344
formulario frmPrincipal, que configuraremos como contenedor MDI, y al que
añadiremos un menú que nos permitirá abrir un formulario hijo para escribir un texto,
y otro de diálogo para mostrar un literal. La Figura 304 muestra esta ventana MDI de la
aplicación.
Formulario MDI para el ejemplo con formularios dependientes.
El siguiente paso consistirá en crear el formulario frmCarta, que utilizaremos para
abrir los formularios dependientes que crearemos posteriormente en este proyecto. La
Figura muestra este formulario.
Formulario para escribir un texto y abrir formularios dependientes.
El Código fuente muestra el código del menú de frmPrincipal que instancia este
objeto y lo muestra como formulario hijo del MDI.
Private Sub mnuCarta_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' este formulario se abre como hijo del MDI
Dim ofrmCarta As New frmCarta()
[Link] = Me
[Link]()
End Sub
A continuación agregaremos al proyecto el formulario frmBuscar. Este formulario
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 345
actuará como dependiente de frmCarta, permitiéndonos buscar una cadena en el TextBox
de este último. La Figura muestra el aspecto de frmBuscar. Aunque no sería necesario,
para adaptarlo mejor a su funcionamiento, hemos variado mediante la propiedad
FormBorderStyle, el estilo de su borde a ventana de herramientas con el valor
FixedToolWindow.
Para conseguir que frmBuscar se comporte como formulario dependiente, al pulsar dentro de
frmCarta el botón Buscar, instanciaremos un objeto frmBuscar, añadiéndolo a la
colección de formularios dependientes de frmCarta mediante el método AddOwnedForm(
), de la clase Form. El Código fuente muestra el código del botón Buscar en el formulario
frmCarta.
Formulario dependiente frmBuscar.
Private Sub btnBuscar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' crear un objeto frmBuscar
Dim ofrmBuscar As New frmBuscar()
' establecer dependencia entre forms
[Link](ofrmBuscar)
[Link]()
End Sub
Podemos eliminar la asociación entre un formulario propietario y uno dependiente
mediante el método RemoveOwnedForm( ) en el formulario propietario. Esto no
quiere decir que el formulario dependiente sea eliminado, simplemente se elimina su
dependencia con respecto al propietario.
En lo que respecta al código de frmBuscar, al pulsar su botón Buscar, buscamos el
contenido del control txtBuscar en el formulario propietario frmCarta.
Si la búsqueda tiene éxito, seleccionamos el texto encontrado dentro del propietario.
La propiedad Owner del formulario nos devuelve una referencia del propietario, mientras
que para manipular los controles de dicho propietario, realizaremos un moldeado de
tipo o type casting sobre Owner utilizando la función CType( ) (observe el lector
de nuevo, la enorme potencia que encierra esta función).
Además mostramos una etiqueta en el formulario dependiente, que sólo se visualizará al
localizar el texto; cuando volvamos a escribir de nuevo texto a buscar, se ocultará dicha
etiqueta. El Código fuente muestra los métodos de frmBuscar que llevan a cabo estas
labores.
' al pulsar este botón, buscamos en el formulario
' propietario de este dependiente
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 346
Private Sub btnBuscar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim iResultadoBuscar As Integer
' la propiedad Owner contiene el formulario propietario
iResultadoBuscar = CType([Link],
frmCarta).[Link]([Link])
' si encontramos el texto buscado...
If iResultadoBuscar > 0 Then
' pasamos el foco al TextBox del formulario propietario
' y seleccionamos el texto encontrado
CType([Link], frmCarta).[Link]()
CType([Link], frmCarta).[Link] =
iResultadoBuscar
CType([Link], frmCarta).[Link] =
[Link]
[Link]()
End If
End Sub
' al volver a teclear un valor a buscar, se oculta el Label
Private Sub txtBuscar_TextChanged(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
[Link]()
End Sub
La Figura muestra la aplicación con ambos formularios abiertos. El formulario frmCarta
tiene el foco actualmente, pero eso no impide que frmBuscar también permanezca abierto,
para poder pasar a él en cualquier momento.
Formulario propietario y dependiente en funcionamiento.
Un formulario dependiente, aunque se muestra en todo momento encima de su propietario,
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 347
puede ser ocultado por otro formulario de la aplicación. Para demostrarlo, añadiremos al
proyecto el formulario frmDatosUsuario, que se mostrará como cuadro de diálogo,
visualizando un Label en su interior. Ver Figura
Formulario frmDatosUsuario.
El código de la opción de menú de frmPrincipal que abre este formulario se muestra en
el Código fuente
Private Sub mnuUsuario_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' mostrar este formulario como un diálogo
Dim ofrmUsuario As New frmDatosUsuario()
[Link]()
End Sub
La Figura muestra como este formulario oculta parcialmente al de búsqueda.
Formulario de diálogo ocultando parte del formulario dependiente.
Para lograr que un formulario se muestre en todo momento por encima del resto de
formularios de la aplicación, hemos de asignar el valor True a su propiedad TopMost;
obtenemos de esta manera, un formulario con estilo de visualización fijo en primer plano.
Ilustraremos este particular añadiendo un nuevo formulario al proyecto, con el nombre
frmPonerColor, en el que asignaremos a su propiedad TopMost el valor True. Ver la Figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 348
Formulario de estilo TopMost.
El Código fuente muestra el código del botón Color de frmCarta, en el que se crea un
formulario frmPonerColor y se visualiza.
Private Sub btnColor_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' abrir el formulario para poner color al texto
Dim ofrmPonerColor As New frmPonerColor(Me)
[Link]()
End Sub
En este momento debemos hacer dos observaciones: en primer lugar, no añadimos el
formulario frmPonerColor a la colección de formularios dependientes del propietario;
en segundo lugar, al instanciar el objeto frmPonerColor, estamos pasando al constructor
de esta clase la referencia del formulario propietario.
La explicación a este modo de proceder la encontramos dentro del código del formulario
dependiente; en donde añadimos dicho formulario, a la lista de formularios dependientes del
propietario, utilizando la propiedad Owner de la clase base Form. Esto tiene el mismo
efecto que usar el método AddOwnedForm( ). El Código fuente 517 muestra el constructor
de la clase frmPonerColor, en donde llevamos a cabo esta operación.
Public Class frmPonerColor
Inherits [Link]
'....
' crear un constructor para establecer el formulario propietario
Public Sub New(ByVal frmPropietario As frmCarta)
[Link]()
[Link] = frmPropietario
End Sub
Al volver a ejecutar ahora el programa, si abrimos el formulario frmPonerColor y después el
cuadro de diálogo, será el formulario de configuración de color el que prevalezca por encima,
al ser dependiente y TopMost. Ver Figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 349
El formulario TopMost siempre se sitúa encima del resto.
Este formulario será abierto también desde frmCarta, mediante su botón Color, y lo
utilizaremos para cambiar el color del control de texto de frmCarta. El Código fuente
muestra el procedimiento manipulador de evento de los controles RadioButton, en el
que se realiza el cambio de color en el formulario propietario.
' en este método ponemos el color al TextBox del formulario propietario
Private Sub PonerColor(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link], [Link], [Link]
Dim oColor As Color
If sender Is [Link] Then
oColor = [Link]
End If
If sender Is [Link] Then
oColor = [Link]
End If
If sender Is [Link] Then
oColor = [Link]
End If
CType([Link], frmCarta).[Link] = oColor
End Sub
Para finalizar con los formularios dependientes, debemos indicar que la clase Form
dispone de la propiedad OwnedForms, que contiene una colección con los
formularios dependientes de un formulario que actúe como propietario.
Ya que en este ejemplo es el formulario frmCarta el que se comporta como propietario,
añadiremos un botón con el nombre btnDependientes, que nos permitirá recorrer la
mencionada colección, y hacer, desde el propietario, una manipulación sobre los
formularios dependientes, en el caso de que haya alguno abierto. El Código fuente
muestra el código de este botón.
Private Sub btnDependientes_Click(ByVal sender As [Link], ByVal e As
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 350
[Link]) Handles [Link]
' obtener los formularios dependientes
Dim oFormularios() As Form = [Link]
Dim oFormulario As Form
' si existen dependientes...
If [Link] > 0 Then
' recorrer la colección y manipular los formularios dependientes
For Each oFormulario In oFormularios
Select Case [Link]().Name
Case "frmBuscar"
CType(oFormulario, frmBuscar).[Link]()
CType(oFormulario, frmBuscar).[Link] ="¡LOCALIZADO!"
[Link]
Case "frmPonerColor"
CType(oFormulario, frmPonerColor).[Link] = "AZULADO"
CType(oFormulario, frmPonerColor).[Link] =
' con el método PerformClick() de un control, simulamos una pulsación
CType(oFormulario,
frmPonerColor).[Link]()
End Select
Next
End If
End Sub
9.10.-Validación de controles
Los controles Windows vienen provistos de un potente y flexible sistema de
validación, que nos permitirá comprobar si el usuario introduce los valores adecuados
en un control, de modo que le permitiremos pasar el foco a otro control, u obligarle a
permanecer en el actual hasta que su valor no sea correcto.
En este esquema de validación, los miembros principales de la clase Control que
intervienen son los siguientes.
CausesValidation. Esta propiedad nos permite establecer un valor lógico, de
manera que cuando un control capture el foco, provocará la validación para otro
control del formulario que
la requiera.
Validating. Este evento se produce para que podamos escribir el código de
validación oportuno en un manipulador de evento. El procedimiento manejador de
evento recibe entre sus parámetros un objeto de tipo CancelEventArgs, por lo
que si la validación no es correcta, asignaremos False a la propiedad Cancel de
dicho objeto.
Validated. Este evento se produce en el caso de que la validación haya tenido éxito.
El proyecto de ejemplo ValidarControl (hacer clic aquí para acceder a este ejemplo)
consta de un formulario con tres controles TextBox. Todos tienen el valor True en su
propiedad CausesValidation, y adicionalmente, para el control txtImporte hemos escrito
el procedimiento que actuará como manipulador del evento Validating; con ello
impediremos el paso desde dicho control a los demás hasta que su contenido no sea
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 351
numérico. Si pasamos la validación, se ejecutará en ese caso el código del evento Validated.
Veamos estos manipuladores de evento en el Código fuente
Private Sub txtImporte_Validating(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
If Not IsNumeric([Link]) Then
[Link] = True
[Link]("Se requiere un número")
End If
End Sub
La Figura muestra esta aplicación en funcionamiento, durante la ejecución del
evento de validación.
En el control txtFecha por otro lado, podemos teclear cualquier valor, aunque no sea fecha,
ya que no proporcionamos manipuladores de evento para validar su contenido.
Cuando escribimos código de validación empleando estos miembros de la clase Control
hemos de tener presente el comportamiento, a veces no muy intuitivo, del sistema de
validación para controles en los formularios Windows.
Validación de un control.
Como hemos mencionado anteriormente, cuando la propiedad CausesValidation de
un control contiene True, al recibir el foco dicho control, se provocará el evento de
validación para el control que acaba de perder el foco. Pero si pasamos el foco a un
control en el que CausesValidation contiene False, la validación no se producirá sobre el
control que acaba de perder el foco.
Esto lo podemos comprobar muy fácilmente sobre nuestro proyecto de ejemplo, asignando al
control txtFecha el valor False en su CausesValidation. A partir de ahora, cuando estemos
situados en el control txtImporte, si este no contiene un número, se producirá la validación
si pasamos el foco a txtNombre, pero no se validará si pasamos a txtFecha.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 352
Indice
9.-Streams en .NET página 289
Las clases basadas en stream
Manejar unfichero usando FileStream
Manejar un fichero usando StreamReader y StreamWriter
10.- Colecciones de datos pagina 332
Tipos de colecciones
Tipos de datos de almaceniamiento de las colecciones
Clases bases para crear colecciones personalizadas
11.- GDI+ Sistema gráfico de Windows pagina 342
[Link]
12.- Operaciones de entrada y salida (I/O). pagina 368
[Link]
Objetos Stream
Clases TextReader y TextWriter
Manejo de datos binarios
13.- Ensamblados en Visual Basic Pagina 391
14 .-Crear un proyecto de instalación (Setup) Pagina 397
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 353
9.- Stream en .NET
Según hemos comentado en la introducción, los streams (o secuencias o flujos) nos
permiten abstraernos de la forma en que están implementados los procesos de acceso
a los ficheros u otros recursos. Todas las clases que manejan este tipo de flujos de datos
están basadas (directa o indirectamente) en la clase Stream, la cual nos ofrece ciertos
métodos que nos permiten, entre otras cosas, leer y escribir en esos flujos de
información.
Además de poder leer o escribir, también podemos realizar búsquedas o, dicho de otro
modo, podemos movernos a través de esa secuencia de datos. Pero debido a que no todos
los flujos de datos nos permiten realizar todas las operaciones de la clase Stream, existen
ciertas propiedades por medio de las cuales podemos saber si se permiten todas las
operaciones "básicas" que normalmente podremos hacer con los streams. Por ejemplo,
es posible que no podamos leer o escribir en una secuencia o que no podamos cambiar
la posición del "puntero" de lectura o escritura. Para todas estas comprobaciones
podremos usar las propiedades CanRead, CanWrite o CanSeek, pero creo que antes de
entrar en detalles, deberíamos ver algunos de las clases que .NET pone a nuestra
disposición para poder realizar este tipo de operaciones con "las secuencias" de datos.
Las clases basadas en stream
Entre las clases que están basadas en esta clase abstracta tenemos las siguientes:
BufferedStream, clase abstracta que representa un buffer de almacenamiento para
operaciones de lectura y escritura de otro stream.
DeflateStream, permite la compresión y descompresión de streams usando el algoritmo
Deflat.
GZipStream, usada para comprimir y descomprimir streams.
FileStream, nos permite una forma básica de acceder y manipular ficheros.
MemoryStream, crear un stream que se almacena en la memoria como una secuencia
de bytes.
NetworkStream, proporciona una secuencia de datos para el acceso a la red.
CryptoStream, un stream usado para encriptar otros streams.
Nota:
Las clases DeflateStream y GZipSteam están incluidas en el espacio de
nombres [Link].
La clase CryptoStream está incluida en el espacio de nombres
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 354
[Link].
La clase NetworkStream está incluida en el espacio de nombres
[Link].
Además de estas clases que se derivan directamente de la clase Stream, y que
normalmente se usan como "secuencias" a usar por otras clases de entrada/salida,
tenemos otras que nos permitirán acceder a esas secuencias de datos de una forma más
directa, (algunas de estas las veremos con algo de más detalle en el próximo capítulo
dedicado al sistema de archivos de .NET), por ejemplo:
BinaryReader / BinaryWriter, lee o escribe tipos primitivos como valores binarios
utilizando una codificación específica.
StreamReader / StreamWriter, clases para leer y escribir caracteres en ficheros
utilizando una codificación determinada.
StringReader / StringWriter, implementa TextReader o TextWriter para leer o escribir
en una cadena.
TextReader / TextWriter, clases abstractas para leer o escribir en una secuencia de
caracteres.
Cuando trabajamos con los streams debemos olvidarnos de las "cosas simples" y
debemos tener en cuenta que trataremos casi siempre con secuencias de bytes, ya que
al fin y al cabo esa es la forma de almacenar la información en los streams. Por tanto
cuando veamos los ejemplos que la documentación de Visual Basic 2010 nos
proporciona no debemos extrañarnos de que haya que hacer tantas "cosas" para
acceder o manipular la información almacenada en esas "secuencias" de datos. Si bien,
esa "complicación" nos da mayor control sobre el formato de la información contenida
en los streams. Por suerte, para los que nos gustan las cosas "simples" las clases
específicas nos facilitan mucho las cosas.
A continuación veremos un par de ejemplos en los que manipularemos cierta
información tanto en la memoria usando un objeto del tipo MemoryStream, como en un
fichero de disco usando FileStream y las clases que casi con seguridad usaremos
habitualmente para acceder al contenido de los ficheros: StreamReader y StreamWriter.
Manejar un fichero usando FileStream
En este primer ejemplo veremos lo complicado que pude parecer acceder a un fichero
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 355
usando la clase FileStream y por extensión cualquier método de otras clases que
devuelvan este tipo de secuencia, como por ejemplo los métodos OpenRead,
OpenWrite, etc. de la clase File.
La "complejidad" de esta clase es que realmente obtiene o guarda la información por
medio de un array de tipo Byte, cuando a lo que estamos acostumbrados es a usar
cadenas.
Nota:
Realmente, esta forma "binaria" de acceder a la información de un fichero
no la tenemos que ver como un inconveniente, ya que nos puede servir para acceder de
forma "binaria" a ese fichero, en caso de que nuestra intención sea acceder de forma
"normal" para, por ejemplo, leer solo texto, deberíamos usar otras clases más
especializadas para esa tarea, como lo es StreamReader.
En el siguiente código tenemos dos métodos, uno que guarda una cadena en el
fichero indicado:
Private Sub guardarDatos(ByVal fichero As String, ByVal cadena As String)
' Abrimos o creamos el fichero, para escribir en él
Dim fs As New
[Link](fichero, _
[Link]
e, _ [Link])
' Escribimos algunas cadenas,
' el problema es que solo podemos escribir arrays de bytes,
' por tanto debemos convertir la cadena en un array de bytes
Dim datos() As Byte
' pero usando la codificación que creamos conveniente
' de forma predeterminada es UTF-8,
' aunque la codificación de Windows es ANSI ([Link])
Dim enc As New [Link].UTF8Encoding
' convertimos la cadena en un array de bytes
datos = [Link](cadena)
' lo escribimos en el stream
[Link](datos, 0,
[Link])
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 356
' nos aseguramos que se escriben todos los
datos [Link]()
' cerramos el stream
[Link]()
End Sub
En el constructor de la clase FileStream indicamos el fichero en el que queremos
guardar la información, también le indicamos que queremos crearlo o abrirlo, es
decir, si ya existe lo abre y si no existe lo crea, de cualquiera de las formas, en el
siguiente parámetro del constructor le indicamos que nuestra intención es escribir
en ese fichero.
Como hemos comentado, la clase FileStream (y en general todos los streams)
trabaja con bytes, por tanto para poder almacenar algo en ese fichero debemos
hacerlo mediante un array de tipo Byte.
En el caso de las cadenas, éstas siempre deben estar codificadas, es decir, deben usar
el juego de caracteres que creamos conveniente, en el mundo de .NET ese juego de
caracteres es Unicode, más concretamente usando la codificación UTF-8, la cual
permite trabajar con cualquier carácter de cualquier cultura.
Como lo que nos interesa es convertir una cadena en un array de bytes, usamos
el método GetBytes de un objeto UTF8Encoding, el cual convierte la cadena en
una "ristra" de bytes con el formato adecuado, en este caso UTF-8.
Si en lugar de usar UTF-8 quisiéramos usar otro "codificador", por ejemplo el
predeterminado de Windows, con idea de que los ficheros sean compatibles con
otras aplicaciones que utilizan el formato predeterminado de Windows,
tendremos que declarar la variable enc de la siguiente forma:
Dim enc As [Link] = [Link]
A continuación, simplemente le pasamos el array de bytes al método Write del
FileStream indicando desde que posición de dicho array debe escribir y cuantos
bytes. Por último nos aseguramos de que todos los bytes del "buffer" se guarden en
el fichero y lo cerramos.
Y otra función que devuelve el contenido de un fichero en formato cadena:
Private Function leerDatos(ByVal fichero As String) As String
' Los bloques leídos los almacenaremos en un StringBuilder
Dim res As New [Link]
' Abrimos el fichero para leer de él
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 357
Dim fs As New [Link](fichero, _
[Link], _
[Link])
' los datos se leerán en bloques de 1024 bytes (1 KB) Dim
datos(1024) As Byte
Dim enc As New [Link].UTF8Encoding()
' leemos mientras hay algo en el fichero
While [Link](datos, 0, 1024) > 0
' agregamos al stringBuilder los bytes leídos
' (convertidos en una cadena)
[Link]([Link](datos))
End While
' cerramos el
buffer
[Link]()
' devolvemos todo lo leído
Return [Link]
End Function
En esta función vamos a leer los datos del fichero indicado, como ya hemos vistos,
la clase FileStream trabaja con bytes y esos bytes los convertimos a caracteres por
medio de las clases de codificación especializadas.
Por regla general, esas lecturas las haremos de forma parcial, es decir leyendo
bloques de bytes y como tenemos que convertir esos bytes en caracteres, y puede
ser que el fichero sea muy grande, en lugar de concatenar una cadena para
almacenar las lecturas parciales, vamos a usar un objeto del tipo StringBuilder en el
que iremos "agregando" cada trozo leído, de forma que el rendimiento no se vea
penalizado por la forma de ser de las cadenas, ya que cada vez que hacemos una
concatenación en una variable de tipo String, realmente estamos creando nuevos
objetos en la memoria y si son muchos, pues la verdad es que tendremos al
recolector de basura (GC) trabajando a tope, y si usamos un objeto StringBuilder el
rendimiento mejora una barbaridad.
La lectura de cada bloque de bytes lo hacemos en un bucle While, también
podríamos haberlo hecho en un bucle Do While, pero en estos casos, el
rendimiento de While es un "poquitín" mayor.
Los datos leídos los agregamos al objeto StringBuilder por medio del método Append
que se encarga de agregarlo a la cadena interna.
Finalmente cerramos el stream y devolvemos la cadena leída.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 358
Para usar estas dos funciones lo podemos hacer de la siguiente forma:
' un fichero de ejemplo (el directorio debe existir) Const fichero As
String = "E:\Pruebas\[Link]"
' guardamos una cadena en el fichero guardarDatos(fichero, "Hola, Mundo de
FileStream")
'
' Leemos el contenido del fichero y lo mostramos
[Link](leerDatos(fichero))
Este código no necesita mayor explicación.
Manejar un fichero usando StreamReader y StreamWriter
A continuación veremos cómo crear las dos funciones del ejemplo anterior para que
utilicen las clases "especializadas" para leer y escribir cadenas en un fichero.
Como podremos comprobar, esta es una forma muchísimo más simple y, por tanto
recomendada para este tipo de acceso a los ficheros. Aunque debemos recordar que
solo servirá para leer la información de forma secuencial y en formato cadena.
Nota:
El código para usar estas dos funciones será el mismo que el usado para las funciones
que utilizan la clase FileStream.
La función para guardar una cadena en un fichero:
Private Sub guardarDatos(ByVal fichero As String, ByVal cadena As String)
' Abrimos el fichero para escribir, (no añadir),
' usando la codificación predeterminada: UTF-8
Dim sw As New [Link](fichero, False)
' guardamos toda la cadena
[Link](cadena)
' Cerramos el fichero [Link]()
End Sub
Como podemos apreciar, esta es una forma mucho más "compacta" que la anterior, ya
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 359
que solo tenemos que indicar en el constructor lo que queremos hacer y usar el
método Write o WriteLine para guardar lo que queramos en el fichero.
Para guardarlo usando la codificación predeterminada del Sistema Operativo en el que
se utilice la aplicación, (en Windows será ANSI), simplemente usamos este constructor:
Dim sw As New [Link](fichero, False,
[Link])
Para leer los datos podemos hacerlo de dos formas: línea a línea o todo el
contenido de una sola vez.
En el código siguiente se muestra línea a línea, y al final, (comentado), cómo
hacerlo en una sola pasada.
Private Function leerDatos(ByVal fichero As String) As String
' Abrimos el fichero para leer
' usando la codificación UTF-8 (la predeterminada
de .NET) Dim sr As New
[Link](fichero, True)
' si queremos usar la predeterminada de Windows
'Dim sr As New [Link](fichero,
[Link])
' Podemos leer cada una de las líneas del fichero o todo el contenido
' Forma larga:
' si vamos a leer el fichero línea por línea, mejor usar un StringBuilder
Dim ret As New [Link]
' recorremos el fichero hasta que no haya nada que leer
While [Link] <> -1
[Link]([Link])
End While
' cerramos el fichero
[Link]()
' devolvemos lo leído
Return [Link]
'
'' Forma corta:
'' leemos todo el contenido del fichero
'Dim ret As String = [Link]()
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 360
'' lo cerramos
'[Link]()
'' devolvemos lo leído
'Return ret
End Function
Si nos decidimos a leer el contenido del fichero línea a línea, podemos usar el método
Peek, el cual devolverá el siguiente carácter del buffer del stream, o -1 si no hay nada
que leer. Peek no "consume" el carácter, simplemente comprueba si hay algo que leer.
Si hay algo que leer, leemos la línea completa y la añadimos al objeto StringBuilder, el
bucle se repetirá mientras haya información pendiente de leer.
Pero si optamos por la vía rápida, porque realmente no nos interese procesar cada línea,
podemos usar el método ReadToEnd, que en nuestro ejemplo, el valor devuelto será todo
el contenido del fichero, el cual asignamos a una variable de tipo String para usarla como
valor devuelto por la función, después de cerrar el fichero.
Asegurarnos que el fichero se cierra
Si queremos ahorrarnos el paso intermedio de asignar el valor en una variable y
después devolverlo, también podemos hacerlo de esta forma:
Try
Return [Link]()
Finally
[Link]()
End Try
Ya que el bloque Finally siempre se ejecutará, se produzca o no un error, por tanto nos
aseguramos de que el fichero se cierra.
Liberar recursos: Using... End Using
O si lo preferimos, podemos usar la nueva forma de asegurarnos de que los recursos
usados se liberan:
' Podemos usar Using para asegurarnos de que el recurso se libera
Private Function leerDatos(ByVal fichero As String) As String
Dim sr As New [Link](fichero, True)
Using sr
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 361
Return
[Link]() End
Using
End Function
En este código, cuando usamos Using sr, al ejecutarse End Using, el CLR se encargará de
llamar al método Dispose de la clase, de forma que se liberen los recursos que estemos
usando, en este ejemplo: el fichero abierto.
Estos dos últimos ejemplos serían equivalentes a los anteriores, más seguros, pero
también con más "trabajo" para el CLR.
Nota:
Using... End Using solo se puede usar con clases que implementen la interfaz IDisposable,
que es la que asegura que el objeto implementa el método Dispose.
Por tanto, si implementamos el método [Link] en nuestras clases, en ese
método nos tenemos que asegurar que liberamos los recursos que nuestra clase esté
utilizando.
Ejemplo de para cifrar y descifrar un fichero
En el siguiente ejemplo (adaptado de uno de la documentación), veremos cómo usar
algunas de las clases basadas en Stream, particularmente las clase MemoryStream,
FileStream, CryptoStream además de las clases StreamReader y StreamWriter.
Este código tiene dos funciones:
La primera encripta (cifra) una cadena y la guarda en un fichero.
La segunda desencripta (descifra) el contenido de un fichero y lo guarda en otro. Ambas
funciones devuelven la cadena cifrada o descifrada respectivamente.
Imports System Imports [Link]
Imports [Link]
Imports [Link]
Module Module1
Const fic1 As String = "E:\Pruebas\Prueba [Link]"
Const fic3 As String = "E:\Pruebas\Prueba CryptoStream
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 362
[Link]"
Const sKey As String = "El password a usar"
'
Sub Main()
Dim ret As String
'
ret = cifrarFichero("Hola, Mundo encriptado", fic1)
[Link]("Cadena encriptada : {0}", ret)
'
ret = descifrarFichero(fic1, fic3) [Link]("Cadena
desencriptada: {0}", ret)
' [Link]()
End Sub
Function cifrarFichero( _
ByVal texto As String, _
ByVal ficSalida As String) As String
' Creamos un MemorySream con el texto a cifrar
Dim enc As New UTF8Encoding
Dim datos() As Byte = [Link](texto)
Dim ms As New MemoryStream(datos)
' El fichero de salida
Dim fs As New FileStream(ficSalida, [Link], [Link])
' El proveedor criptográfico
Dim r As New DESCryptoServiceProvider
'
' Establecer la clave secreta
[Link] = [Link]([Link](0, 8))
[Link] = [Link]([Link](0, 8))
'
' Crear una secuencia de cifrado
Dim cs As New CryptoStream(fs,[Link](), _
[Link])
'
' Escribir el fichero cifrado [Link](datos, 0,
[Link])
[Link]()
'
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 363
' devolver el texto cifrado
Return Convert.ToBase64String([Link]())
End Function
Function descifrarFichero( _
ByVal fichero As String, _
ByVal ficSalida As String) As String
' el proveedor del cifrado y las claves usadas para cifrar
Dim r As New DESCryptoServiceProvider
[Link]() = [Link]([Link](0, 8))
[Link] = [Link]([Link](0, 8))
'
' crear la secuencia para leer el fichero cifrado
Dim fs As New FileStream(fichero, [Link], [Link])
'
Dim cs As New CryptoStream(fs,[Link](), _
[Link])
'
' guardar el contenido de fichero descifrado
Dim sw As New StreamWriter(ficSalida) Dim sr As New StreamReader(cs)
[Link]([Link])
[Link]()
[Link]()
'
' devolver el texto
sr = New StreamReader(fic3)
Dim ret As String = [Link]()
[Link]()
'
Return ret
End Function
End Module
10.- Colecciones en [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 364
Colecciones, la especialización de los arrays
A través de la clase Array, podemos manipular estos elementos del lenguaje con una
mayor potencia y flexibilidad que en pasadas versiones del lenguaje. No obstante, en
muchas ocasiones nos encontraremos con situaciones en las que sería muy agradable
que los arrays dispusieran de algunas características adicionales, dependiendo del
problema que tengamos que resolver en ese preciso momento.
Por ejemplo, sería una gran idea poder manejar un array que creciera dinámicamente,
sin tener que preocuparnos por aumentar o disminuir su tamaño; o también, disponer
de un array a cuyos valores pudiéramos acceder, a través de identificadores claves, y
no por el número de índice, que en algunas situaciones es más incómodo de manejar.
Todas las funcionalidades mencionadas, y algunas más, se encuentran disponibles
en un tipo especial de array denominado colección (collection).
Nota:
Diferencia básica entre estos tipos de colecciones es cómo están almacenados los
elementos que contienen, por ejemplo, las colecciones de tipo IList (y las directamente
derivadas de ICollection) solo almacenan un valor, mientras que las colecciones de tipo
IDictionary guardan un valor y una clave relacionada con dicho valor.
Definicion:
Una colección es un objeto que internamente gestiona un array, pero que está
preparado, dependiendo del tipo de colección, para manejar el array que contiene de
una manera especial; podríamos definirlo como un array optimizado o especializado en
ciertas tareas.
El espacio de nombres [Link]
Este espacio de nombres del entorno de .NET Framework, es el encargado de agrupar el
conjunto de clases e interfaces que nos permiten la creación de los distintos tipos de objetos
collection. Por lo que si necesitamos un array con alguna característica especial, sólo
hemos de instanciar un objeto de alguna de las clases de este espacio de nombres para
disponer de un array con esa funcionalidad. Entre las clases más significativas de
[Link], podemos destacar las siguientes.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 365
ArrayList. Proporciona una colección, cuyo array es redimensionado
dinámicamente.
Hashtable. Las colecciones de este tipo, contienen un array cuyos elementos se
basan en una combinación de clave y valor, de manera que el acceso a los valores
se facilita, al realizarse mediante la clave.
SortedList. Consiste en una colección ordenada de claves y valores.
Queue. Representa una lista de valores, en el que el primer valor que entra, es el
primero que sale.
Stack. Representa una lista de valores, en el que el último valor que entra, es el
primero que sale.
Para hacer uso de colecciones en una aplicación [Link] creada desde [Link], no es
necesario importar este espacio de nombres, ya que como sabrá, el propio IDE incluye
por defecto la importación del espacio System al proyecto.
La clave se halla en los interfaces
Las clases integrantes de [Link] implementan en mayor o menor grado,
un conjunto común de interfaces, que proporcionan la funcionalidad para el trabajo
con arrays especializados o colecciones. Entre alguno de los interfaces de Collections,
podemos mencionar los siguientes.
IEnumerable. Proporciona el soporte para recorrer colecciones de valores.
ICollection. Proporciona las características para manipular el tamaño,
gestionar enumeradores, etc., de listas de valores.
IList. Referencia a una lista de valores que puede ordenarse.
ICloneable. Permite la creación de copias exactas e independientes de objetos.
Todo ello significa, que además de las clases con las funcionalidades especiales de
Collections, podemos crear nuestras propias clases, para aquellos casos en los que
necesitemos disponer de un array con funcionalidades especiales, no contempladas
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 366
por los arrays base, y que además tampoco exista como colección. La manera de crear
nuestro propio tipo de colección sería heredando de una clase collection existente y/o
la implementación de alguno de los interfaces de Collections.
Las colecciones basadas en ICollection
La interfaz ICollection es un caso aparte, ya que realmente todas las colecciones de .NET
implementan esta interfaz, de hecho, esta interfaz se deriva de IEnumerable que es la
que nos permite recorrer las colecciones usando bucles For Each.
Esta interfaz no la tendremos que usar de forma habitual, ya que realmente el resto de
colecciones (e interfaces) útiles ya se derivan de ella, por tanto vamos a centrarnos en
las otras dos.
Aunque es importante que tengamos en cuenta que el resto de colecciones implementan
ICollection, por tanto siempre podremos usar un objeto de este tipo para acceder a
cualquier colección.
Independientemente de que todas las colecciones de .NET estén basadas en esta interfaz,
hay ciertos tipos de colecciones que solo implementan esta interfaz, por ejemplo las
colecciones de tipo Queue, Stack o BitArray, por tanto esas colecciones estarán limitadas
a los métodos expuestos por la interfaz ICollection y los que esas colecciones
implementen de forma independiente.
Por regla general, los tipos que solo se basan en ICollection suelen ser colecciones que no
necesitan de las características que proporcionan las otras interfaces y, por regla general,
nos permiten la manipulación de los datos de una forma básica o elemental, de forma
que su uso sea para casos muy concretos.
Por ejemplo, la clase Queue nos permite crear fácilmente una colección de tipo FIFO
(primero en entrar, primero en salir); por otra parte, con la clase Stack podemos crear
colecciones del tipo LIFO (último en entrar, el primero en salir), de forma que sean muy
útiles para crear "pilas" de datos.
El caso de la otra clase que hemos comentado: BitArray, nos sirve para almacenar valores
de tipo "bit", en el que cada valor se almacena como un cero o un uno, de forma que
podamos tener una colección muy compacta, pero, también muy específica y no de uso
general, ya que en este caso particular, los métodos que implementa esta clase están
enfocados en la manipulación de valores de tipo Boolean, (False y True), aunque
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 367
internamente se almacenen como valores cero y uno respectivamente.
Nota:
Realmente la clase BitArray no se comporta como una colección "normal", ya que el
tamaño de la misma debemos controlarlo nosotros, al igual que ocurre con los arrays,
aunque de forma más "fácil", mediante la propiedad Length.
Las colecciones basadas en IList
La interfaz IList se utiliza en las colecciones a las que queremos acceder mediante un
índice, por ejemplo, los arrays realmente está basados en esta interfaz, y tal como
pudimos comprobar, la única forma que tenemos de acceder a los elementos de un array,
(y por extensión a los elementos de las colecciones basadas en IList), es mediante un
índice numérico.
Existen tres tipos principales de colecciones que implementan esta interfaz:
Las de solo lectura, colecciones que no se pueden modificar. Este tipo de
colecciones suelen basarse en la clase abstracta ReadOnlyCollectionBase.
Las colecciones de tamaño fijo, no se pueden quitar ni añadir elementos,
pero si modificarlos. Por ejemplo, las colecciones basadas en Array son de
tamaño fijo.
Las de tamaño variable permiten cualquier tipo de adición, eliminación y
modificación. La mayoría de las colecciones suelen ser de este tipo, es decir, nos
permiten dinámicamente añadir o eliminar elementos.
Existe un gran número de colecciones en .NET que implementan esta interfaz, (sobre
todo las colecciones basadas en controles), entre las que podemos destacar las
siguientes:
ArrayList, la colección "clásica" para este tipo de interfaz. Contiene todos los
miembros habituales en este tipo de colecciones.
CollectionBase, una clase abstracta para poder crear nuestras propias
colecciones basadas en IList.
StringCollection, una colección especializada que solo puede contener valores de
tipo cadena.
La colección ArrayList
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 368
Tal como hemos comentado, el tipo de colección que se usa como referencia a la hora de
hablar de las colecciones basadas en la interfaz IList, es ArrayList.
Esta colección permite añadir, eliminar y modificar fácilmente los elementos que
contiene. También podemos recorrerlos mediante un bucle For accediendo a los
elementos por medio de un índice e incluso mediante un bucle del tipo For Each.
Al igual que ocurre con los arrays, el índice inferior es siempre el cero y los elementos se
almacenan de forma consecutiva, es decir, si añadimos dos elementos a una colección de
tipo ArrayList (y a las que implementen la interfaz IList), el primero ocupará la posición
cero y el segundo la posición uno. La ventaja de trabajar con las colecciones es que no
debemos preocuparnos de reservar memoria cada vez que vayamos a añadir un nuevo
elemento, simplemente usamos el método Add y asunto arreglado.
Lo mismo ocurre a la hora de quitar elementos de una colección, no tenemos que
preocuparnos demasiado por el espacio dejado al quitar elementos, de eso se encarga el
propio .NET, nosotros simplemente debemos llamar al método Remove o RemoveAt
indicando respectivamente el elemento a eliminar o el índice en el que se encuentra
almacenado.
Truco:
Si decidimos eliminar varios elementos de una colección de tipo IList (o de un array), lo
normal es que lo hagamos usando un bucle For; si este es el caso, para evitar una posible
excepción, (realmente no es posible, sino con toda certeza segura), debemos recorrer el
bucle desde el final hacia adelante, con idea de que al cambiar el número de elementos
no falle al intentar a acceder a un elemento que ya no existe.
El tipo de datos de almacenamiento de las colecciones
Estos elementos internamente están almacenados como objetos del tipo Object, por
tanto podemos añadir cualquier tipo de datos a una colección de este tipo, ya que todos
los tipos de datos de .NET están basado en la clase Object.
El problema con este tipo de colecciones es que siempre que queramos acceder a uno
de los elementos que contiene, debemos hacer una conversión al tipo adecuado, es
decir, si en una colección de este tipo guardamos objetos de tipo Cliente y queremos
acceder a uno de ellos, debemos hacer una conversión (cast) del tipo Object al tipo
Cliente, ya que si no lo hacemos y tenemos activada Option Strict (la opción para las
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 369
comprobaciones estrictas), se producirá un error si hacemos algo como esto:
Dim lista As New
ArrayList [Link](New
Cliente("Pepe"))
[Link](New
Cliente("Lola"))
Dim unCliente As Cliente
' ¡Error!
unCliente = lista(0)
...
Por tanto, la última línea deberíamos escribirla de una de estas dos formas:
' Usando CType para hacer la
conversión unCliente =
CType(lista(0), Cliente)
...
' Usando DirectCast para hacer la conversión (más recomendable)
unCliente = DirectCast(lista(0), Cliente)
Otro de los problemas que tienen las colecciones "normales" es que en algunos casos,
particularmente cuando almacenamos tipos por valor, el rendimiento se ve bastante
mermado, ya que el runtime de .NET (el CLR) debe hacer lo que en inglés se conoce
como boxing/unboxing, es decir, convertir un tipo por valor en uno por referencia
cuando va a guardarlo en la colección (boxing), y el proceso inverso cuando lo
queremos recuperar (unboxing).
Nota:
Por suerte, en Visual Basic 2010 tenemos otra forma de mejorar el rendimiento de las
colecciones, y es mediante las colecciones "generic", de esto, nos ocuparemos más
adelante.
Otras de las ventajas de las colecciones de .NET, no solo las basadas en la interfaz IList,
es que proporcionan una gran cantidad de métodos que nos facilitan la manipulación de
ese tipo de datos. Por ejemplo, tenemos métodos para clasificar el contenido de las
colecciones, (aunque esos objetos deben implementar la interfaz IComparable, tal como
vimos en el último ejemplo del capítulo de las interfaces), además tienen métodos para
hacer copias, buscar elementos y muchos etcéteras más.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 370
Las colecciones basadas en IDictionary
El otro grupo de colecciones que podemos encontrar en .NET son las colecciones basadas
en la interfaz IDictionary. Éstas, a diferencia de las colecciones IList, siempre mantienen
el par clave/valor, ya que la forma de acceder a los elementos es mediante una clave
única. Por tanto, cada vez que añadimos un elemento a una colección de este tipo
tendremos que indicar una clave y un valor. Cada valor estará relacionado con su
correspondiente clave.
Sabiendo esto, es fácil adivinar que si queremos acceder a un elemento, lo normal es que
lo hagamos usando la clave indicada al añadirlo. Los que hayan trabajado anteriormente
con Visual Basic 6.0, (o lo estén haciendo actualmente), puede que piensen que también
se podrá acceder a cada elemento mediante un índice numérico, ya que el objeto
Collection de VB6, (que aún sigue existiendo en Visual Basic 2010), nos permite indicar
una clave para cada elemento, y además de acceder a esos elementos mediante la clave,
podemos hacerlo mediante un valor numérico (índice). Pero en las colecciones basadas
en IDictionary, salvo casos muy especiales, siempre accederemos a los valores contenidos
mediante la clave y "nunca" mediante un índice que haga referencia a la posición dentro
de la colección, entre otras cosas porque cuando almacenamos valores en este tipo de
colecciones, éstos no se guardan en el mismo orden en que fueron añadidos.
Nota:
Si bien la clase Collection está disponible en la nueva versión de Visual Basic, ésta
tiene algunas mejoras con respecto a la que tiene VB6, entre esas mejoras están dos
nuevos métodos que nos facilitarán su uso: el método Clear con el que podemos
eliminar todos los elementos de la colección y el método Contains, con el que
podemos averiguar si un determinado elemento está en la colección.
Entre las colecciones basadas en la interfaz IDictionary podemos destacar:
Hashtable, es la colección por excelencia de las basadas en IDictionary. Los
elementos se organizan basándose en el código hash de las claves.
DictionaryBase, es una clase abstracta que podemos usar como base de
nuestras propias colecciones de tipo diccionario.
ListDictionary, es una colección con mayor rendimiento que Hashtable pensada
para trabajar con 10 o menos elementos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 371
HybridDictionary, es una colección especial en la que si hay 10 o menos elementos,
se utiliza una colección ListDictionary y si contiene más elementos se utiliza una
colección Hashtable.
SortedList, es una colección en la que los elementos están clasificados por las
claves. Internamente utiliza una mezcla entre Hashtable y Array, según la forma
en que se
accedan a esos elementos.
Almacenar valores en una colección tipo IDictionary
Para añadir nuevos elementos a una colección de tipo IDictionary siempre tendremos
que indicar la clave y el valor, la clave no puede ser un valor nulo, (Nothing), pero puede
ser de cualquier tipo. El valor también puede ser de cualquier tipo y en este caso si que
se admiten valores nulos.
Los elementos los añadiremos usando el método Add, al que habrá que indicar
primero la clave y después el valor:
Dim valores() As String = {"uno", "dos", “tres"} Dim dic As New _
[Link]
For i As Integer = 0 To [Link] - 1
[Link](valores(i), "El valor de " & valores(i))
Next
Cómo se almacenan los elementos de las colecciones IDictionary
Tal como hemos comentado, las colecciones que implementan la interfaz IDictionary
siempre almacenan un par de datos: la clave y el valor propiamente dicho, por tanto cada
vez que queramos acceder a un valor, debemos usar la clave asociada con dicho valor. Al
menos esa es la forma habitual, ya que como veremos, también podremos acceder a esos
valores directamente.
Debido a esta característica, para acceder a los elementos de este tipo de colecciones
por medio de un bucle del tipo For Each, debemos usar una clase llamada
DictionaryEntry, esta clase tiene dos propiedades, una contiene la clave y otra el valor.
Por tanto, cuando usemos un bucle For Each, el tipo de objeto usado para acceder a los
elementos de la colección será DictionaryEntry, tal como vemos en el siguiente código:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 372
For Each de As DictionaryEntry In dic
[Link]("{0} = {1}", [Link], [Link])
Next
Obtener todas las claves y valores de una colección IDictionary
Independientemente de que podamos recorrer los valores contenidos en una colección
de tipo IDictionary usando un objeto de tipo DictionaryEntry, habrá ocasiones en las que
realmente nos interesen tener solo los valores e incluso solo las claves, en estos casos,
podemos usar dos propiedades que la interfaz IDictionary define: Keys y Values. Estas
propiedades devuelven un objeto del tipo ICollection con las claves y valores
respectivamente.
Al ser objetos ICollection, solo podremos usarlos para recorrerlos por medio de un bucle
For Each, ya que las colecciones ICollection no tienen ningún método que nos permita
acceder a los elementos que contiene usando un índice. En el siguiente código mostramos
todas las claves de la colección creada en el ejemplo anterior:
For Each clave As String In [Link]
MsgBox(clave)
Next
Nota:
Siempre que usemos un bucle For Each para recorrer los elementos (o datos) de una
colección, solo tendremos acceso de solo lectura a esos datos, es decir, no podremos
modificarlos usando la variable por medio de la que accedemos a ellos.
Seguidamente realizaremos una descripción general y pruebas con algunas de las
colecciones existentes en el entorno, remitiendo al lector a la documentación de la
plataforma accesible desde Visual Studio .NET para los detalles más específicos.
La clase ArrayList
Los objetos de tipo colección creados con esta clase, implementan un array cuyo número
de elementos puede modificarse dinámicamente.
Instanciación de objetos ArrayList
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 373
Podemos instanciar una colección ArrayList en alguno los modos mostrados en el Código
fuente. Observe el lector, cómo en este ejemplo, el constructor de ArrayList recibe como
parámetro una colección dinámica.
Private Sub [Link]….
' crear una lista sin elementos
Dim alEstaciones As New ArrayList()
' crear una lista indicando el número de elementos pero sin darles valor
Dim alDatos As New ArrayList(3)
' crear una lista utilizando una colección dinámica
Dim alLetras As New ArrayList(New String() {"a", "b", "c"})
End Sub
Una colección dinámica se crea de forma muy similar a un array, con la diferencia de
que no es necesario usar una variable a la que asignar la colección, ya que en su lugar, se
pasa como parámetro al constructor de ArrayList. El modo de creación de una colección
dinámica consiste en utilizar la palabra clave New, seguida del tipo de dato de la colección,
los paréntesis indicativos de array, y por último, encerrados entre llaves, los valores de la
colección.
Agregar valores a un ArrayList
Una vez creado un ArrayList, podemos utilizar algunos de los métodos indicados a
continuación para añadir valores a la colección.
Add(Valor). Añade el valor representado por Valor.
AddRange(Colección). Añade un conjunto de valores mediante un objeto del
interfaz ICollection, es decir, una colección dinámica creada en tiempo de ejecución.
Insert(Posición, Valor). Inserta el valor Valor en la posición Posición del array,
desplazando el resto de valores una posición adelante.
InsertRange(Posición, Colección). Inserta un conjunto de valores mediante una
colección dinámica, a partir de una posición determinada dentro del array.
SetRange(Posición, Colección). Sobrescribe elementos en un array con los valores
de la colección Colección, comenzando en la posición Posición.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 374
El siguiente ejemplo muestra algunas formas de asignación de nuevos valores a un
ArrayList.
Private Sub Button2_Click(sender As [Link], e As [Link]) Handles
[Link]
[Link] = “ “
Dim alDatos As New ArrayList(10)
[Link]("a")
[Link](New String() {"b", "c", "d"})
[Link] = [Link] & "ArrayList después de usar Add() y AddRange()" _
& vbCrLf
RecorrerAList(alDatos)
[Link](2, "hola")
[Link] = [Link] & "ArrayList después de usar Insert()" & _
vbCrLf
RecorrerAList(alDatos)
[Link](1, New Integer() {55, 77, 88})
[Link] = [Link] & "ArrayList después de usar InsertRange()" & _
vbCrLf
RecorrerAList(alDatos)
[Link](3, New String() {"zzz", "yyy"})
[Link] = [Link] & "ArrayList después de usar SetRange()" & _
vbCrLf
RecorrerAList(alDatos)
End Sub
Private Sub RecorrerAList(ByVal alValores As ArrayList)
Dim oEnumerador As IEnumerator = [Link]()
While [Link]()
[Link] = [Link] & "Valor: " & [Link] & VbCrLf
End While
[Link] = [Link] & VbCrLf
End Sub
Los valores que espera recibir una colección son del tipo genérico Object, por lo que
podemos insertar valores de diferentes tipos de dato.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 375
Recorrer y obtener valores de un ArrayList
Para recorrer un array podemos emplear la técnica habitual del bucle For...Next y la
propiedad Count del objeto ArrayList, que devuelve el número de elementos que tiene
el objeto; o bien podemos usar un objeto del interfaz IEnumerator, proporcionado por
el método GetEnumerator( ), mucho más simple de recorrer. Ver el siguiente código
Private Sub [Link]
[Link] = “ “
' crear ArrayList y añadir valores
Dim alLetras As New ArrayList(6)
[Link]("a")
[Link](New String() {"b", "c", "d"})
' recorrer con un bucle For y usando la propiedad Count,
' tener en cuenta que al ser cero el primer índice del array,
' tenemos que restar uno a la propiedad Count
[Link] = [Link] & "Recorrer objeto ArrayList con bucle For" & VbCrLf
Dim iContador As Integer
For iContador = 0 To ([Link] - 1)
[Link] = [Link] & "Elemento actual “ & iContador & _
“ valor: “& alLetras(iContador) & vbCrLf
Next
[Link] = [Link] & vbCrLf
' recorrer el array con un enumerador
[Link] =[Link] & "Recorrer objeto ArrayList con un enumerador" & _
vbCrLf
Dim oEnumerador As IEnumerator
oEnumerador = [Link]()
While [Link]()
[Link] = [Link] & "Elemento de la lista: " & _
[Link]() & vbCrLf
End While
[Link] = [Link] & vbCrLf
End Sub
Capacidad y valores en una colección ArrayList
Cuando manipulamos un objeto ArrayList debemos distinguir entre los conceptos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 376
capacidad y valores asignados.
La capacidad de un ArrayList hace referencia al número de elementos del array
subyacente que contiene este objeto, mientras que los valores asignados se refieren a
aquellos elementos del array a los que se ha asignado valor mediante métodos como Add(
) o AddRange( ). Podemos obtener esta información a través de las propiedades Capacity
y Count del objeto colección. Ver e l código
MsgBox("Valores asignados al array: " & [Link])
MsgBox("Capacidad del array: "& [Link])
La capacidad es un aspecto de la clase ArrayList que mejora el rendimiento a la hora de
añadir o eliminar elementos del array. Analicemos esta característica con más
detenimiento.
En primer lugar, todo objeto ArrayList dispone de una propiedad oculta llamada _items,
conteniendo el array que internamente gestiona los valores asignados. Esta es una
propiedad que no puede manipular el programador, pero que puede visualizar a través
del depurador, abriendo la ventana Locales y expandiendo el contenido de un objeto
ArrayList. Ver Figura
Cuando creamos un objeto ArrayList con un tamaño como el del último ejemplo, la acción
de añadir un valor a la colección no redimensiona su array subyacente, puesto que ya está
creado con un tamaño determinado, sino que asigna un valor al siguiente elemento libre
que no hubiera sido previamente asignado. Veámoslo en el esquema de la Figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 377
Figura Asignación de valores al array subyacente de una colección ArrayList.
Este comportamiento del objeto tiene la ventaja de que mejora el rendimiento y
optimiza recursos, puesto que cada vez que añadimos o eliminamos valores, el array
_items no siempre tiene que ser redimensionado.
¿Qué sucede, sin embargo, cuando se han añadido valores y el array está completo?, pues
que el objeto ArrayList detecta esta situación y en la siguiente ocasión en que se
añade un nuevo valor, automáticamente redimensiona el array _items, duplicando
el número de elementos inicial que contenía. La Figura muestra un esquema con los
pasos de este proceso.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 378
Figura. Redimensión automática del array _items de un objeto ArrayList.
En el caso que muestra la anterior figura, después de añadir la letra m al objeto, la
propiedad Capacity devolvería 12 y la propiedad Count devolvería 9.
Un detalle muy importante que debe tener en cuenta el lector, es que al crear un objeto
ArrayList, si no especificamos el tamaño, la propiedad _items tiene una capacidad por
defecto de 16 elementos.
Obtención de subarrays a partir de un objeto ArrayList
La clase ArrayList nos proporciona métodos tanto para obtener un fragmento o rango
(subarray) de un objeto ArrayList, como para crear nuevos objetos mediante métodos
shared o compartidos. Entre este tipo de métodos, se encuentran los siguientes.
GetRange(Posición, Elementos). Obtiene un subarray comenzando en el índice
Posición, y tomando el número que indica Elementos.
FixedSize(ArrayList). Método compartido que crea un array de tamaño fijo a
partir de un objeto ArrayList pasado como parámetro. Sobre el nuevo array
obtenido, podemos modificar los elementos existentes, pero no añadir nuevos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 379
Repeat(Valor, Cantidad). Método compartido que crea un ArrayList de valores
repetidos, tomando como valor a repetir el parámetro Valor, y creando tantos
elementos como se especifica en el parámetro Cantidad.
ToArray(). Copia los elementos del ArrayList en un objeto Array, al ser ambos
arrays independientes, el objeto sobre el que se han copiado los elementos puede
modificarse sin que afecte al ArrayList.
ReadOnly( ). Método compartido que crea un objeto ArrayList de sólo lectura a
partir de un array existente.
Veamos algunos ejemplos de uso de estos métodos en el Código fuente:
Private Sub [Link]…
[Link] = “”
Dim alLetras As New ArrayList(10)
[Link](New String() {"a", "b", "c", "d", "e", "f", "g"})
[Link] = [Link] & "Array alLetras" & VbCrLf
RecorrerAList(alLetras)
' obtener un subarray con un rango determinado
Dim alRangoLetras As ArrayList
alRangoLetras = [Link](4, 2)
[Link] = [Link] &"Array alRangoLetras " & VbCrLf
RecorrerAList(alRangoLetras)
' obtener un subarray de tamaño fijo, se pueden modificar sus elementos,
' no se pueden añadir valores
Dim alLetrasFijo As ArrayList = [Link](alLetras)
'[Link]("m") <-- esto provocaría error
alLetrasFijo(2) = "vvv"
[Link] = [Link] & "Array alLetrasFijo " & VbCrLf
RecorrerAList(alLetrasFijo)
' ArrayList de valores repetidos
Dim alRepetidos As ArrayList
alRepetidos = [Link]("hola", 3)
[Link]("otro valor")
[Link] = [Link] & "Array alRepetidos" & VbCrLf
RecorrerAList(alRepetidos)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 380
' copiar ArrayList sobre un array normal
Dim aNuevo As Array
aNuevo = [Link]()
aNuevo(2) = "zzz"
[Link] = [Link] & "Array aNuevo" & VbCrLf
RecorrerArray(aNuevo)
' crear ArrayList de sólo lectura a partir de un array existente
Dim alLetrasSoloLeer As ArrayList = [Link](alLetras)
' solamente podemos recorrerlo
[Link] = [Link] & "ArrayList de sólo lectura" & VbCrLf
RecorrerAList(alLetrasSoloLeer)
' las dos líneas siguientes provocarían un error
'[Link]("yyy")
'alLetrasSoloLeer(2) = "wwer"
End Sub
Private Sub RecorrerAList(ByVal alValores As ArrayList)
Dim oEnumerador As IEnumerator = [Link]()
While [Link]()
[Link] = [Link] &"Valor: " & [Link] & VbCrLf
End While
[Link] = [Link] & VbCrLf
End Sub
Private Sub RecorrerArray(ByVal aValores As Array)
Dim oEnumerador As IEnumerator = [Link]()
While [Link]
[Link] = [Link] & "Valor: " & [Link] & VbCrLf
End While
[Link] = [Link] & VbCrLf
End Sub
Respecto a los ArrayList de tamaño fijo, tipo FixedSize, queremos advertir al lector que
a la hora de ver su contenido en el depurador, no debe consultar la propiedad _items
mencionada anteriormente, ya que esta contendrá un array de valores vacíos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 381
Este punto puede crear confusión, ya que el lector al ejecutar la aplicación sí obtendrá los
valores de la colección FixedSize, por lo que se preguntará dónde han ido a parar esos
valores.
El secreto reside en el siguiente lugar: al ejecutar con el depurador, debemos expandir la
propiedad [[Link]] del ArrayList con tamaño fijo.
Dentro de esta propiedad, que es realmente una variante del objeto ArrayList, abriremos
la propiedad _list, y de nuevo dentro de esta propiedad encontraremos otra con el nombre
_items, la cual será la que contiene realmente los valores del array de tamaño fijo. La
Figura muestra la ventana Locales del depurador ejecutando el ejemplo.
Figura : Acceso a la lista de valores de un ArrayList de tipo FixedSize.
Búsquedas en colecciones ArrayList
Además de los métodos IndexOf( ) y LastIndexOf( ), disponibles en los arrays estándar,
un ArrayList aporta el método Contains( ), que nos devuelve un valor lógico indicando
si el valor pasado como parámetro existe en el array. Veamos unos ejemplos en el Código
:
Private Sub [Link]…
[Link] = “”
Dim alLetras As New ArrayList(10)
[Link](New String() {"jj", "oo", "aa", "jj", "ee", "tt", "mm", "xx"})
Dim iPosicIndexOf As Integer
' buscar un elemento de la colección desde el principio
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 382
iPosicIndexOf = [Link]("aa")
[Link] = [Link] & "Posición al buscar con IndexOf: " & _
iPosicIndexOf & VbCrLf
Dim iPosicLastIndexOf As Integer
' buscar un elemento de la colección desde el final
iPosicLastIndexOf = [Link]("jj")
[Link] = [Link] & "Posición al buscar con LastIndexOf: " _
& iPosicLastIndexOf & VbCrLf
Dim bEncontrado As Boolean
' comprobar si existe un valor en la colección
bEncontrado = [Link]("oo")
[Link] = [Link] & "Resultado de la búsqueda con Contains: " & _
bEncontrado & VbCrLf
[Link] = [Link] & VbCrLf
End Sub
Borrado de elementos en una colección ArrayList
Para realizar un borrado de valores, la clase ArrayList proporciona los métodos
descritos a continuación.
Remove(Valor). Elimina el elemento del array que corresponde a Valor.
RemoveAt(Posicion). Elimina el elemento del array situado en el índice Posición.
RemoveRange(Posición, Elementos). Elimina el conjunto de elementos
indicados en el parámetro Elementos, comenzando por el índice Posición.
Clear( ). Elimina todos los elementos del objeto.
Debido a las causas de optimización en cuanto a ejecución comentadas en un apartado
anterior, al borrar elementos de un ArrayList, el valor de la propiedad Capacity
permanece inalterable. Eso quiere decir que si añadimos muchos valores a un ArrayList
para después eliminar gran parte de ellos, el array subyacente de la propiedad _items
no disminuirá su tamaño para ahorrar recursos. Esto no es algo preocupante sin
embargo, puesto que si utilizamos el método TrimToSize( ) de esta clase,
conseguiremos que el tamaño o capacidad del ArrayList se ajuste al número real de
elementos que contiene. El Código muestra algunos ejemplos de borrados sobre este tipo
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 383
de objeto.
Private Sub bottono1. Click…
[Link] = “”
' borra todos los elementos
Dim alLetras1 As New ArrayList(10)
[Link](New String() {"a", "b", "c", "d", "e", "f", "g"})
[Link]()
Estado("alLetras1", alLetras1)
' borra un elemento por el valor
Dim alLetras2 As New ArrayList(10)
[Link](New String() {"a", "b", "c", "d", "e", "f", "g"})
[Link]("c")
Estado("alLetras2", alLetras2)
' borra un elemento por posición
Dim alLetras3 As New ArrayList(10)
[Link](New String() {"a", "b", "c", "d", "e", "f", "g"})
[Link](5)
Estado("alLetras3", alLetras3)
' borra un rango de elementos por posición
Dim alLetras4 As New ArrayList(10)
[Link](New String() {"a", "b", "c", "d", "e", "f", "g"})
[Link](2, 3)
[Link] = [Link] & "Array alLetras4: estado antes de reajustar
tamaño" & VbCrLf
Estado("alLetras4", alLetras4)
' reajustar capacidad del array
[Link]()
[Link] = [Link] & "Array alLetras4: estado después de reajustar
tamaño" & VbCrLf
Estado("alLetras4", alLetras4)
[Link] = [Link] & VbCrLf
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 384
Public Sub Estado(ByVal sNombre As String, ByVal alValores As ArrayList)
[Link] = [Link] & "Array: “ & sNombre & VbTab & _
“ Capacidad: “ & [Link] & VbTab & “ Número de elementos: " &
[Link] & VBCrLf
[Link] = [Link] & VbCrLf
End Sub
Ordenar elementos en un objeto ArrayList
Al igual que en la clase base Array, los objetos ArrayList disponen del método Sort( ), que
ordena los elementos del array; y del método Reverse( ), que invierte las posiciones de
un número determinado de elementos del array. El Código muestra un ejemplo de cada
uno.
Private Sub [Link]….
[Link] = “”
Dim alLetras As New ArrayList(10)
[Link](New String() {"z", "t", "c", "a", "k", "f", "m"})
' ordenar
[Link]()
[Link] = [Link] & "ArrayList después de ordenar" & VbCrLf
RecorrerAList(alLetras)
' invertir posiciones de elementos
[Link](3, 3)
[Link] = [Link] & "ArrayList después de invertir elementos" &
VbCrLf
RecorrerAList(alLetras)
[Link] = [Link] & VbCrLf
End Sub
Private Sub RecorrerAList(ByVal alValores As ArrayList)
Dim oEnumerador As IEnumerator = [Link]()
While [Link]()
[Link] = [Link] &"Valor: " & [Link] & VbCrLf
End While
[Link] = [Link] & VbCrLf
End Sub
La clase Hashtable
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 385
Esta clase tiene la particularidad de que el acceso a los valores del array que gestiona
internamente se realiza a través de una clave asociada a cada elemento, al estilo de los
objetos Dictionary de versiones anteriores de VB. Como dato significativo, esta clase
implementa el interfaz IDictionary, por lo que si hemos utilizado anteriormente objetos
Dictionary, ya conocemos gran parte de su filosofía de trabajo.
En este tipo de colección no es necesario preocuparse por la posición o índice de los
elementos, ya que accedemos a ellos a través de literales, lo cual en algunas
circunstancias es mucho más cómodo de manejar.
Manejo básico de colecciones Hashtable
Supongamos como ejemplo, que un proceso en una aplicación necesita guardar de
forma temporal, datos de un cliente en un array. Podemos naturalmente utilizar un
array estándar para tal fin, como muestra el Código:
Dim aCliente = [Link](GetType(Object), 6)
aCliente(0) = 22
aCliente(1) = "Pedro"
aCliente(2) = "Naranjo"
aCliente(3) = "C/Rio Bravo, 25"
aCliente(4) = 35
aCliente(5) = 250
En un planteamiento como el anterior, debemos acordarnos, a la hora de obtener los
datos del array, que la primera posición corresponde al código de cliente, la siguiente al
nombre, etc.,. Bien es cierto que podemos utilizar constantes numéricas para cada
posición, pero sigue siendo una solución poco flexible.
Utilizando un objeto Hashtable sin embargo, tenemos la ventaja de que no
necesitamos saber la posición en que se encuentra cada valor, ya que precisamente a
cada posición le damos un nombre clave que es mediante el que accedemos
posteriormente cuando queremos obtener los valores. El ejemplo siguiente, mejora
sustancialmente el fuente del caso anterior, al estar basado en una colección
Hashtable.
PrivateSub [Link]…
[Link] = “”
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 386
' declarar colección Hashtable
Dim htCliente As Hashtable
htCliente = New Hashtable()
' añadir valores
[Link]("ID", 22)
[Link]("Nombre", "Pedro")
[Link]("Apellidos", "Naranjo")
[Link]("Domicilio", "C/Rio Bravo, 25")
[Link]("Edad", 35)
[Link]("Credito", 250)
' mostrar el número de elementos que contiene
[Link] = [Link] & "El objeto Hashtable tiene “ & _
[Link] & “ elementos" & vbCrLf
[Link] = [Link] & VbCrLf
' obtener algunos valores
[Link] = [Link] & "Obtener algunos valores del objeto Hashtable" _
& VbCrLf
[Link] = [Link] & "Domicilio: "& [Link]("Domicilio") _
& vbCrLf
[Link] = [Link] & "Nombre: "& htCliente("Nombre") & vbCrLf
[Link] = [Link] & "Credito: " & htCliente("Credito") & vbCrlf
[Link] = [Link] & vbCrLf
' recorrer el array al completo
[Link] = [Link] &"Recorrer objeto Hashtable con un enumerador" _
&vbCrLf
Dim oEnumerador As IDictionaryEnumerator
oEnumerador = [Link]()
While [Link]()
[Link] = [Link] &"Clave: “ & [Link] & vbtab & _
“ Valor: " & [Link] & vbCrLF
End While
[Link] = [Link] & vbCrLf
End Sub
Para crear un nuevo objeto Hashtable hemos utilizado el constructor sin parámetros,
que es el más básico disponible. Puesto que se trata de un constructor sobrecargado,
sugerimos al lector que consulte la documentación de .NET Framework para ver una
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 387
lista completa de todos los constructores disponibles.
Respecto a la asignación de valores a la colección, esta clase utiliza el método Add( ), cuyo
primer parámetro corresponde a la clave del elemento y el segundo corresponde al valor
que vamos a asignar a la posición de su array. Para obtener un valor del array utilizamos el
método Item( ), pasando como parámetro el nombre de la clave de la que vamos a obtener
el valor correspondiente. Al tratarse del método por defecto de esta clase no es necesario
especificarlo. Como hemos podido comprobar, el resultado es el mismo tanto si
especificamos como si no el nombre del método.
Si queremos recorrer el array al completo contenido en el objeto, podemos utilizar
el método GetEnumerator( ), que nos devuelve un enumerador para poder obtener todos
los valores del objeto en un bucle. La diferencia con los otros algoritmos de recorrido que
hemos visto anteriormente, es que al estar la colección Hashtable basada en una
combinación de clave/valor, necesitamos un enumerador basado en el interfaz
IDictionaryEnumerator, especialmente adaptado para manipular arrays de este tipo.
Como habrá comprobado el lector, un enumerador IDictionaryEnumerator proporciona la
información de la colección mediante las propiedades Key y Value, a diferencia de un
enumerador simple, basado en IEnumerator, en el que usamos la propiedad Current, para
extraer los datos.
La clase Hashtable no sitúa los valores que se añaden al array en posiciones consecutivas,
por lo que al obtener los valores mediante un enumerador posiblemente no aparecerán en
el mismo orden en el que los añadimos inicialmente. Dada la filosofía de funcionamiento
de este tipo de objetos, el orden en el que se graban los valores dentro del array no debería
ser un problema, ya que nosotros accedemos al array utilizando claves y no índices, como
sucede en un array estándar.
Operaciones varias con colecciones Hashtable
Antes de obtener valores de un objeto Hashtable, podemos comprobar que la clave o
valor que necesitamos están realmente en la colección, empleando respectivamente los
métodos ContainsKey( ) y ContainsValue( ). Al primero le pasamos como parámetro la clave
a buscar, mientras que al segundo le pasamos el valor. Ambos métodos devuelven un
resultado de tipo Boolean, que indica si la comprobación tuvo o no éxito.
Por otra parte, el método Remove( ), elimina un elemento del objeto, pasándole como
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 388
parámetro la clave a borrar, mientras que el método Clear( ), elimina el contenido
completo de la colección. El Código muestra un ejemplo.
Private Sub [Link]….
[Link] = “”
' crear colección Hashtable y añadir valores
Dim htCliente As New Hashtable()
[Link]("ID", 22)
[Link]("Nombre", "Pedro")
[Link]("Apellidos", "Naranjo")
[Link]("Domicilio", "C/Rio Bravo, 25")
[Link]("Edad", 35)
[Link]("Credito", 250)
' comprobar la existencia de elementos por la clave
Dim sClave As String
sClave = Inputbox("Introducir la clave a buscar")
sClave =Trim(sClave)
If [Link](sClave) Then
[Link] = [Link] & "La clave “ & sClave & “ existe, su valor es: "
_& htCliente(sClave) & VbCrLf
Else
[Link] = [Link] & "La clave “ & sClave & “ NO existe" & VbCrLf
End If
[Link] = [Link] & VbCrLf
' comprobar la existencia de elementos por el valor
Dim oValor As Object
oValor = InputBox("Introducir el valor a buscar")
' antes de comprobar si existe el valor debemos hacer una conversión al tipo
' específico de dato del contenido de la variable oValor
If IsNumeric(oValor) Then
oValor = CType(oValor, Integer)
Else
oValor = CType(oValor, String)
End If
' ahora comprobamos
If [Link](oValor) Then
[Link] = [Link] & "El valor “ & oValor & ” existe" & VbCrLf
Else
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 389
[Link] = [Link] & "El valor “ & oValor &” no existe" & VbCrLf
End If
' para borrar un elemento se usa la clave
[Link]("Nombre")
[Link] = [Link] & VbCrLf
RecorrerHT(htCliente)
' ahora borramos el contenido al completo del objeto
[Link]()
[Link] = [Link] & VbCrLf
End Sub
Public Sub RecorrerHT(ByVal htTabla As Hashtable)
Dim oEnumerador As IDictionaryEnumerator
oEnumerador = [Link]()
While [Link]()
[Link] = [Link] & "Clave: “ & [Link] & “ Valor: " & _
[Link] & VbCrLf
End While
End Sub
Las propiedades Keys y Values de la clase Hashtable, devuelven un array con los nombres
de las claves y los valores de un objeto Hashtable respectivamente. Realmente devuelven
un objeto del interfaz ICollection, pero ya que un array implementa este interfaz, dicho
objeto podemos manipularlo como un array.
Seguidamente mostramos un ejemplo del uso de estas propiedades en el Código. Observe
el lector el diferente modo de declarar y obtener los objetos ICollection e IEnumerator,
que en definitiva, nos llevan al mismo resultado, demostrando así, la gran flexibilidad
sintáctica que la especificación CLS proporciona al lenguaje.
Private Sub [Link]….
[Link] = “”
' crear y llenar la colección
Dim htCliente As New Hashtable()
[Link]("ID", 22)
[Link]("Nombre", "Pedro")
[Link]("Apellidos", "Naranjo")
[Link]("Domicilio", "C/Rio Bravo, 25")
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 390
[Link]("Edad", 35)
[Link]("Credito", 250)
[Link] = [Link] & "Coleccion HashTable original " & vbCrLf
RecorrerHT(htCliente) ‘Nota: Este procedimiento esta en programa anterior
[Link] = [Link] & vbCrLf
' obtener un array con las claves, y recorrer con un enumerador
Dim aClaves As ICollection
aClaves = [Link]
Dim oEnumerador As IEnumerator
oEnumerador = [Link]()
[Link] = [Link] & "Claves del objeto Hashtable" & VbCrLf
RecorrerEnumerador(oEnumerador)
' obtener un array con los valores, y recorrer con un enumerador
Dim aValores As ICollection = [Link]
Dim oEnumVal As IEnumerator = [Link]()
[Link] = [Link] & "Valores del objeto Hashtable" &vbCrLf
RecorrerEnumerador(oEnumVal)
[Link] = [Link] & VbCrLf
End Sub
Public Sub RecorrerEnumerador(ByVal oEnumerador As IEnumerator)
While [Link]
[Link] = [Link] & [Link] & VbCrLf
End While
[Link] = [Link] & VbCrLf
End Sub
Traspaso de elementos desde una colección Hashtable a un array básico
El método CopyTo( ) de la clase Hashtable, se encarga de traspasar a un array
estándar un determinado número de elementos desde un objeto Hashtable. Como ya
sablemos, cada elemento de una colección de este tipo está formado realmente por dos
componentes, clave y valor; por ello, cabe preguntarse cómo se las ingenia esta clase
para poder traspasarlos a un array normal.
La respuesta es la siguiente: lo que realmente se traspasa al array normal no
son valores independientes, sino una estructura de tipo DictionaryEntry, cuyas
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 391
propiedades son precisamente Key y Value, es decir, la clave y valor del elemento de la
colección.
El Código muestra un ejemplo, en el cual, después de crear un objeto Hashtable con
sus correspondientes valores, creamos un array normal de tipo Object al que
traspasamos los elementos desde el Hashtable.
Private Sub [Link]…
'traspaso a un arreglo basico
[Link] = ""
' crear un array Hashtable
Dim htCliente As New Hashtable()
[Link]("ID", 22)
[Link]("Nombre", "Pedro")
[Link]("Apellidos", "Naranjo")
[Link]("Domicilio", "C/Rio Bravo, 25")
[Link]("Edad", 35)
[Link]("Credito", 250)
' crear un array estándar
Dim aDeposito(10) As Object
aDeposito(0) = "aaa"
aDeposito(1) = "bbb"
aDeposito(2) = "ccc"
aDeposito(3) = "ddd"
Dim iContador As Integer
' impresion del arreglo basico
[Link] = [Link] & "datos del arreglo " & vbCrLf
For iContador = 0 To 3
[Link] = [Link] & aDeposito(iContador) & vbTab & vbCrLf
Next
[Link] = [Link] & vbCrLf
' volcar elementos del Hashtable al array estándar,
' comenzando a copiar desde una posición determinada del array estándar
[Link](aDeposito, 2)
' obtener algunos valores del objeto Hashtable que se han pasado al array normal
Dim oEntradaDicc As DictionaryEntry
[Link] = [Link] & "datos trasladados al arreglo " & vbCrLf
For iContador = 3 To 6
oEntradaDicc = aDeposito(iContador)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 392
[Link] = [Link] & "Clave: " & vbTab & [Link] & vbTab &
" Valor: " & [Link] & vbCrLf
Next
[Link] = [Link] & vbCrLf
End Sub
Como el array normal tenía valores asignados previamente, algunos de ellos se pierden,
puesto que el método CopyTo( ) no redimensiona el array normal. Tenga este hecho en
cuenta el lector, ya que el array destino deberá tener el suficiente tamaño cuando
traspasamos valores desde una colección de este tipo.
La clase SortedList
Esta clase es una variación de Hashtable, ya que nos permite crear colecciones basadas
en pares de claves y valor, pero con la diferencia de que en una colección SortedList, los
elementos se ordenan por la clave según van siendo agregados. El funcionamiento general,
es básicamente igual que para los objetos Hashtable. Veamos un ejemplo en el Código:
Private Sub [Link]…..
' crear una colección
Dim slListaOrden As New SortedList()
' según añadimos elementos, se van
' ordenando dinámicamente
[Link]("H", 111)
[Link]("A", 222)
[Link]("Z", 333)
[Link]("M", 444)
' recorrer la colección SortedList
Dim oEnumerador As IDictionaryEnumerator
oEnumerador = [Link]()
While [Link]()
[Link] = [Link] & "Clave: “ &[Link] & “ Valor: "
& [Link] & VbCrLf
End While
[Link] = [Link] & VbCrLf
End Sub
La clase Queue
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 393
Esta clase implementa toda la operativa de una lista de tipo FIFO (first in, first out),
primero en entrar/primero en salir; también denominada cola de valores. A pesar de lo
básico de su funcionalidad, es un aspecto que el programador agradece en muchas
situaciones. La Figura muestra un esquema del funcionamiento de este tipo de objeto.
Figura Representación gráfica del funcionamiento de una colección Queue.
Como el resto de clases en el espacio de nombres [Link], los objetos de
tipo Queue contienen un array gestionado por la propia clase e inaccesible para el
programador, que almacena los valores que vamos encolando. Este array parte con un
tamaño inicial y es redimensionado por el propio objeto cuando todos sus elementos
han sido asignados y se intenta añadir un nuevo valor.
Manipulación de valores en una colección Queue
El método Enqueue( ) añade nuevos valores, que quedan situados al final de la lista,
del modo ilustrado en la figura anterior.
Para desarrollar un ejemplo de uso de la clase Queue, vamos a plantear la siguiente
situación: necesitamos implementar un sistema de recepción y envío de mensajes. El primer
mensaje entrante se situará en la lista de modo que será el primero en enviarse, el
segundo mensaje recibido será el siguiente enviado y así sucesivamente.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 394
El Código mostrado a continuación, ilustra el modo de introducción de valores, en un
estilo diferente al utilizado en los anteriores ejemplos. En este caso, en lugar de
introducir directamente por código los valores en la lista, utilizaremos el método
ReadLine( ) del objeto Console, de manera que el usuario introduzca los valores que
precise. Cuando pulse [INTRO] sin haber escrito valor alguno, se considerará que ha
terminado la introducción de datos.
Private Sub [Link]….
' crear objeto Queue, cola de valores
Dim aqListaMensa As New Queue()
[Link] = [Link] & "Introducir mensajes" & VbCrLf
Dim sMensaje As String
' bucle de recepción de mensajes
Do
sMensaje = Input(“Escriba mensaje, no escriba y enter para terminar”)
' si hemos escrito algo...
If [Link] > 0 Then
' añadimos a la cola
[Link](sMensaje)
Else
' si no escribimos nada salimos
Exit Do
End If
loop
' la propiedad Count nos indica la cantidad de ' elementos en la lista
[Link] = [Link] & "Hay “ [Link] & “ mensajes para
procesar" & vbCrLf
' con un enumerador recorremos la lista
Dim oEnumerador = [Link]()
[Link] = [Link] & "Contenido del objeto Queue" &VbCrLf
[Link] = [Link] & VbCrLf
RecorrerEnumerador(oEnumerador)
[Link] = [Link] & VbCrLf
End Sub
Public Sub RecorrerEnumerador(ByVal oEnumerador As IEnumerator)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 395
While [Link]
[Link] = [Link] & [Link] & VbCrLf
End While
[Link] = [Link] & VbCrLf
End Sub
Normalmente, en un sistema de gestión de mensajes, una vez que solicitamos un
mensaje, este es enviado y borrado de su contenedor. Pues algo similar es lo que
haremos seguidamente, ya que después de que el usuario haya introducido todos los
mensajes, utilizaremos el método Dequeue( ), que irá extrayendo o desencolando cada
uno de los valores de la lista, comenzando por el primero que fue introducido. Este
método, además de devolver el valor, lo elimina de la lista. Ver el Código fuente
Private Sub [Link]….
' utilizando el método Dequeue() para desencolar
Dim aqListaMensa As New Queue()
Dim sMensaje As String
Dim iContador As Integer
' bucle de recepción de mensajes
Do
iContador += 1
[Link] = [Link] & " Mensaje nro. " & iContador & vbCrLf
sMensaje = InputBox("escriba mensaje , no escriba y enter para terminar")
' si hemos escrito algo...
If [Link] > 0 Then
' añadimos a la lista
[Link](sMensaje)
Else
' si no escribimos salimos
Exit Do
End If
Loop
[Link] = [Link] & vbCrLf
' la propiedad Count nos indica la cantidad de elementos en la lista
[Link] = [Link] & "Hay " & [Link] & " mensajes para
procesar" & vbCrLf
[Link] = [Link] & vbCrLf
' procesar los mensajes de la lista
iContador = 0
[Link] = [Link] & "Procesar lista de mensajes" & vbCrLf
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 396
While [Link] > 0
iContador += 1
[Link] = [Link] & "Mensaje nro. " & iContador & vbTab & " texto: "
& vbTab & _
[Link]() & vbCrLf
[Link] = [Link] & "Quedan " & [Link] & " mensajes
por procesar" & vbCrLf
[Link] = [Link] & vbCrLf
End While
[Link] = [Link] & vbCrLf
End Sub
Pero supongamos que queremos comprobar el contenido del próximo mensaje a
procesar antes de sacarlo de la lista. En ese caso, el método Peek( ) de la clase
Queue es el indicado, ya que precisamente devuelve el siguiente valor de la lista sin
eliminarlo, como ilustra el Código :
[Link] = [Link] & "Obtenemos el primer valor sin eliminar: " &
[Link]())
Puede ocurrir también, que necesitemos obtener los valores de la lista pero sin
eliminarlos, por ejemplo, para poder repetir el proceso posteriormente. ¿Tenemos que
volver a pedirlos al usuario?, no en absoluto, ya que mediante el método Clone( ) de la clase
Queue, podemos obtener un nuevo objeto independiente, pero con los mismo elementos.
A partir de ese momento, aunque procesemos la lista original, mantendremos los datos en
una copia del objeto.
Otra técnica consiste en utilizar el método ToArray( ), que copia los valores de la lista a
un array estándar. Dicho array deberá haber sido previamente creado con el tamaño
adecuado, ya que si tiene menos elementos que el objeto Queue, cuando copiemos los
valores al array se producirá un error.
Para saber el tamaño del array que tenemos que crear, podemos ayudarnos de la propiedad
Count del objeto Queue. El Código muestra unos ejemplos.
Private Sub [Link] …
' crear objeto Queue e introducir valores
Dim aqListaMensa As New Queue()
'....
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 397
' crear copia de seguridad de la lista
Dim aqCopiaMensajes As Queue = [Link]()
' o también, podemos crear un array normal con los elementos del objeto Queue
Dim aListaDatos As Array = [Link](GetType(Object), _
[Link])
aListaDatos = [Link]()
' procesar los mensajes de la lista original, mantendremos los valores en el objeto
' clonado o en un array
[Link] = [Link] & " datos de la cola " & vbCrLf
Dim oEnumerador = [Link]()
RecorrerEnumerador(oEnumerador)
[Link] = [Link] & vbCrLf
End Sub
Copiando los valores a un array, tenemos la ventaja de poder ordenarlos, o hacer cualquier
operación que nos permita la clase Array. Y ya para terminar con esta clase, el método
Clear() elimina todos los valores del array interno que mantiene un objeto Queue. Podemos
utilizar este método en el caso de que después de haber obtenido algunos valores de la lista,
no queramos seguir extrayendo información, pero necesitemos el objeto vacío para poder
repetir el proceso de captura de datos.
La clase Stack
Al igual que en el caso anterior, esta clase nos permite gestionar colas de valores, pero
los objetos de este tipo, crean listas de valores al estilo de pilas LIFO (last in, first out),
último en entrar/primero en salir.
Su modo de manejo es similar a las colecciones Queue, con la característica de que en
una pila, los valores que extraemos son los últimos que han entrado. Veamos un ejemplo en
el Código :
Private Sub [Link]…
' creamos una colección de tipo pila
Dim oPila As Stack
oPila = New Stack()
' para añadir valores, usamos el método Push()
[Link]("A") ' este será el último en salir
[Link]("B")
[Link]("C")
[Link]("D")
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 398
[Link]("E") ' este será el primero en salir
' para extraer un valor de la pila, usamos el método Pop(),
'dicho valor se eliminará de la lista
[Link] = [Link] & " Obtenemos los datos de la pila creada " & vbCrLf
[Link] = [Link] & vbCrLf
While [Link] > 0
[Link] = [Link] & "El valor obtenido de la pila es: " & [Link] &
vbCrLf
End While
End Sub
Colecciones personalizadas
Cuando el tipo de array que necesitamos no existe
Los arrays básicos proporcionados por el entorno de .NET, a través de la clase Array,
proveen al programador, a través del conjunto de miembros que implementan, de
un excelente conjunto de funcionalidades para realizar la manipulación de listas de
valores.
Por si ello no fuera suficiente, disponemos además del espacio de nombres
[Link], que aportan un conjunto de clases, que nos facilitan objetos para
manejar arrays con características avanzadas.
Pese a todo, habrá ocasiones en que necesitemos trabajar con un array de un modo
especial, y no dispongamos entre los miembros de la clase Array, ni entre las
clases de Collection, de las funcionalidades requeridas. Sin embargo, gracias a la
arquitectura orientada a objeto de la plataforma, podemos crear nuestras propias clases
para la manipulación de arrays, heredando de las colecciones existentes o
implementando los interfaces necesarios.
Utilizando la herencia para crear una nueva colección
Situémonos en primer lugar en un escenario de ejemplo: estamos desarrollando una
aplicación en la que utilizamos colecciones de tipo ArrayList. Sin embargo,
necesitamos que dichas colecciones admitan sólo números, y que además, el array de
la colección esté ordenado.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 399
Dado que estas características no están implementadas en los objetos ArrayList, pero
este tipo de colección se adapta en gran medida a nuestras necesidades, crearemos una
nueva clase con el nombre NumerosOrden, que herede de ArrayList, y en la que
codificaremos el comportamiento personalizado que necesitamos. Ver el Código:
' Creamos una clase que herede de ArrayList, que ordene los elementos del array,
' y que sólo admita números
Class NumerosOrden
Inherits ArrayList
' sobrescribimos el método Add() de la clase base;
' sólo vamos a permitir añadir números a la colección
Public Overrides Function Add(ByVal value As Object) As Integer
' si es un número, añadimos
If IsNumeric(value) Then
[Link](value) ' llamamos al método base
[Link]() ' ordenamos el array
Return [Link] ' devolvermos el número de elementos que hay
Else
' si no es un número...
Return -1
End If
End Function
End Class
Para usar esta clase desde el código cliente, instanciaremos un objeto y trabajaremos con
él como si se tratara de una colección normal. Ver el Código siguiente:
Private Sub [Link]…
' instanciar un objeto de nuestra
' colección personalizada que ordena números
Dim oNumOr As New NumerosOrden()
[Link](980)
[Link](500)
[Link](25)
[Link](700)
' recorrer la colección
Dim oEnumera As IEnumerator = [Link]()
[Link] = [Link] & "Colección ordenada de números" & vbcCrLf
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 400
While [Link]
[Link] = [Link] & "valor: "& [Link] & vbCrLf
End While
[Link] = [Link] & vbCrLf
End Sub
En este ejemplo, el lector ha podido comprobar cómo con una mínima cantidad de código
en una clase derivada, conseguimos toda la potencia de una colección base, y
le proporcionamos un comportamiento del que originalmente carecía.
Implementando un interfaz para crear una nueva colección
Como acabamos de comprobar en el ejemplo anterior, la creación de nuevas clases de
tipo collection mediante herencia es una estupenda solución. Debido a que el código
principal ya existe en la clase base, simplemente tenemos que añadir el código para el
nuevo comportamiento en la clase derivada, mediante la creación de nuevos miembros,
a través de sobrecarga, o sobre-escritura. Sin embargo, esta técnica tiene el
inconveniente de que no podemos modificar o eliminar ciertos comportamientos de la
clase base.
Para salvar este obstáculo, en lugar de heredar de una colección, podemos emplear otra
técnica, que consiste en crear una clase, e implementar en ella uno o varios interfaces de
los incluidos en el espacio de nombres [Link], los cuales definen las
características que deben tener los arrays y colecciones del entorno.
La ventaja de implementar interfaces de colección en una clase, reside en que
tenemos control absoluto en cuanto al comportamiento que tendrán los objetos
collection que instanciemos de dicha clase. Aunque como inconveniente, tenemos el
hecho de que la implementación de un interfaz, obliga a codificar todos los miembros
que vienen en la declaración de dicho interfaz; respecto a esto último, podemos escribir
sólo la declaración de algunos miembros y no su código; de esta manera, para
aquellos aspectos del interfaz en los que no estemos interesados, no será necesario
codificar.
Supongamos como ejemplo, que necesitamos en nuestro programa una colección
que convierta a mayúsculas los valores que añadimos o modificamos. Para ello, vamos a
crear una clase con el nombre ListaMay, que implemente el interfaz IList. Este interfaz
está compuesto por un numeroso conjunto de miembros, pero nosotros sólo vamos a
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 401
codificar los siguientes.
Add( ). Añadir un nuevo elemento.
Item( ). Asigna u obtiene un valor.
Contains( ). Comprueba si existe un valor entre los elementos de la colección,
devolviendo un valor lógico Verdadero si existe, o Falso en el caso de que no exista.
Count. Devuelve el número de elementos que hay en la colección.
GetEnumerator( ). Devuelve un enumerador para recorrer el array de la colección.
Clear( ). Elimina los valores de los elementos del array que tiene la colección.
Para el resto de miembros del interfaz, aunque no vayamos a utilizarlos, debemos crear
su declaración vacía, ya que en caso contrario, se producirá un error al intentar
ejecutar el programa, porque el entorno detectará la falta de la creación de los
miembros de dicho interfaz en nuestra clase.
No codificamos todos los miembros del interfaz para simplificar el presente ejemplo,
y al mismo tiempo, demostramos que sólo hemos de escribir código para aquellos
aspectos del interfaz que necesitemos, aunque lo recomendable sería, evidentemente,
implementar correctamente todos los métodos y propiedades que indica el interfaz.
Veámoslo en el Código:
' esta clase implementa la funcionalidad de una colección;
' admite como elementos cadenas de caracteres, y los convierte a mayúsculas
Class ListaMay
' para conseguir el comportamiento de una colección
' en esta clase implementamos el siguiente interfaz Implements IList
' declaramos un array que contendrá los valores de la colección
Protected aValores() As String
' a partir de aquí, debemos declarar todos los miembros
' del interfaz, y codificar aquellos que necesitemos
' -----------------------------------------------------
Public ReadOnly Property Count() As Integer _
Implements [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 402
Get
If Not (aValores Is Nothing) Then
Count = [Link]
End If
End Get
End Property
Public ReadOnly Property IsSynchronized() As Boolean _
Implements [Link]
Get
End Get
End Property
Public ReadOnly Property SyncRoot() As Object _
Implements [Link]
Get
End Get
End Property
Public Function GetEnumerator() As [Link] _
Implements [Link]
Return [Link]()
End Function
Public Function Add(ByVal value As Object) As Integer _
Implements [Link]
If aValores Is Nothing Then
ReDim Preserve aValores(0)
aValores(0) = CStr(value).ToUpper()
Else
Dim iIndiceMayor As Integer = [Link](0)
ReDim Preserve aValores(iIndiceMayor + 1)
aValores(iIndiceMayor + 1) = CStr(value).ToUpper()
End If
Return [Link]
End Function
Public Sub Clear() _
Implements [Link]
[Link](aValores, 0, [Link])
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 403
Public Function Contains(ByVal value As Object) As Boolean _
Implements [Link]
Dim oEnumera As IEnumerator
oEnumera = [Link]()
While [Link]
If ([Link] = CType(value, String).ToUpper()) Then
Return True
End If
End While
Return False
End Function
Public Function IndexOf(ByVal value As Object) As Integer _
Implements [Link]
End Function
Public ReadOnly Property IsFixedSize() As Boolean _
Implements [Link]
Get
End Get
End Property
Public ReadOnly Property IsReadOnly() As Boolean _
Implements [Link]
Get
End Get
End Property
Default Public Property Item(ByVal index As Integer) As Object _
Implements [Link]
Get
Item = [Link](index)
End Get
Set(ByVal Value As Object)
Dim oTipo As Type
oTipo = [Link]()
If [Link] = "String" Then
[Link](CType(Value, String).ToUpper(), index)
Else
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 404
[Link](Value, index)
End If
End Set
End Property
Public Sub Remove(ByVal value As Object) _
Implements [Link]
End Sub
Public Sub RemoveAt(ByVal index As Integer) _
Implements [Link]
End Sub
Public Sub Insert(ByVal index As Integer, ByVal value As Object) _
Implements [Link]
End Sub
Public Sub CopyTo(ByVal array As [Link], ByVal index As Integer) _
Implements [Link]
End Sub
End Class
Desde código cliente, el modo de utilizar nuestra nueva clase es igual que para una de
las colecciones normales, aunque debemos tener en cuenta los métodos no codificados,
para no utilizarlos. Veamos el Código :
Private Sub [Link]
' instanciar un objeto de la colección personalizada
Dim oLis As ListaMay = New ListaMay()
[Link] = [Link] &"Número de elementos " & [Link] & vbCrLf
[Link] = [Link] & vbCrLf
' añadir valores
[Link]("Esta es")
[Link]("mi clase")
[Link]("de arrays personalizados")
RecorrerMiLista(oLis)
[Link] = [Link] &"Número de elementos " & [Link] & vbCrLf
[Link] = [Link] & vbCrLf
' comprobar si existe un valor
Dim sValorBuscar As String
[Link] = [Link] &"Introducir un valor a buscar en la colección" &
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 405
vbCrLf
sValorBuscar = [Link]()
If [Link](sValorBuscar) Then
[Link] = [Link] &"El valor introducido sí existe" & vbCrLf
Else
[Link] = [Link] &"El valor introducido no existe" & vbCrLf
End If
[Link] = [Link] & vbCrLf
' eliminar valores de la colección (no elimina elementos)
[Link]()
' asignar valores a los índices existentes de la colección
oLis(2) = "mesa"
[Link](0) = "coche"
RecorrerMiLista(oLis)
[Link] = [Link] & vbCrLf
End Sub
Public Sub RecorrerMiLista(ByVal oListaValores As ListaMay)
Dim oEnumera As IEnumerator
oEnumera = [Link]()
While [Link]
[Link] = [Link] & "valor " & [Link] & vbCrLf
End While
[Link] = [Link] & vbCrLf
End Sub
11.- GDI+ Sistema gráfico de Windows
GDI+ es la evolución de GDI, el API para la manipulación de gráficos incluido en anteriores
versiones de Windows.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 406
Al tratarse de un interfaz de programación independiente del dispositivo físico sobre el
que se van a generar los gráficos, el programador gana en flexibilidad, ya que no debe
preocuparse de si el gráfico generado se va a mostrar por el monitor, impresora, etc.;
esta labor es resuelta por GDI+, que aísla el programa del hardware a manejar.
GDI+ divide su campo de trabajo en tres áreas principales.
Generación de gráficos vectoriales 2D
Manipulación de imágenes en los formatos gráficos más habituales.
Visualización de texto en un amplio abanico de tipos de letra.
En versiones anteriores del lenguaje, el objeto Form disponía de una serie de métodos y
controles para el dibujo sobre la superficie del formulario. La mayor parte de esos
elementos han desaparecido en la actual versión de VB, integrándose todas las operaciones
de dibujo en las clases de .NET Framework; con ello, lo que aprendamos sobre trabajo
con gráficos en [Link] utilizando GDI+, nos servirá igualmente si en un futuro debemos
abordar un proyecto en otro lenguaje de la plataforma, ya que las clases pertenecen a .NET
Framework y no a un lenguaje en particular.
Otro problema con el que nos enfrentábamos anteriormente era el hecho de que al
necesitar alguna manipulación gráfica especial, teníamos que recurrir al API de Windows.
A partir de ahora esto no será necesario, ya que como hemos comentado, es el propio
entorno de ejecución de .NET el que nos proporciona dicho acceso, por lo que no será
necesario acudir al API del sistema operativo.
[Link]
Para utilizar las clases relacionadas con la manipulación de gráficos, es preciso importar
este espacio de nombres.
[Link] contiene el conjunto de clases principales, aunque no es el único
namespace de GDI+; para tareas de mayor especialización con gráficos deberemos
recurrir a alguno de los siguientes espacios de nombre que están dentro de
[Link]: Drawing2D, Imaging y Text.
Dibujo con las clases Graphics y Pen
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 407
La clase Graphics representa el denominado Contexto de dispositivo gráfico (Graphics device
context)
sobre el que se va a realizar una operación de dibujo, por ejemplo, el formulario.
Debido a la arquitectura del sistema gráfico, no es posible tomar un objeto Form y
realizar una operación directa de dibujo sobre el mismo, sino que precisamos en
primer lugar, obtener una referencia hacia el área de dibujo de dicho formulario, o
contexto gráfico, y una vez obtenida esa referencia, efectuar el dibujo.
Este área lo vamos a obtener mediante el método CreateGraphics( ) de la clase Form, que
devuelve un objeto Graphics con la información del contexto de dispositivo gráfico del
formulario, que usaremos para dibujar sobre el mismo, mediante el conjunto de métodos
DrawXXX( ).
Por otro lado, la clase Pen representa un objeto de tipo lapicero o bolígrafo, que con un
determinado color y grosor, utilizará un objeto Graphics para dibujar líneas y formas en un
contexto de dispositivo,
es decir, el formulario.
El Código fuente 535 muestra un ejemplo de dibujo de un círculo sobre el formulario
utilizando el método DrawEllipse( ) de Graphics. Este método recibe como parámetro un
objeto Pen con un color y grosor determinados y un objeto Rectangle con las
coordenadas y medida necesarias para dibujar el círculo.
' crear objeto Pen
Dim oPen As New Pen([Link], 10)
' obtener el contexto de dispositivo
' gráfico del formulario
Dim oGraphics As Graphics = [Link]()
' dibujar en el formulario
[Link](oPen, New Rectangle(150, 20, 100, 100))
Asociando este código a la pulsación de un botón en el formulario, el resultado será el
dibujo del círculo mostrado en la Figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 408
. Dibujar un círculo con un objeto Pen.
Sin embargo, el dibujo de figuras de esta manera tiene un inconveniente, puesto que si el
formulario es ocultado parcial o totalmente por otro, la zona ocultada se dice que ha
quedado invalidada, y requiere un repintado, labor que actualmente, no indicamos que se
haga en el código del formulario.
Para mantener las figuras dibujadas en el formulario en todo momento, debemos
recurrir al evento Paint( ) de la clase Form. Dicho evento se produce cada vez que el
formulario necesita repintarse porque parte o la totalidad de su superficie ha quedado
invalidada
Vamos por lo tanto a observar las diferencias codificando el mencionado evento Paint( ),
en el que dibujaremos un rectángulo. Ver Código fuente
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
' crear objeto Pen
Dim oPen As New Pen([Link], 6)
' obtener el contexto de dispositivo
' gráfico del formulario; en este caso usaremos el objeto que contiene
' los argumentos de evento para obtener dicho contexto de dispositivo
Dim oGraph As Graphics = [Link]
' dibujar en el formulario
[Link](oPen, New Rectangle(40, 80, 70, 70))
End Sub
Al ejecutar el programa, el rectángulo será mostrado en todo momento, aunque
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 409
minimicemos el formulario, lo ocultemos parcial, totalmente, etc., ya que este evento se
ejecuta automáticamente cada vez que el formulario detecta que su superficie ha
quedado invalidada y necesita repintarse. La Figura muestra el formulario con ambas
figuras dibujadas, si ocultamos y mostramos de nuevo la ventana, comprobaremos
como el círculo ha desaparecido mientras que el rectángulo persiste.
Figuras dibujadas en la superficie del formulario desde un botón y el evento Paint.
El proyecto GraficosGDI , contiene a través de las opciones de sus menús, el conjunto de
operaciones de dibujo que describiremos seguidamente.
Mediante el menú Dibujo con Pen, dibujaremos un círculo, rectángulo, curva, polígono, etc.
Consulte el lector sus opciones para comprobar el código para cada tipo de figura.
A continuación comentaremos las más destacables.
Al dibujar un rectángulo vamos a modificar el estilo de línea mediante la propiedad
DashStyle. Esta propiedad contiene una enumeración con la que podemos hacer que la
línea se muestre como guiones, guiones y puntos, etc. Ver Código fuente
Private Sub mnuPenRectangulo_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' crear objeto Pen
Dim oPen As New Pen([Link], 4)
' aplicar un estilo de línea con la propiedad
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 410
' DashStyle --> guión, punto
[Link] = [Link]
' obtener el contexto de dispositivo
' gráfico del formulario
Dim oGraphics As Graphics = [Link]()
' dibujar en el formulario
[Link](oPen, New Rectangle(280, 75, 120, 40))
End Sub
Si queremos aplicar más estilos a la línea del objeto Pen, disponemos también de las
propiedades StartCap, EndCap, DashCap. El Código fuente 538 muestra el dibujo de una
curva con varios efectos de línea. Al dibujar una curva, necesitamos pasar al método
DrawCurve( ) un array de tipos Point, con las coordenadas de referencia a usar para el dibujo
de la curva.
Private Sub mnuPenCurva_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' crear objeto Pen
Dim oPen As New Pen([Link], 5)
' configurar estilo de línea
[Link] = [Link]
[Link] = [Link]
[Link] = [Link]
[Link] = [Link]
' obtener el contexto de dispositivo gráfico del formulario
Dim oGraphics As Graphics = [Link]()
' crear un array de puntos-coordenadas necesario para dibujar una curva
Dim oPuntos(4) As Point
oPuntos(0) = New Point(10, 200)
oPuntos(1) = New Point(40, 100)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 411
oPuntos(2) = New Point(100, 20)
oPuntos(3) = New Point(130, 100)
oPuntos(4) = New Point(200, 200)
' dibujar en el formulario
[Link](oPen, oPuntos)
End Sub
En cuanto a las curvas de tipo Bezier, el método DrawBezier( ) recibe como parámetros, el
objeto Pen y una lista de coordenadas para el dibujo. Ver el Código fuente
Private Sub mnuPenBezier_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' dibujar curva estilo Bezier
Dim oGraphics As Graphics = [Link]()
[Link](New Pen([Link], 2), 20, 45, 100, 90, 140,
200, 300, 25)
End Sub
La Figura muestra todas las formas dibujadas con objetos Pen.
Si en un momento dado, necesitamos borrar los elementos gráficos dibujados en la
superficie del formulario, utilizaremos el método Invalidate( ) de la clase Form, que en este
ejemplo está disponible en la opción de menú Abrir + Borrar. Ver Código fuente .
Private Sub mnuBorrar_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' borrar las figuras dibujadas en el formulario
[Link]()
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 412
. Figuras dibujadas con objetos de la clase Pen.
La clase Brush
Esta clase representa un objeto de tipo brocha, utilizado para rellenar de diferentes formas,
las figuras dibujadas sobre el formulario.
Se trata de una clase abstracta, por lo que tendremos que utilizar alguna de sus
diversas clases derivadas, según el estilo de brocha que necesitemos aplicar. Debido
a las características 2D de algunas de estas clases, tendremos que importar en nuestro
código el espacio de nombres Drawing2D.
Los métodos de la clase Graphics que utilizaremos para dibujar con brochas serán los que
comienzan por el nombre FillXXX( )
El menú Dibujo con Brush del formulario de este ejemplo, muestra algunas de las
operaciones de dibujo y estilos de relleno, que podemos aplicar con las clases de tipo Brush.
La clase más básica es SolidBrush, que permite rellenar en un estilo sencillo un área
dibujada. Ver el Código fuente
Private Sub mnuBrushSolid_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 413
Dim oBrush As New SolidBrush([Link])
Dim oGraphics As Graphics = [Link]()
[Link](oBrush, New Rectangle(150, 160, 150, 50))
End Sub
A continuación tenemos la clase HatchBrush, que permite la creación de brochas que al
pintar aplican un efecto de tramado con un color de fondo y frente. Ver el Código fuente
Private Sub mnuBrushHatch_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' pintar con brocha de tipo hatch; para utilizar este tipo de brocha
' necesitamos importar [Link].Drawind2D
' crear objeto HatchBrush
Dim oHatchBrush As New HatchBrush([Link], [Link],
[Link])
' dibujar y pintar un polígono
Dim oGraphics As Graphics = [Link]()
[Link](oHatchBrush, New Rectangle(25, 40, 150, 50))
End Sub
Podemos emplear un bitmap como base para la zona de relleno que tendrá que
pintarse, para ello usaremos la clase TextureBrush, pasándole como parámetro un
objeto Bitmap, que previamente habremos creado, y que contendrá un fichero con la
textura necesaria. Ver Código fuente
Private Sub mnuBrushTextura_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' crear un bitmap
Dim oBitmap As New Bitmap("[Link]")
' crear una brocha de textura
Dim oTextureBrush As New TextureBrush(oBitmap)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 414
' dibujar una figura y pintarla con la brocha de textura
Dim oGraphics As Graphics = [Link]()
[Link](oTextureBrush, New Rectangle(220, 15, 100, 75))
End Sub
Para efectos avanzados de relleno, consistentes en degradados de colores,
utilizaremos las clases LinearGradientBrush y PathGradientBrush. Una vez creado
un objeto Brush de estas clases, aplicaremos un conjunto de colores que serán
mezclados para crear un efecto de degradado o fundido en el área a pintar, mediante
el constructor y/o las propiedades de la clase que corresponda. Ver Código fuente
' pintar figura con brocha LinearGradientBrush
Private Sub mnuBrushLinearG_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' crear brocha de tipo LinearGrad.
Dim oLGB As New LinearGradientBrush(New Rectangle(10, 50, 40, 60),
[Link], [Link], [Link])
' crear array de coordenadas
Dim oPuntos(2) As Point
oPuntos(0) = New Point(20, 200)
oPuntos(1) = New Point(75, 100)
oPuntos(2) = New Point(140, 220)
' obtener contexto gráfico
Dim oGraphics As Graphics = [Link]()
' dibujar y pintar una curva cerrada
[Link](oLGB, oPuntos)
End Sub
'-------------------------------------------
' pintar figura con brocha PathGradientBrush
Private Sub mnuBrushPathG_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' array de coordenadas
Dim oPuntos(2) As Point
oPuntos(0) = New Point(100, 150)
oPuntos(1) = New Point(175, 80)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 415
oPuntos(2) = New Point(210, 150)
' crear brocha de tipo PathGradient,
' y configurar el objeto
Dim oPGB As New PathGradientBrush(oPuntos)
[Link] = [Link]
[Link] = New Color() {[Link], [Link]}
' crear gráfico y pintar polígono
Dim oGraphics As Graphics = [Link]()
[Link](oPGB, oPuntos)
End Sub
La Figura muestra todas las formas dibujadas con objetos de los tipos derivados de Brush.
Figuras dibujadas y pintadas con objetos derivados de Brush.
Dibujo de texto en el formulario
Aparte de los controles que nos permiten visualizar y editar texto en un formulario,
como Label, TextBox, etc., podemos realizar operaciones de dibujo de texto en la
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 416
superficie del formulario, empleando el método DrawString( ) de la clase Graphics.
El texto visualizado mediante esta técnica no es evidentemente editable, se
encamina fundamentalmente a mostrar texto con efectos adicionales que no podríamos
conseguir mediante los controles típicos.
En el formulario de nuestro ejemplo, la opción de menú Texto + Dibujar texto, crea
un objeto HatchBrush con un tramado específico, un objeto Font de una determinada
familia, y con ambos elementos, pinta el texto mediante un objeto Graphics. Ver el
Código fuente
Private Sub mnuTextoTxt_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' crear un objeto Brush con efectos
Dim oBrush As New HatchBrush([Link], [Link], [Link])
' crear el tipo de letra
Dim oFont As New Font(New FontFamily("Georgia"), 50)
' obtener el dispositivo gráfico del formulario y pintar el texto
Dim oGraf As Graphics = [Link]()
[Link]("Texto en modo gráfico", _
oFont, oBrush, New RectangleF(20, 20, 500, 200))
End Sub
La Figura muestra el texto dibujado en el formulario.
Dibujo de texto empleando clases de manipulación de gráficos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 417
Personalización de la imagen de fondo del formulario
En un tema anterior explicamos que la propiedad BackgroundImage nos permite asignar
un fichero de imagen para el fondo del formulario. La facilidad que proporciona
esta propiedad tiene desafortunadamente su lado negativo, ya que el tamaño de
la imagen asignada, no se adapta automáticamente al del formulario.
Por tal motivo, en este apartado vamos a proporcionar al lector un par de técnicas, que
le permitirán crear imágenes de fondo para formularios con ajuste dinámico, para
que la imagen adapte sus dimensiones a las del formulario, cuando este cambie su
tamaño en tiempo de ejecución.
Manipulación de los eventos de pintado en la clase Form
El primer ejemplo, contenido en el proyecto FondoFormManual se basa en la codificación
del evento Paint( ) de la clase Form.
Dentro del procedimiento manipulador de este evento, creamos un objeto Bitmap
que contenga la referencia hacia un fichero con el gráfico a mostrar de fondo, y con un
objeto Graphics, obtenido del parámetro EventArgs del evento, pintamos el objeto
Bitmap. Ver el Código fuente 546.
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
' crear un objeto bitmap
Dim oBitmap As New Bitmap("[Link]")
' pintar el objeto con el contexto gráfico del formulario;
' el area a pintar abarca desde la coordenada 0,0 y toma el ancho
' y alto del formulario de su propiedad Size
Dim oGraphics As Graphics = [Link]
[Link](oBitmap, 0, 0, [Link], [Link])
End Sub
Queda todavía un paso más, ya que aunque la imagen se muestra como fondo del
formulario, si redimensionamos este, sólo se repinta la parte nueva redimensionada,
produciendo un efecto no deseado. Ver Figura
Para conseguir que se pinte por completo toda la imagen, debemos invalidar la zona
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 418
gráfica del formulario mediante su método Invalidate( ), en el evento Resize, el cual es
provocado cada vez que cambia el formulario de tamaño. Después de escribir el
Código fuente cuando volvamos a ejecutar el ejemplo, la imagen de fondo se adaptará
en todo momento a las medidas del formulario.
Imagen de fondo con repintado irregular.
Private Sub Form1_Resize(ByVal sender As Object, ByVal e As [Link])
Handles [Link]
' cada vez que cambie el tamaño del formulario invalidamos su área 'de dibujo para
que el evento Paint pinte toda la superficie
[Link]()
End Sub
Empleo del control PictureBox
Después de la técnica compleja (sólo en parte), vamos ahora con el modo fácil para crear
una imagen de fondo, que pasa por el uso del control PictureBox.
Este control nos permite la visualización de imágenes en el formulario de un modo
sencillo, ya que toda la mecánica de generación la lleva incorporada, con lo que el
programador se despreocupa de la manipulación del gráfico a mostrar.
El proyecto FondoFormPicB contiene esta aplicación para que el lector pueda realizar las
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 419
pruebas que requiera.
Una vez insertado un PictureBox en el formulario, asignaremos a su propiedad Dock el
valor Fill; de esta forma el control ocupará por completo la superficie del formulario.
A continuación asignaremos el fichero con la imagen a la propiedad Image, y por último,
tenemos que establecer la propiedad SizeMode al valor StretchImage. Esto será todo,
por lo que si ejecutamos el programa, la imagen quedará en todo momento ajustada al
formulario al igual que en el anterior caso. Ver Figura
. Imagen de fondo del formulario empleando un PictureBox.
Manipulando el grado de opacidad del formulario
La propiedad Opacity de la clase Form, contiene un valor numérico de tipo Double
que permite establecer el grado de opacidad del formulario. Cuando esta propiedad
contenga el valor 1, el formulario se mostrará en la forma habitual; pero si el valor es
0, el formulario será transparente.
Podemos asignar valores intermedios de modo que hagamos parcialmente transparente
el formulario, mostrando los elementos que quedan bajo el mismo. Debemos tener en
cuenta que cuando asignemos este valor mediante la ventana de propiedades del
formulario en modo de diseño, el número asignado será el porcentaje de opacidad. La
Figura muestra la ventana de propiedades para este caso con un setenta y cinco por ciento
de opacidad para el formulario.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 420
Propiedad Opacity establecida desde la ventana de propiedades del IDE.
La Figura muestra este formulario con el anterior porcentaje de opacidad.
Formulario parcialmente transparente debido a la propiedad Opacity.
El Código fuente establece por código la opacidad del formulario a un grado del cuarenta
y cinco por ciento, en el evento DoubleClick del formulario.
Private Sub Form1_DoubleClick(ByVal sender As Object, ByVal e As [Link])
Handles [Link]
[Link] = 4.5
End Sub
El proyecto Opacidad contiene un control TrackBar, que con el estilo de un control de
volumen, nos va a permitir graduar el nivel de opacidad del formulario.
Mediante las propiedades Maximum y Minimum establecemos el rango de opacidad
respectivamente a diez y cero.
En la propiedad Value asignaremos el valor 10, para partir de la máxima opacidad e ir
disminuyendo. Como efectos visuales de este control, las propiedades Orientation y
TickStyle nos permiten establecer la orientación del indicador de posición y su apariencia.
Finalmente, el evento Scroll se producirá cada vez que movamos el indicador de
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 421
posición en el control, ejecutando el código de su procedimiento manipulador, que vemos
en el Código fuente
Private Sub tkbOpaco_Scroll(ByVal sender As Object, ByVal e As [Link])
Handles [Link]
' cada vez que se mueve el desplazador del TrackBar se modifica la opacidad
Select Case [Link]
Case 0
[Link] = 0
Case 10
[Link] = 1
Case Else
[Link] = "0," & [Link]
End Select
End Sub
La Figura muestra este ejemplo en ejecución.
Esta útil característica de los formularios nos permite, por ejemplo, proporcionar un
efecto de fundido durante su proceso de cierre. Para conseguirlo, escribiremos el
manipulador para el evento Closing del formulario, que es producido cuando el formulario
está a punto de cerrarse; en dicho procedimiento de evento, cancelaremos en ese
momento el cierre del formulario, crearemos un temporizador que conectaremos
con un manipulador del evento Tick, y lo pondremos en marcha.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 422
Utilizando un TrackBar para graduar la opacidad de un formulario.
En el procedimiento del evento Tick, crearemos el efecto de fundido, disminuyendo
el grado de opacidad del formulario hasta hacerlo invisible, punto en el que cerraremos
el formulario. Esto hará que se vuelva a pasar por el evento Closing, pero en esta
ocasión, como la opacidad del formulario estará a cero, no se volverá a realizar el
proceso de fundido. Todo esto lo vemos en el Código fuente
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
Dim oTiempo As Timer
' el formulario debe tener el valor 1 en Opacity para conseguir el efecto
If [Link] <> 0 Then
' cancelamos el cierre del formulario
[Link] = True
' iniciamos un temporizador cada medio segundo
oTiempo = New Timer()
[Link] = 500
' conectamos el temporizador con un manipulador de su evento Tick
AddHandler [Link], AddressOf TickTiempo
[Link]()
End If
End Sub
Private Sub TickTiempo(ByVal sender As Object, ByVal e As EventArgs)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 423
' este manipulador del evento del temporizador, cada medio segundo irá
' disminuyendo el grado de opacidad del formulario hasta hacerlo invisible
Static dbContador As Double = 1
dbContador -= 0.1
[Link] = dbContador
' cuando el formulario es invisible
If [Link] = 0 Then
' parar el temporizador
CType(sender, Timer).Stop()
' cerrar el formulario
[Link]()
End If
End Sub
Modificación de la forma del formulario
Las capacidades gráficas del GDI+ nos permiten dotar a los formularios de efectos hasta la
fecha muy difíciles de conseguir, si no se conocía en profundidad el API de Windows.
Aspectos como la transparencia del formulario tratada en el apartado anterior, o el cambio
en la forma estándar del formulario, que veremos seguidamente.
Para cambiar el aspecto rectangular de un formulario debemos, en primer lugar, importar
en nuestro programa, el espacio de nombres [Link].Drawing2D.
A continuación crearemos un objeto de la clase GraphicsPath, que representa un conjunto
de líneas y curvas conectadas. A este objeto le añadiremos una forma mediante alguno de
sus métodos AddXXX( ).
Finalmente, crearemos un objeto de tipo Region, al que pasaremos el objeto
GraphicsPath con la forma creada previamente. Esto creará una región con dicha forma,
que asignaremos a la propiedad Region del formulario, consiguiendo de esta manera,
modificar el aspecto del formulario en cuanto a su forma.
El proyecto FormasForm muestra un formulario con dos botones que cambian la forma del
formulario a un círculo y triángulo al ser pulsados. El Código fuente muestra los eventos
Click de ambos botones.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 424
Imports [Link].Drawing2D
'....
'....
Private Sub Circulo_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' crear un objeto gráfico para conectar líneas y curvas
Dim oGPath As GraphicsPath = New GraphicsPath()
' añadir un círculo al objeto gráfico
[Link](New Rectangle(0, 0, 200, 260))
' crear una región con el objeto gráfico y asignarla a la región del formulario
[Link] = New Region(oGPath)
End Sub
Private Sub btnPoligono_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' mostrar el formulario con el aspecto de un triángulo
Dim oPuntos(2) As Point
oPuntos(0) = New Point(-20, -20)
oPuntos(1) = New Point(-20, 200)
oPuntos(2) = New Point(220, 90)
Dim oGPath As GraphicsPath = New GraphicsPath()
[Link](oPuntos)
[Link] = New Region(oGPath)
End Sub
La Figura muestra el formulario con forma de elipse.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 425
Formulario con forma de elipse.
La Figura muestra el formulario con forma de triángulo.
Formulario con forma triangular.
Integrando elementos. Un visualizador de gráficos
Para finalizar con el presente tema, vamos a realizar, a modo de práctica, una aplicación que
contendrá un formulario para visualizar archivos de imagen. De esta forma practicaremos
con algunos de los puntos ya tratados, y nos servirá para presentar dos nuevos controles:
TreeView y ListView.
para acceder a este ejemplo), y consiste en crear un formulario con un ComboBox que
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 426
permita, en primer lugar, seleccionar una unidad lógica del equipo. Una vez hecho esto,
se llenará el TreeView con la lista de directorios de la unidad elegida. Al seleccionar un
directorio del TreeView, se rellenará el ListView con una lista de ficheros de tipo gráfico,
de los que al seleccionar uno, se cargará su contenido en un PictureBox; al realizar dicha
carga, podremos optar por ajustar la imagen a las dimensiones del PictureBox o bien
mantener el tamaño original de la imagen. Debido a que algunos de estos controles
necesitan de imágenes asociadas como iconos, utilizaremos también un control
ImageList para almacenar estos iconos.
El control TreeView muestra una lista de elementos dispuestos en forma de árbol o nodos
expandibles.
La propiedad Nodes es una colección que contiene los nodos del control, que en
este caso rellenaremos desde el código del programa. Las propiedades ImageIndex y
SelectedImageIndex muestran respectivamente una de las imágenes del control ImageList
asociado, con el icono indicativo de si un nodo se encuentra o no seleccionado.
Por otro lado, el control ListView consiste en un ListBox al que podemos asociar una
imagen para cada elemento o item que muestra en la lista.
Para poder mostrar los elementos de un ListView de esta forma estableceremos la
propiedad View al valor Details; crearemos una columna en su propiedad Columns, y
asociaremos el control ImageList a las propiedades Large/Small/StateImageList. También
es conveniente que la propiedad MultiSelect esté a False para poder seleccionar sólo
un elemento en cada ocasión. El llenado de este control también lo haremos desde el
código de la aplicación. La Figura muestra el formulario de este proyecto una vez
completada su fase de diseño.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 427
Formulario del visualizador de gráficos.
Pasando al código de la clase del formulario, debido a que vamos a trabajar con objetos
que manipulan directorio y ficheros, importaremos en la cabecera del fichero de
código el espacio de nombres [Link]. En el evento Load del formulario, cargaremos
el ComboBox con las unidades lógicas detectadas por el sistema, empleando el
objeto Environment del sistema, y su método GetLogicalDrives( ). Ver Código
fuente
Imports [Link]
Public Class Form1
Inherits [Link]
Private Sub Form1_Load(ByVal sender As Object, ByVal e As [Link])
Handles [Link]
' al cargar el formulario llenar
' el combo con las letras de unidad
Dim sUnidades() As String
sUnidades = [Link]()
[Link](sUnidades)
End Sub
'....
Al seleccionar un elemento en el ComboBox, se produce su evento
SelectedIndexChanged, en el que nos ocupamos de obtener los directorios raíz de
la unidad lógica seleccionada, y con dicha información, rellenar el TreeView. Ver
Código fuente 553.
Private Sub cboUnidades_SelectedIndexChanged(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
' este evento se dispara cuando se cambia
' el elemento seleccionado del combo
' obtener los directorios raíz de la unidad seleccionada
Dim oDirUnidadSelec As New DirectoryInfo([Link])
Dim sDirectorios() As DirectoryInfo
sDirectorios = [Link]()
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 428
' vaciar el treeview
[Link]()
' dibujar cada nombre de directorio raíz en el treeview
Dim oDirInfo As DirectoryInfo
Dim oNodo As TreeNode
For Each oDirInfo In sDirectorios
oNodo = New TreeNode([Link], 0, 1)
[Link](oNodo)
Next
End Sub
El siguiente paso lógico es la selección de un directorio en el TreeView. Cuando esto
suceda, se provocará el evento AfterSelect de dicho control; en él comprobaremos si existen
directorios anidados al seleccionado, y al mismo tiempo, llenaremos el ListView con los
nombres de ficheros del directorio seleccionado, asociando a cada elemento de la lista, una
imagen del control ImageList por el número de orden que ocupa la imagen en la lista. Ver
Código fuente
Private Sub tvDirectorios_AfterSelect(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
' si el nodo pulsado no está expandido...
If Not [Link] Then
' comprobar si tiene subdirectorios
Dim oSubDirInfo As DirectoryInfo
oSubDirInfo = New DirectoryInfo([Link])
' obtener subdirectorios del directorio seleccionado
Dim oSubDirectorios() As DirectoryInfo
oSubDirectorios = [Link]()
' crear nodos para cada subdirectorio en el treeview
Dim oSubDirI As DirectoryInfo
Dim oNodo As TreeNode
For Each oSubDirI In oSubDirectorios
oNodo = New TreeNode([Link], 0, 1)
[Link]([Link])
Next
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 429
' obtener los archivos del subdirectorio
Dim oArchivos() As FileInfo
oArchivos = [Link]()
' limpiar el listview
[Link]()
' rellenar el listview con los nombres de archivo
' que tengan tipo gráfico
Dim oArchInfo As FileInfo
For Each oArchInfo In oArchivos
Select Case [Link]()
Case ".BMP", ".PNG", ".WMF"
[Link]([Link], 3)
Case ".JPG", ".JPEG"
[Link]([Link], 4)
Case ".GIF"
[Link]([Link], 5)
End Select
Next
End If
End Sub
Finalmente, ya sólo queda comprobar cuándo se pulsa en uno de los ficheros de imagen
del ListView, cosa que haremos con su evento SelectedIndexChanged. Al producirse esta
situación, lo que haremos será invalidar el área de dibujo del PictureBox, forzando a
que se desencadene su evento Paint, en donde realmente realizaremos la carga de la
imagen. A pesar de todo, en el Código fuente también se acompaña el código para
hacer una carga directa de la imagen en el evento sobre el que nos encontramos.
Private Sub lstFicheros_SelectedIndexChanged(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
If [Link] > 0 Then
' CARGA MANUAL EN PICTUREBOX:
' si invalidamos la región gráfica del picturebox
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 430
' obligamos a que se produzca su evento Paint,
' y en ese evento escribimos el código que carga
' la imagen en el control
[Link]()
' CARGA AUTOMÁTICA DE IMAGEN:
' escribimos en este evento el código para
' asignar una imagen al picturebox
'[Link] = New Bitmap( _
' [Link] & "\" & _
' [Link](0).Text)
End If
End Sub
En el evento Paint del PictureBox, mostramos la imagen seleccionada, ajustada al tamaño
del control o con su propio tamaño, según el RadioButton seleccionado del formulario.
Adicionalmente, para el caso en el que se redimensione el formulario, también
invalidamos el PictureBox, de manera que la imagen que actualmente se esté mostrando
será recargada. Veámoslo en el Código fuente
Private Sub picImagen_Paint(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
' si el nodo seleccionado tiene contenido
If Not (IsNothing([Link])) Then
' crear imagen a partir del fichero seleccionado
Dim oBitmap As New Bitmap( _
[Link] & _
"\" & [Link](0).Text)
' obtener dispositivo gráfico del picturebox
Dim oGraf As Graphics = [Link]
If [Link] Then
' dibujar imagen ajustada al picturebox
[Link](oBitmap, 0, 0, _
[Link], [Link])
Else
' dibujar imagen con su tamaño original
[Link](oBitmap, 0, 0, _
[Link], [Link])
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 431
End If
End If
End Sub
Private Sub picImagen_Resize(ByVal sender As Object, ByVal e As [Link])
Handles [Link]
' al redimensionar, invalidar área gráfica del picturebox
[Link]()
End Sub
Terminada la escritura de código del programa, sólo queda ejecutarlo para comprobar su
resultado, como muestra la Figura
Visualizador de gráficos en ejecución.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 432
12.- Operaciones de entrada y salida (I/O).Gestión del
sistema de archivos
La remodelación del viejo esquema de entrada y salida
Desde las primeras versiones del lenguaje, el programador de Visual Basic ha
dispuesto de un conjunto de instrucciones y funciones para el manejo de las
operaciones de lectura/escritura con archivos, y la gestión de los mismos dentro del
sistema operativo, en cuanto a su creación, borrado copia, etc., entre directorios y
unidades.
Si bien este modo de trabajo ha sido válido durante mucho tiempo, la incorporación de
las técnicas
OOP a los lenguajes de programación, hacían necesario una renovación en este aspecto
de VB.
Las instrucciones Open, Input, Write, Put, etc., a pesar de resolver su cometido, no
proporcionan un entorno de trabajo cómodo, en un mundo en el que cada vez prima más
el trabajo con objetos.
La jerarquía de objetos FileSystemObject, introducida recientemente, vino a paliar
en parte esta carencia, aportando un conjunto de clases que ya nos permitían, desde
un prisma orienta a objeto, trabajar con todos los aspectos del sistema de archivos, en
cuanto a su lectura, escritura, manejo de directorios, unidades, etc. La evolución de este
conjunto de objetos se halla en la plataforma .NET.
[Link], el punto de partida
Con la llegada de la tecnología .NET, el acceso al sistema de archivos, es un aspecto que
ya no forma parte de un lenguaje determinado, como ocurría en las anteriores versiones
de VB, sino que ha sido integrado dentro de la jerarquía de clases de la plataforma, en
el espacio de nombres IO de System.
Con ello, todos los lenguajes compatibles con .NET podrán utilizar este conjunto de
objetos.
Las clases incluidas en [Link], nos van a permitir realizar labores de lectura y escritura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 433
en archivos de texto, binarios, etc., así como la creación y manipulación de los
archivos y directorios que contienen la información.
A lo largo de este tema realizaremos una descripción, y ejemplos de uso, de algunas
de las clases contenidas en IO. Por lo que, en todos los ejemplos utilizados aquí,
tendremos que importar este espacio de nombres.
Objetos Stream
Un objeto Stream representa un flujo o corriente de datos, es decir, un conjunto de
información guardada en formato de texto o binario, que podremos leer y escribir sobre
un soporte físico, también denominado en la plataforma .NET, almacén de respaldo
(backing store).
Algunos tipos de Stream, para optimizar el flujo de transferencia de datos entre el objeto
y su medio físico de almacenamiento, disponen de una característica denominada
almacenamiento intermedio (buffering), que consiste en mantener un búfer intermedio
con los datos. En el caso, por ejemplo, de tareas de escritura, todas las operaciones
se realizarían en el búfer, mientras este dispusiera de capacidad. Una vez terminado
el proceso de escritura, o cuando el búfer estuviera lleno, su contenido pasaría al archivo
físico. Podemos también, alterar el comportamiento por defecto del búfer a través de
diversas propiedades y métodos del objeto Stream correspondiente.
Las clases TextReader y TextWriter
Estas clases contienen los miembros genéricos para realizar lectura y escritura de
caracteres.
Se trata de clases abstractas, por lo que deberemos utilizar las clases derivadas
StreamReader, StreamWriter, StringReader y StringWriter, comentadas a continuación.
La clase StreamWriter
Un objeto StreamWriter realiza operaciones de escritura de texto sobre un archivo.
El proceso típico de escritura de datos mediante un StreamWriter, comprende los
siguientes pasos:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 434
Instanciar un objeto de esta clase mediante alguno de los constructores
disponibles. Aquí creamos un nuevo archivo para escribir datos sobre él, o abrimos
uno existente.
Escritura de texto mediante los métodos WriteLine( ) y Write( ). El primero
escribe el texto pasado como parámetro, y añade los caracteres especiales de
retorno de carro y nueva línea. El segundo escribe el texto pasado y deja el
puntero de escritura a partir del último carácter escrito, con lo que no produce
un cambio automático de línea. Deberemos utilizar la propiedad NewLine para
introducir manualmente un salto de línea.
Cierre del Stream con el método Close( ). Esta acción vuelca el contenido del
búfer del objeto en el archivo.
El Código fuente muestra el proceso básico que acabamos de describir.
Imports [Link]
Module Module1
Sub Main()
Dim swEscritor As StreamWriter
' creamos un stream de escritura, y al mismo tiempo un
' nuevo archivo para escribir texto sobre él
swEscritor = New StreamWriter("\pruebas\[Link]")
' escribir líneas
[Link]("esta es la primera línea")
[Link]("segunda línea de texto")
' ahora escribimos texto pero sin provocar un salto de línea
[Link]("Juan y Luna ")
[Link]("van de paseo")
[Link]([Link]) ' esto introduce el salto de línea
[Link]("con esta línea cerramos")
' cerrar el stream y el archivo asociado
[Link]()
End Sub
End Module
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 435
Algunas de las clases de tipo Stream de escritura disponen del campo compartido Null,
que permite realizar una operación de escritura que no será volcada en el medio físico
de almacenamiento, con lo que se perderán los datos escritos. Ver el Código fuente.
' escribir a un medio inexistente (nulo)
[Link]("este texto no llegará al archivo")
En el caso de que el archivo sobre el que vamos a escribir ya exista, podemos utilizar
un constructor de StreamWriter que nos permite especificar si vamos a añadir texto al
archivo o vamos a sobrescribir, perdiendo el texto que hubiera. Veamos un ejemplo en el
Código fuente
' abre el archivo y se sitúa al final del texto para añadir
swEscritor = New StreamWriter("\pruebas\[Link]", True)
' se elimina el contenido previo del archivo
swEscritor = New StreamWriter("\pruebas\[Link]", False)
Después de crear un objeto de este tipo, y escribir algunas líneas de texto sin cerrar
el Stream, si abrimos su archivo de texto correspondiente, nos encontraremos con
que no hay texto dentro del archivo. Ello es debido a que todavía no se ha volcado
el contenido del búfer del objeto sobre el archivo. Para forzar dicho volcado, deberemos
llamar al método Flush( ), que se encarga de traspasar el búfer al archivo asociado al
Stream. Veamos el Código fuente
Dim swEscritor As StreamWriter
' creamos un stream de escritura
swEscritor = New StreamWriter("\pruebas\[Link]", False)
' escribir líneas
[Link]("la primera línea")
[Link]("un poco más de texto")
' si abrimos el archivo antes de la siguiente, estará vacío
[Link]()
' ahora el archivo ya contendrá texto
' cerrar el stream y el archivo asociado
[Link]()
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 436
La clase StreamReader
Un objeto StreamReader realiza operaciones de lectura de texto sobre un archivo.
El proceso que debemos llevar a cabo para leer el contenido de un Stream de lectura es
muy similar al de escritura: instanciar el objeto con uno de sus constructores, abriendo
un archivo para leer; ejecutar alguno de los métodos de lectura del StreamReader, y cerrar
el objeto con Close( ).
Entre los métodos de lectura de este objeto, tenemos ReadLine( ), que devuelve una línea
del archivo; y ReadToEnd( ), que devuelve el resto del contenido del archivo, desde
el punto en el que se encontrara el Stream al realizar la última lectura. Veamos unos
ejemplos en el Código fuente
Dim srLector As StreamReader = New StreamReader("\pruebas\[Link]")
[Link]("**Leer una primera línea**")
Dim Linea As String
Linea = [Link]()
[Link]("La línea contiene --> {0}", Linea)
[Link]()
[Link]("**Ahora leemos el resto del archivo**")
Dim Texto As String
Texto = [Link]()
[Link]("El texto restante contiene --> {0}", Texto)
[Link]()
' ***********************************************
' leer línea a línea mediante un bucle
Dim srLector As StreamReader = New StreamReader("\pruebas\[Link]")
Dim Linea As String
Dim ContadorLin As Integer = 1
Linea = [Link]()
Do While Not (Linea Is Nothing)
[Link]("Línea: {0} - Contenido: {1}", ContadorLin, Linea)
ContadorLin += 1
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 437
Linea = [Link]()
Loop
Otro de los métodos de lectura es ReadBlock( ), que recibe como parámetro un array
de tipo Char, sobre el que se depositarán una cierta cantidad de caracteres leídos
del archivo. En el segundo parámetro de este método indicamos la posición del array
desde la que se comenzarán a guardar los caracteres. En el tercer parámetro, el
número de caracteres a leer.
El método Read( ), también permite realizar una lectura igual que ReadBlock( ), pero en
el caso de no utilizar parámetros, devuelve un valor numérico, correspondiente al código
del carácter que acaba de leer. Cuando llega al final del Stream, devuelve –1.
Para convertir de nuevo a carácter los valores que devuelve Read( ), debemos pasar estos
valores a un array de tipo Byte, y después, utilizando un objeto ASCIIEncoding, mediante
su método GetString( ), pasaríamos el array a una cadena. Veamos unos ejemplos de estos
métodos en el Código fuente
Imports [Link]
Imports [Link]
Module Module1
Sub Main()
' crear un Stream de lectura
Dim srLector As StreamReader = New StreamReader("\pruebas\[Link]")
' obtener valores del Stream con el método ReadBlock()
' ----------------------------------------------------
' crear un array Char que contendrá los caracteres leídos
Dim Caracteres(15) As Char
' leemos 16 caracteres del archivo y los pasamos al array
' comenzando a grabarlos a partir de su posición 0
[Link](Caracteres, 0, 16)
' pasamos el array de valores Char a String mediante
' el constructor de la clase String que recibe como
' parámetro un array Char
Dim Parte1 As String = New String(Caracteres)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 438
[Link]("Resultado de la lectura con ReadBlock()")
[Link](Parte1)
[Link]()
' obtener valores del stream con el método Read()
' -----------------------------------------------
Dim Valor As Integer
Dim Codigos() As Byte
' vamos a ir volcando en un bucle los códigos de carácter
' leidos desde el archivo a un array Byte
Valor = [Link]()
While (Valor <> -1) ' cuando lleguemos al final, obtendremos -1
If Codigos Is Nothing Then
ReDim Codigos(0)
Else
ReDim Preserve Codigos([Link](0) + 1)
End If
Codigos([Link](0)) = Valor
Valor = [Link]()
End While
Dim Codificador As New ASCIIEncoding()
Dim Parte2 As String
' con el objeto ASCIIEncoding, método GetString(),
' obtenemos una cadena, pasando como parámetro un array
' de tipos Byte
Parte2 = [Link](Codigos)
[Link]("Resultado de la lectura con ReadBlock()")
[Link](Parte2)
[Link]()
End Sub
End Module
Finalmente, el método Peek( ), al igual que Read( ), devuelve el siguiente valor disponible
del Stream, pero sin extraerlo del búfer, con lo que deberemos utilizar alguno de los
métodos anteriormente descritos para realizar una lectura real.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 439
Las clases StringWriter y StringReader
Estas clases proporcionan la misma funcionalidad que StreamWriter y StreamReader, con
la diferencia de que StringWriter trabaja con un objeto StringBuilder como almacén
de datos, mientras que StringReader utiliza un String para leer su contenido.
La clase Stream (flujo de datos)
La clase Stream representa un flujo o corriente de datos, es decir, un conjunto
secuencial de bytes, como puede ser un archivo, un dispositivo de entrada/salida,
memoria, un conector TCP/IP, etc.
Se trata de una clase abstracta, por lo que si queremos hacer uso de un stream
concreto, tenemos que acudir a alguna de sus clases derivadas como son FileStream,
MemoryStream, BufferedStream, etc.
La clase FileStream
Realiza escritura y lectura de bytes sobre un archivo; en el caso de que el archivo
no exista, lo crearíamos al mismo tiempo que instanciamos este objeto.
Uno de los constructores de esta clase, nos permite especificar una cadena con la ruta
del archivo a utilizar, mientras que en el segundo parámetro utilizaremos un valor de
la enumeración FileMode, mediante la que indicamos el modo de trabajo sobre el archivo:
añadir, abrir, crear, etc.
Las propiedades CanRead, CanWrite y CanSeek, devuelven un valor lógico que nos
informa de si en el objeto podemos realizar operaciones de lectura, escritura y
desplazamiento por los bytes que contiene.
Para escribir datos, disponemos del método WriteByte( ), que escribe un byte en el
archivo; y también tenemos el método Write( ), que escribe de un array de bytes pasado
como parámetro, una cantidad de elementos determinada empezando por una de las
posiciones de dicho array. Veamos un ejemplo de escritura en el Código fuente 416.
' escrituras con Filestream
Dim oFileStream As FileStream
oFileStream = New FileStream("\pruebas\[Link]", [Link])
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 440
[Link](New Byte() {15, 160, 88, 40, 67, 24, 37, 50, 21}, 0, 6)
[Link](75)
[Link]("Opciones en el FileStream")
[Link]("Podemos leer: {0}", IIf([Link], "SI", "NO"))
[Link]("Podemos escribir: {0}", IIf([Link], "SI", "NO"))
[Link]("Podemos movernos: {0}", IIf([Link], "SI", "NO"))
[Link]()
oFileStream = Nothing
Para las operaciones de lectura, tenemos ReadByte( ), que devuelve el valor sobre
el que esté posicionado el objeto en ese momento. También disponemos del método
Read( ), que traspasa valores un array de bytes.
Si queremos desplazarnos por los elementos del Stream, podemos utilizar el método
Seek( ), pasando la cantidad de posiciones a movernos, y el punto desde el que
queremos realizar dicho desplazamiento, mediante los valores de la enumeración
SeekOrigin.
Para averiguar el elemento del Stream en el que estamos situados, disponemos de
la propiedad Position. Veamos algunos ejemplos de lectura sobre este tipo de objetos,
en el Código fuente
' lectura con FileStream
Dim oFileStream As FileStream
oFileStream = New FileStream("\pruebas\[Link]", [Link])
Dim Valor As Byte
Valor = [Link]() ' obtener un valor
[Link]("Se ha leido el valor: {0}", Valor)
[Link]("Nos desplazamos dos bytes en el stream")
[Link](2, [Link])
Valor = [Link]()
[Link]("Se ha leido el valor: {0}", Valor)
[Link]("La posición actual del stream es: {0}", _
[Link])
' leer varios valores, pasándolos a un array previamente dimensionado
Dim VariosValores(3) As Byte
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 441
[Link](VariosValores, 0, 4)
[Link]("Leer bloque de valores del stream")
Dim Enumerador As IEnumerator
Enumerador = [Link]()
While [Link]
[Link]("Valor: {0}", [Link])
End While
Las clases BufferedStream y MemoryStream, que también heredan de Stream, disponen
de los mismos miembros que FileStream, teniendo como principal diferencia el que
utilizan la memoria de la máquina como almacén de respaldo.
Manejo de datos binarios
Las clases BinaryWriter y BinaryReader, tal y como podemos anticipar por sus nombres,
nos permiten escribir y leer respectivamente, datos binarios en archivos, utilizando los
métodos ya vistos en clases anteriores. Veamos un ejemplo en el Código fuente
' escritura binaria
Dim oBin As New BinaryWriter(New FileStream("\pruebas\[Link]",
[Link]))
[Link]("H"c)
[Link]("D"c)
[Link]("U"c)
[Link]()
oBin = Nothing
' lectura binaria
Dim oBinLector As BinaryReader
oBinLector = New BinaryReader(New FileStream("\pruebas\[Link]", [Link]))
[Link]("Valor 1 del lector: {0}", [Link]())
[Link]("Valor 2 del lector: {0}", [Link]())
[Link]("Valor 3 del lector: {0}", [Link]())
[Link]()
[Link]()
Manipulación de archivos mediante File y FileInfo
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 442
Las clases File y FileInfo, proporcionan a través de sus miembros, el conjunto de
operaciones comunes que podemos realizar con archivos en cuanto a su creación, copia,
borrado, etc.
La diferencia principal entre ambas radica en que los miembros de File son todos
compartidos, con lo cual se facilita en gran medida su uso, al no tener que crear una
instancia previa de la clase; mientras que en FileInfo deberemos crear un objeto para
poder utilizarla, ya que sus miembros son de instancia. FileInfo dispone de algunos
métodos adicionales que no se encuentran en File.
Comenzando por la clase File, los métodos CreateText( ) y OpenText( ), devuelven
respectivamente un objeto StreamWriter y StreamReader, que utilizaremos para
escribir y leer en el archivo pasado como parámetro a estos métodos. Con el método
Exists( ), comprobamos si existe un determinado
archivo. Veamos un ejemplo en el Código fuente
Dim sNombreFich As String
Dim srLector As StreamReader
Dim swEscritor As StreamWriter
[Link]("Introducir ruta y archivo")
sNombreFich = [Link]()
If [Link](sNombreFich) Then
srLector = [Link](sNombreFich)
[Link]("El archivo contiene:{0}{1}", _
[Link], [Link]())
[Link]()
Else
swEscritor = [Link](sNombreFich)
[Link]("este es")
[Link]("un nuevo archivo")
[Link]()
End If
MsgBox("Proceso finalizado")
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 443
[Link]()
Para obtener los atributos de un archivo, disponemos del método GetAttributes( ), al
que pasamos la ruta de un archivo, y devuelve un valor de la enumeración FileAttributes
con la información sobre los atributos. En el caso de que al intentar acceder a un archivo,
este no exista, se producirá una excepción de tipo FileNotFoundException, que podemos
tratar en una estructura de manejo de excepciones. Ver el Código
Dim sNombreFich As String
Dim oAtributos As FileAttributes
Try
[Link]("Introducir ruta y archivo")
sNombreFich = [Link]()
oAtributos = [Link](sNombreFich)
[Link]("Atributos del archivo: {0}", [Link]())
Catch oExcep As FileNotFoundException
[Link]("Se ha producido un error {0}{1}", _
[Link], [Link])
Finally
[Link]("Proceso finalizado")
[Link]()
End Try
Además de esta excepción, el espacio de nombres IO proporciona algunas clases de
excepción adicionales para tratar otras diversas circunstancias de error. Consulte el lector
la documentación de la plataforma referente a IO.
Los métodos Copy( ), Move( ) y Delete( ), nos permiten copiar, mover y borrar
respectivamente el nombre de archivo que pasemos como parámetro. El método
GetCreationTime( ) nos devuelve un tipo Date con la fecha de creación del archivo.
Por otro lado, si queremos obtener información adicional sobre un archivo, como
su nombre, extensión, ruta, etc., instanciaremos un objeto FileInfo( ), pasando al
constructor una cadena con el nombre del archivo, y utilizaremos algunas de sus
propiedades como Name, Extensión, DirectoryName. Veamos una muestra de todo
esto en el Código fuente 421.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 444
Dim sNombreFich As String
Dim iOperacion As Integer
Dim oFInfo As FileInfo
[Link]("Introducir ruta y archivo")
sNombreFich = [Link]()
[Link]("Fecha creación archivo: {0}", _
[Link](sNombreFich))
oFInfo = New FileInfo(sNombreFich)
[Link]("Introducir el número de operación a realizar:")
[Link]("1 - Copiar")
[Link]("2 - Mover")
[Link]("3 - Borrar")
iOperacion = [Link]()
Select Case iOperacion
Case 1
[Link](sNombreFich, "\pruebas\distinto" & [Link])
Case 2
[Link]("Vamos a mover el archivo {0}", [Link])
[Link]("que está en la ruta {0}", [Link])
[Link](sNombreFich, "\pruebas\" & [Link])
[Link]("Completado")
[Link]()
Case 3
[Link](sNombreFich)
End Select
Manipulación de archivos mediante Directory y DirectoryInfo
Las clases Directory y DirectoryInfo contienen métodos y propiedades para crear,
borrar, copiar y mover directorios, así como otra serie de tareas para su manejo y
obtención de información.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 445
Al igual que sucedía con las clases del anterior apartado, los miembros de Directory son
compartidos, mientras que los de DirectoryInfo son de instancia; esta es su principal
diferencia.
En el ejemplo del Código fuente, el método Exists( ) comprueba la existencia de un
directorio, y en caso afirmativo, obtenemos su última fecha de uso mediante
GetLastAccessTime( ). Seguidamente obtenemos un array String con su lista de archivos
mediante GetFiles( ), y creamos un subdirectorio de respaldo con CreateSubdirectory( ).
En caso de que el directorio no exista, lo creamos con CreateDirectory( ).
Dim sNombreDir As String
Dim Archivos() As String
Dim Archivo As String
Dim oDirInfo As DirectoryInfo
[Link]("Introducir un nombre de directorio")
sNombreDir = [Link]()
If [Link](sNombreDir) Then
[Link]("Fecha último acceso: {0}", _
[Link](sNombreDir))
[Link]("Archivos del directorio {0}", sNombreDir)
Archivos = [Link](sNombreDir)
For Each Archivo In Archivos
[Link](Archivo)
Next
Else
oDirInfo = New DirectoryInfo(sNombreDir)
[Link]("bak")
[Link](sNombreDir)
[Link]("No existía el directorio, se acaba de crear")
End If
Para obtener el directorio actual de ejecución, disponemos del método
GetCurrentDirectory( ), mientras que si queremos subir al directorio de nivel superior,
tenemos el método GetParent( ), que devuelve un tipo DirectoryInfo, con el que
podemos, por ejemplo, mostrar su nombre completo mediante la propiedad FullName,
y fecha de creación con CreationTime. Veamos el Código fuente
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 446
Dim sNombreDir As String
Dim oDirInfo As DirectoryInfo
' obtenemos el directorio actual de ejecución
sNombreDir = [Link]()
[Link]("Directorio actual: {0}", sNombreDir)
' obtenemos el directorio padre del actual,
' y mostramos información de dicha directorio
oDirInfo = [Link](sNombreDir)
[Link]("Directorio padre y fecha de creación {0}{1}{2}{3}", _
[Link], [Link], _
[Link], [Link])
En el siguiente ejemplo, el método GetDirectories( ) devuelve un array de cadenas, con los
nombres de los subdirectorios que se encuentran dentro del directorio pasado como
parámetro a este método. A continuación, mediante el método Move( ), cambiamos de
lugar un directorio; con Delete( ) borramos otro de los directorios. Observe el lector,
cómo utilizando de forma combinada CType( ), [Link]( ), y un elemento
del array que contiene la lista de directorios, creamos una expresión que nos permite
averiguar, si en un determinado directorio hay o no archivos. Ver el Código fuente.
Dim sNombreDir As String
Dim oDirInfo As DirectoryInfo
Dim sDirectorios() As String
Dim sDirectorio As String
[Link]("Introducir un nombre de directorio")
sNombreDir = [Link]()
' obtener directorios del directorio especificado
sDirectorios = [Link](sNombreDir)
' comprobar que el directorio contiene a su vez
' varios directorios; en caso negativo, finalizar
If Not ([Link] > 1) Then
[Link]("El directorio especificado debe contener al menos dos
subdirectorios")
[Link]()
Exit Sub
End If
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 447
' mostrar nombres de directorios
For Each sDirectorio In sDirectorios
[Link](sDirectorio)
Next
' mover uno de los directorios a otra ubicación del disco actual
[Link](sDirectorios(0), "\temp\BIS")
' borrar otro de los directorios;
' el directorio a borrar debe estar vacío;
' comprobar con la siguiente expresión si dicho
' directorio contiene o no archivos
If (CType([Link](sDirectorios(1)), String()).Length() > 0) Then
[Link]("No se puede borrar el directorio: {0} - " & _
"contiene archivos", sDirectorios(1))
Else
[Link](sDirectorios(1))
End If
[Link]("Completado")
[Link]()
La clase Path
Esta clase nos proporciona un conjunto de campos y métodos compartidos, para la
obtención de información y manipulación de rutas de archivos. El Código fuente muestra
un ejemplo en el que, una vez introducido un directorio, se muestra la información de
cada uno de sus archivos, en lo que respecta a los métodos de esta clase.
[Link]("Introducir nombre de directorio")
Dim sDirectorio As String
sDirectorio = [Link]()
Dim sArchivos() As String
sArchivos = [Link](sDirectorio)
[Link]("Datos sobre archivos obtenidos del objeto Path")
[Link]("===========================================")
Dim sArchivo As String
For Each sArchivo In sArchivos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 448
[Link]("GetDirectoryName() {0}", [Link](sArchivo))
[Link]("GetExtension() {0}", [Link](sArchivo))
[Link]("GetFileName() {0}", [Link](sArchivo))
[Link]("GetFileNameWithoutExtension() {0}",
[Link](sArchivo))
[Link]("GetFullPath() {0}", [Link](sArchivo))
[Link]()
Next
[Link]()
Monitorización del sistema de archivos con FileSystemWatcher
Esta clase contiene los mecanismos necesarios, que nos van a permitir la creación de
objetos que actúen como observadores de los sucesos que ocurran en el sistema de
archivos de un equipo local o remoto en cuanto a la creación, borrado, modificación, etc.,
de archivos y directorios.
La creación de este proceso de vigilancia podemos dividirla en dos partes:
instanciación y configuración del propio objeto FileSystemWatcher; y la escritura
de los procedimientos manipuladores de los diversos eventos que pueden ocurrir sobre
los archivos y directorios.
Para facilitar la escritura de los manipuladores de evento, podemos declarar una variable
de esta clase a nivel de módulo, con la palabra clave WithEvents. Ver Código fuente
Module Module1
Private WithEvents oFSW As FileSystemWatcher
Sub Main()
'....
'....
Declarado el objeto FileSystemWatcher, lo instanciaremos y asignaremos valor a las
propiedades mencionadas a continuación, que nos permitirán configurar el modo de
observación que realizará este objeto sobre los archivos.
Path. Tipo String. Contiene la ruta de la unidad de disco sobre la que se
efectuará la monitorización.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 449
Filter. Tipo String. Contiene el tipo de fichero que se va a observar, admitiendo
los caracteres comodín; por ejemplo: “*.*”, “*.txt”.
IncludeSubdirectories. Tipo Boolean. Establece si se van a monitorizar los
subdirectorios de la ruta especificada en la propiedad Path. El valor True incluye los
subdirectorio, mientras que False no los incluye.
EnableRaisingEvents. Tipo Boolean. Activa el proceso de observación sobre el
sistema de archivos, teniendo en cuenta la configuración establecida en
las demás propiedades mencionadas arriba. El valor True pone en marcha el
mecanismo de observación, mientras que el valor False lo detiene.
Veamos un ejemplo de estas propiedades en el Código fuente
Sub Main()
' instanciar objeto FileSystemWatcher
oFSW = New FileSystemWatcher()
' configurar objeto
[Link] = "C:\pruebas"
[Link] = "*.txt"
[Link] = True
' activar
[Link] = True
' mientras que no pulsemos S, el objeto inspeccionará
' el sistema de archivos del equipo
While ([Link]() <> "S")
End While
End Sub
Para completar este proceso que estamos describiendo, sólo nos queda escribir los
procedimientos que van a ejecutarse cuando se realice la creación, borrado,
modificación, etc., de un archivo.
Puesto que hemos declarado la variable FileSystemWatcher a nivel del módulo
de código, seleccionaremos dicha variable en la lista desplegable Nombre de clase,
del editor de código. Seguidamente, abriremos la lista Nombre de método, también
del editor; seleccionando el evento a codificar.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 450
Las anteriores acciones, crearán el procedimiento de evento correspondiente, pero
vacío, por lo que tendremos que escribir el código que queramos ejecutar en
respuesta a tal evento. La lista de parámetros de este procedimiento consiste en un
tipo Object, que contiene la referencia al objeto FileSystemWatcher que originó el
evento; y un tipo FileSystemEventArgs, que contiene información adicional sobre el
evento ocurrido, como el nombre y ruta del archivo.
El Código fuente muestra los procedimientos de evento que se ejecutarán cuando se
cree o borre un archivo.
' al crear un fichero se ejecutará este procedimiento de evento
Public Sub oFSW_Created(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
[Link]("Se ha creado un archivo : {0}", [Link])
End Sub
' al borrar un fichero se ejecutará este procedimiento de evento
Public Sub oFSW_Deleted(ByVal sender As Object, ByVal e As
[Link]) Handles [Link]
[Link]("Se ha producido el borrado: {0}", [Link])
End Sub
Ajuste preciso de filtros para el monitor de archivos
Si queremos realizar un filtro más puntual, por ejemplo, cuando hagamos cambios sobre
los archivos a monitorizar, la clase FileSystemWatcher dispone de la propiedad
NotifyFilter, que contiene una enumeración de tipo NotifyFilters, cuyos valores
podemos combinar para que sólo se detecten los cambios al modificar el tamaño y/o
la última escritura sobre un archivo. La Figura muestra un ejemplo del uso de esta
propiedad.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 451
Uso de filtros de notificación para un objeto FileSystemWatcher.
Establecer el procedimiento de evento con AddHandler
Además de crear los procedimientos de evento de la forma descrita en apartados
anteriores, podemos emplear una técnica más flexible, que nos permite conectar
los eventos del objeto con sus manipuladores, utilizando la palabra clave AddHandler.
El Código fuente muestra un ejemplo de esta situación.
Sub Main()
' instanciar objeto FileSystemWatcher
Dim oFSW As New FileSystemWatcher()
' configurar objeto
[Link] = "C:\pruebas"
[Link] = "*.txt"
[Link] = True
' conectamos manualmente los eventos del objeto
' con los procedimientos manipuladores de esos eventos
AddHandler AddressO oFSW_Created
[Link],
AddHandler f
AddressO CambioProducido
[Link], f
' activar
[Link] = True
' mientras que no pulsemos S, el objeto inspeccionará
' el sistema de archivos del equipo
While ([Link]() <> "S")
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 452
End While
End Sub
Public Sub oFSW_Created(ByVal sender As Object, ByVal e As
[Link])
[Link]("Se ha creado un archivo: {0}", [Link])
End Sub
Public Sub CambioProducido(ByVal emisor As Object, ByVal argumentos As
FileSystemEventArgs)
[Link]("Se ha cambiado el archivo: {0}", [Link])
End Sub
Observe el lector, que para el nombre del procedimiento manipulador de evento,
podemos emplear tanto el formato que utiliza el editor de código, como otro nombre
cualquiera.
Para el evento de creación de archivo hemos utilizado el formato que usa también el
editor, consistente en poner el nombre de objeto, guión bajo, y nombre de evento:
oFSW_Created( ).
Sin embargo para el evento de modificación de archivo hemos utilizado un nombre que
no se ajusta en absoluto al formato del editor: CambioProducido( ).
Consideraciones sobre la ruta de archivos
El modo en que asignemos a la propiedad Path del objeto FileSystemWatcher, la cadena
con la ruta a inspeccionar, influirá en el modo en que recuperemos la información del
evento en el procedimiento manipulador correspondiente.
Si asignamos a Path la ruta, sin especificar la unidad de disco, al intentar utilizar la
propiedad FullName del objeto FileSystemEventArgs, en el procedimiento de evento, se
producirá un error. Ver el Código fuente
Sub Main()
'....
[Link] = "\pruebas"
'....
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 453
End Sub
Public Sub oFSW_Created(ByVal sender As Object, ByVal e As
[Link])
' al intentar utilizar la propiedad FullPath ocurrirá un error
[Link]("Se ha creado un archivo: {0}", [Link])
End Sub
Para que en el anterior ejemplo no se produzca un error, debemos indicar también la
letra de unidad correspondiente al asignar la ruta a Path. Ver Código fuente
[Link] = "C:\pruebas"
Detección con espera, de eventos producidos sobre archivos
El método WaitForChanged( ) de la clase FileSystemWatcher, devuelve un objeto
de tipo WaitForChangedResult, el cual efectúa una parada en la ejecución, quedando a
la espera de que ocurra un determinado evento sobre el sistema de archivos. Una vez
que dicho evento se produzca, se continuará la ejecución del programa.
El tipo de evento que ponemos a la espera, lo definimos pasando como parámetro
al método WaitForChanged( ), un valor de la enumeración WatcherChangeTypes.
Veamos un ejemplo en el Código fuente
Dim oFSW As New FileSystemWatcher()
'....
' crear un objeto de espera para un evento
Dim oWFCR As WaitForChangedResult
oWFCR = [Link]([Link])
[Link]("Se ha creado el archivo: {0}", [Link])
'....
Manipulación de archivos mediante funciones específicas de Visual Basic
Como comentábamos al comienzo de este tema, en anteriores versiones de VB, el
programador tenía a su disposición un grupo de instrucciones como Open, Input, Write,
etc., para la lectura y escritura de información en archivos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 454
Por cuestiones de compatibilidad y migración de aplicaciones existentes, estas
instrucciones han sido transformadas en funciones, para facilitar su manejo.
Funciones como FileOpen( ), para abrir un archivo; FileClose( ), para cerrarlo; LineInput(
), para leer una línea de texto de un archivo, etc, son las que permiten en la actual versión
del lenguaje, realizar las operaciones que anteriormente efectuábamos mediante sus
correspondientes instrucciones.
El Código fuente muestra un pequeño ejemplo, en el que se abre un fichero de texto y
se lee su contenido utilizando algunas de estas funciones. Consulte el lector, la
documentación de la plataforma, para una mayor información.
Dim iNumArchivo As Integer
' obtener número de manipulador de archivo libre
iNumArchivo = FreeFile()
' abrir archivo para lectura
FileOpen(iNumArchivo, "\cubo\[Link]", [Link])
Dim sLinea As String
' recorrer archivo hasta el final
While Not EOF(iNumArchivo)
' leer una línea del archivo
sLinea = LineInput(iNumArchivo)
[Link](sLinea)
End While
' cerrar el archivo
FileClose(iNumArchivo)
[Link]()
A pesar de que estas funciones nos permiten la manipulación de ficheros, debemos tener
muy presente que se trata de elementos fundamentalmente proporcionados para
compatibilidad con versiones anteriores, por lo que se recomienda que cuando
tengamos que hacer cualquier tipo de operación con archivos en cuanto a su lectura,
escritura, manipulación, etc., utilicemos las clases del espacio de nombres IO.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 455
13.- Ensamblados en Visual Basic net
Los ensamblados componen la unidad fundamental de implementación, control de
versiones, reutilización, ámbito de activación y permisos de seguridad en una aplicación
basada en .NET. Los ensamblados adoptan la forma de un archivo ejecutable (.exe) o un
archivo de biblioteca de vínculos dinámicos (.dll), y constituyen unidades de creación de
.NET Framework. Proporcionan a Common Language Runtime la información que necesita
para estar al corriente de las implementaciones de tipos. Un ensamblado puede entenderse
como una colección de tipos y recursos que forman una unidad lógica de funcionalidad y
que se generan para trabajar conjuntamente.
En Visual Basic, se utiliza el contenido de los ensamblados y se agregan referencias a dichos
ensamblados, de forma muy parecida a como se utilizaban las bibliotecas de tipos en
versiones anteriores de Visual Basic. No obstante, lo que distingue a los ensamblados de los
archivos .exe o .dll de versiones anteriores de Windows es que pueden contener toda la
información que antes se encontraba en una biblioteca de tipos, además de información de
todo aquello que sea necesario para utilizar la aplicación o el componente.
Manifiesto del ensamblado
Todos los ensamblados contienen un manifiesto del ensamblado. Éste es similar a una tabla
de contenido, y contiene la siguiente información:
La identidad del ensamblado (nombre y versión).
Una tabla de archivos que describe el resto de archivos que componen el
ensamblado, por ejemplo, otros ensamblados creados por el usuario de los que
dependa el archivo .exe o .dll, e incluso archivos de mapa de bits o archivos Léame.
Una lista de referencias de ensamblado, es decir, una lista de todas las dependencias
externas, archivos .dll u otros archivos necesarios para la aplicación que otros
usuarios hayan podido crear. Las referencias de ensamblado contienen referencias
a objetos globales y privados. Los objetos globales residen en la caché de
ensamblados global, un área disponible para otras aplicaciones, parecida al
directorio System32. El espacio de nombres [Link] es un ejemplo de
un ensamblado en la caché de ensamblados global. Los objetos privados deben
encontrarse en un directorio del mismo nivel o inferior al directorio de instalación
de la aplicación.
Dado que los ensamblados contienen información del contenido, la versión y las
dependencias, las aplicaciones que se crean con Visual Basic no dependen de los valores del
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 456
Registro para que funcionen correctamente. Los ensamblados reducen los conflictos de los
archivos DLL y hacen que las aplicaciones sean más seguras y más fáciles de implementar.
En muchos casos es posible instalar una aplicación basada en .NET simplemente copiando
los archivos de la aplicación en el equipo de destino.
Referencias
Para utilizar un ensamblado, debe agregar una referencia a él, tal como se describe en
Cómo: Agregar o quitar referencias en Visual Studio (Visual Basic). Luego, utiliza la
instrucción Imports para elegir el espacio de nombres de los elementos que desea utilizar,
tal como se describe en Referencias y la instrucción Imports. Una vez que se haya hecho
referencia a un ensamblado y se haya importado, todas las clases, propiedades, métodos y
otros miembros accesibles de su espacio de nombres están disponibles para la aplicación
como si su código formara parte del archivo de código fuente. Un ensamblado individual
puede contener varios espacios de nombres, y cada espacio de nombres puede contener
una agrupación de elementos distinta, incluidos otros espacios de nombres.
Crear ensamblados
Se pueden crear ensamblados de un único archivo o de varios archivos mediante un IDE,
como Visual Studio 2005 o mediante los compiladores y herramientas proporcionados en
Kit de desarrollo de software de Windows (SDK). El ensamblado más sencillo es un único
archivo que tiene un nombre sencillo y se carga en un solo dominio de aplicación. A este
ensamblado no pueden hacer referencia otros ensamblados de fuera del directorio de la
aplicación. En este ensamblado no se pueden comprobar las versiones. Para desinstalar la
aplicación que forma el ensamblado, no hay más que eliminar el directorio en que reside.
Muchos programadores no necesitan más que un ensamblado con estas características para
implementar una aplicación.
Se puede crear un ensamblado con varios archivos a partir de varios módulos de código y
archivos de recursos. También se puede crear un ensamblado que puedan compartir varias
aplicaciones. Un ensamblado compartido debe tener un nombre seguro y se puede
implementar en la caché de ensamblados global.
Existen varias opciones para agrupar módulos de código y recursos en ensamblados,
dependiendo de los siguientes factores:
Control de versiones
Agrupe módulos que deban tener la misma información de versión.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 457
Implementación
Agrupe módulos de código y recursos compatibles con el modelo de
implementación.
Reutilización
Agrupe módulos si se pueden utilizar juntos de forma lógica con la misma finalidad.
Por ejemplo, un ensamblado formado por tipos y clases que se usan raramente en
el mantenimiento de programas se pueden poner en el mismo ensamblado.
Además, los tipos que se vayan a compartir entre varias aplicaciones se deben
agrupar en un ensamblado, que se debe firmar con un nombre seguro.
Seguridad
Agrupe módulos que contengan tipos que requieran los mismos permisos de
seguridad.
Ámbito
Agrupe módulos que contengan tipos que sólo pueda ver el mismo ensamblado.
Si los ensamblados de Common Language Runtime van a estar disponibles para aplicaciones
COM no administradas hay que tener en cuenta factores especiales. Para obtener más
información sobre cómo trabajar con código no administrado, vea Exponer componentes
de .NET Framework en COM.
Cómo: Crear y utilizar ensamblados
Un ensamblado está formado por uno o más archivos .exe o .dll que componen una
aplicación de Visual Studio. Los ensamblados se crean de forma automática cuando se
compilan archivos de código fuente de Visual Basic.
Nota:
Los cuadros de diálogo y comandos de menú que se ven pueden diferir de los descritos
en la Ayuda, dependiendo de los valores de configuración o de edición activos. Para
cambiar la configuración, elija la opción Importar y exportar configuraciones en el menú
Herramientas. Para obtener más información, vea Valores de configuración de Visual
Studio.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 458
Para crear un ensamblado
Para compilar la aplicación, haga clic en Generar en el menú Generar o bien
genérela desde la línea de comandos, mediante el compilador de la línea de
comandos. Para obtener información detallada sobre la generación de
ensamblados desde la línea de comandos, vea Generar desde la línea de comandos
(Visual Basic).
Para agregar una referencia a otro ensamblado
Haga clic en el comando Agregar referencia del menú Proyecto y seleccione el
ensamblado que desee usar. Para obtener información detallada, vea Cómo:
Agregar o quitar referencias en Visual Studio (Visual Basic).
Para utilizar objetos en otro ensamblado
Especifique el nombre completo del objeto o utilice un alias que se haya definido
para el objeto por medio de una instrucción Imports. Para obtener información
detallada acerca de los nombres completos, vea Espacios de nombres en Visual
Basic. Para obtener información detallada sobre la adición de referencias y la
utilización de la instrucción Imports, vea Referencias y la instrucción Imports.
Cómo: Generar un ensamblado de un solo archivo
Un ensamblado de un único archivo, que es el tipo de ensamblado más sencillo, contiene la
información e implementación del tipo, además del manifiesto del ensamblado. Para crear
un ensamblado de un único archivo se pueden usar compiladores de la línea de comandos
o Visual Studio 2005. De forma predeterminada, el compilador crea un archivo de
ensamblado con la extensión .exe.
Nota:
Visual Studio 2005 para C# y Visual Basic sólo se puede utilizar para crear ensamblados de
un solo archivo. Si se desea crear ensamblados de múltiples archivos, se deben usar
compiladores de la línea de comandos o Visual Studio 2005 para Visual C++.
Los procedimientos siguientes muestran cómo se crean ensamblados de un único archivo
mediante compiladores de la línea de comandos.
Para crear un ensamblado con la extensión .exe
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 459
En el símbolo del sistema, escriba el siguiente comando:
<comando del compilador> <nombre del módulo>
En este comando, comando del compilador es el comando del compilador para el
lenguaje utilizado en el módulo de código y nombre del módulo es el nombre del
módulo de código que se va a compilar en el ensamblado.
En el ejemplo siguiente se crea un ensamblado denominado [Link] desde un módulo
de código denominado myCode.
C# VB
csc [Link]
Para crear un ensamblado con una extensión .exe y especificar el nombre del
archivo de resultados
En el símbolo del sistema, escriba el siguiente comando:
<comando del compilador> /out:<nombre de archivo> <nombre del módulo>
En este comando, comando del compilador es el comando del compilador para el
lenguaje usado en el módulo de código, nombre de archivo es el nombre del archivo
de salida y nombre del módulo es el nombre del módulo de código que se va a
compilar en el ensamblado.
En el ejemplo siguiente se crea un ensamblado denominado [Link] desde un
módulo de código denominado myCode.
C# VB
csc /out:[Link] [Link]
Crear ensamblados de biblioteca
Un ensamblado de biblioteca es parecido a una biblioteca de clases. Contiene tipos a los
que harán referencia otros ensamblados, pero no tiene un punto de entrada para comenzar
la ejecución.
Para crear un ensamblado de biblioteca
En el símbolo del sistema, escriba el siguiente comando:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 460
<comando del compilador> /t:library <nombre del módulo>
En este comando, comando del compilador es el comando del compilador para el
lenguaje utilizado en el módulo de código y nombre del módulo es el nombre del
módulo de código que se va a compilar en el ensamblado. También se pueden usar
otras opciones de compilador, por ejemplo /out:.
En el ejemplo siguiente se crea un ensamblado de biblioteca denominado
[Link] desde un módulo de código denominado myCode.
C# VB
csc /out:[Link] /t:library [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 461
14 .-Crear un proyecto de instalación (Setup) para
Windows
Introducción:
Aunque como sabemos con .NET Framework no es necesario crear programas (o
proyectos) de instalación, dado que este nuevo entorno facilita la forma de distribuir las
aplicaciones mediante lo que se llama instalación XCOPY (o FTP), es decir, podemos copiar
nuestras aplicaciones creadas con cualquier lenguaje .NET simplemente copiando el
directorio con el ejecutable y las librerías de las que depende al equipo en el que queremos
usarlo y ya funcionará. Pero funcionará si el equipo de destino ya tiene instalada el
"runtime" de .NET Framework, y esto es así porque ese runtime ya incluye todo lo que
necesitamos para que nuestra aplicación funcione. Aunque en ocasiones, es posible que
además de esas librerías "básicas" (incluidas en el runtime del .NET), necesitemos copiar
nuevas librerías, en ese caso simplemente copiaremos las librerías extras dentro del propio
directorio de nuestra aplicación y... ¡todo funcionará!
Esto es así porque no necesitamos registrar ningún componente para poder usarlo con
nuestra aplicación, por tanto... realmente no necesitamos crear ningún proyecto de
instalación, pero... si es eso lo que quieres hacer, para facilitarte las cosas, no es lo mismo
tener que copiar cosas en una carpeta que distribuir un instalador y que sea el propio
usuario el que se encargue del proceso de instalación, así como de eliminar dicha
instalación cuando le apetezca.
También habrá ocasiones en las que tengamos que instalar una librería "compartida", en
esos casos, la creación de un proyecto de instalación nos facilitará el registro (o copia) de
esa librería en el GAC (Global Assembly Cache, caché de ensamblado global) que es una
carpeta especial usada por el .NET Framework en la que estarán todas las librerías
compartidas del .NET Framework.
Nota:
Para que una librería se pueda usar de forma global, ésta debe estar firmada con un Strong
Name (nombre seguro). Si quieres saber más cómo crear (o firmar) una librería con nombre
seguro.
Aviso importante:
Una cosa que debes saber antes de seguir, es que creando un proyecto de instalación, no
se instala el runtime del .NET Framework.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 462
Cuando creamos el proyecto de instalación, éste se encargará de instalar nuestra aplicación
y los demás ficheros (archivos) que le indiquemos, pero NO instalará el runtime.
El runtime (o redistribuible) de .NET Framework debemos instalarlo por nuestra cuenta
ANTES de instalar nuestra aplicación.
Bien, sabiendo esto, sigamos con lo nuestro.
Vamos a ver cómo crear un proyecto de instalación.
Para que quede la cosa clara, primero tendremos que tener abierto el proyecto con el
ejecutable (o aplicación) que queremos distribuir, (si quieres, puedes crear un nuevo
proyecto, simplemente para probar).
Supongamos que el proyecto que queremos distribuir se llama: ClienteSetup y lo tenemos
abierto en el Visual Studio .NET (la versión usada para este artículo es la versión 2002, pero
los pasos a seguir serán los mismos para versiones posteriores).
Proyecto de instalación usando el Asistente:
Del menú Archivo, seleccionaremos la opción Agregar proyecto>Nuevo proyecto..., se
mostrará el cuadro de diálogo de añadir nuevo proyecto, del panel izquierdo
seleccionaProyectos de instalación e implementación, en el panel derecho se mostrarán
los posibles tipos de proyectos, seleccionaremos Asistente para proyectos de
instalación (después veremos cómo crear un proyecto de instalación sin usar el asistente).
Este cuadro de diálogo podemos verlo en la siguiente figura (Figura 1):
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 463
Figura 1, cuadro de diálogo Agregar nuevo proyecto
Se mostrará el Asistente para proyectos de instalación (iremos viendo las distintas pantallas
que se irán mostrando), en la figura 2, tenemos la primera de las 5 pantallas del asistente:
Figura 2, Primera pantalla del asistente
En esta pantalla, simplemente pulsaremos en Siguiente, para que se muestre la siguiente
pantalla del asistente:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 464
Figura 3, seleccionar el tipo de proyecto
Aquí dejaremos la opción que hay seleccionada, ya que lo que queremos es crear un
proyecto de instalación para una aplicación de Windows.
Pulsamos en Siguiente
En la cuarta pantalla del asistente, se nos preguntará qué es lo que queremos incluir en el
proyecto de instalación, tal como se muestra en la Figura 4:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 465
Figura 4, indicar los resultados a incluir en el proyecto de instalación
Si sólo queremos distribuir el ejecutable, seleccionaremos la primera de las opciones:
Resultado principal del "Nombre del proyecto", en caso de que queramos incluir también
el código fuente, seleccionaremos la última de las opciones que se indican, pero por ahora
sólo seleccionaremos la primera de ellas.
Una vez realizada la selección, pulsaremos en Siguiente.
Se nos mostrará la siguiente pantalla (ver la Figura 5), desde aquí podemos añadir más
archivos, como por ejemplo imágenes y otros ejecutables, bases de datos, etc., que nuestro
programa necesite; en caso de que así sea, pulsaremos en el botón Agregar... y
seleccionaremos el o los ficheros extras que queramos.
Si no tenemos que añadir nada más, (o cuando hayamos terminado de agregar los ficheros
que queramos), pulsaremos en Siguiente para finalizar el asistente.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 466
Figura 5
Una vez terminado, el asistente nos mostrará información sobre las cosas que hemos
indicado, tal como se muestra en la Figura 6:
Figura 6
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 467
Una vez que hemos terminado con el asistente, (después de pulsar en el botón Finalizar),
tendremos un nuevo proyecto en la solución del proyecto que queremos distribuir. Esto lo
podemos comprobar en el Explorador de soluciones, tal como podemos ver en la figura 7:
Figura 7, el explorador de soluciones
Lo único que nos queda es generar el proyecto Setup1 y ya tendremos creado el proyecto
de instalación, el cual se encontrará en la carpeta indicada para almacenar ese proyecto de
instalación y dependiendo que estemos en modo Debug o Release, tendremos que navegar
hasta la carpeta correspondiente.
Dentro de esa carpeta se incluirán estos ficheros:
Figura 8, los ficheros generados con el instalador
Realmente sólo necesitaremos el fichero con la extensión .msi, ya que el resto es para los
casos de que el equipo de destino no disponga del Windows Installer 2.0, si estamos seguro
de que es así, sólo necesitaremos usar el fichero [Link], si no estamos seguro de que
tenga el Windows Installer 2.0, usaremos los 5 ficheros incluidos en el directorio.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 468
Nota:
Si seleccionamos Propiedades del proyecto de instalación (el último icono mostrado al
seleccionar el proyecto de instalación del Explorador de soluciones, ver figura 7), podemos
cambiar esta generación de tantos ficheros "de soporte", es decir, podemos cambiar la
configuración para que sólo se genere el fichero con extensión .msi
Proyecto de instalación sin usar el asistente:
Si te decides por seleccionar un proyecto de instalación sin usar el asistente, sigue estos
pasos para crearlo:
1- Del cuadro de diálogo de Agregar nuevo proyecto (ver figura 1), selecciona Proyecto de
instalación.
2- Se agregará un nuevo proyecto de instalación.
3- Selecciona el proyecto del Explorador de soluciones, pulsa con el botón secundario del
ratón y del menú desplegable selecciona la opción Agregar>Resultados del proyecto.
4- Se mostrará una ventana como la de la figura 9:
Figura 9, agregar grupo de resultados del proyecto
5- Seleccionaremos de la lista desplegable el proyecto que queremos usar y pulsaremos en
Aceptar.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 469
A partir de este momento, el resto será como si hubiésemos usado el asistente.
También podemos usar esta última forma de agregar resultados (o más cosas) en el caso de
que queramos distribuir más de un proyecto, ya que en esa lista desplegable se mostrarán
cada uno de los proyectos que tengamos en nuestra solución (o grupo de proyectos).
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 470
BASES DE DATOS EN VISUAL BASIC NET
1.- Acceso a Datos con [Link] en Visual Basic
1.1.- Que es una base de datos
1.2.- Tipos de bases de datos
1.3.- Lenguaje de consulta estructurado
1.4.- Sentencias SQL básicas
1.5.- Acercandonos a [Link]
1.6.- SystemData
1.7.- Los proveedores de acceso a datos
1.8.- El concepto DataBinding
1.9.- Otras consideraciones
1.10.- El paradigama de conexión
2.- Trabajando con Datos
2.1.- Conociendo el objeto DataReader
2.2.- Un primer contacto con el objeto DataReader
2.3.- ¿Trabaja DatReader en un ambiente conectado realmente?
2.4.- Usando DataSource con DataReader
2.5.- Usando componentes de acceso a datos de .NET
2.6.- Esquema general de la estrucutra desconectada de acceso a datos
2.7.- Conociendo el objeto DataAdapter
2.8.- Insertando datos a través del Objeto DataAdapter
2.9.- Actualizando datos a través del objeto DataAdapter
2.10.- Eliminando datos a través del objeto DataAdapter
2.11.- ¿Qué son los datos Maestro Detalle?
2.12.- Configurando la fuente de datos
2.13.- Preparando el origen de datos
2.14.- Inscrustando los datos Maestro Detalle
2.15.- Manipulando los datos.
ADENDUM
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 471
Acceso a datos con [Link] en Visual Basic
1.1 Que es una base de datos
Una base de datos es un sistema formado por un conjunto de datos almacenados en discos
que permiten el acceso directo a ellos y un conjunto de programas que manipulen ese
conjunto de datos (S.G.B.D. Sistema de Gestión de Bases de Datos). Cada base de datos se
compone de una o más tablas que guarda un conjunto de datos. Cada tabla tiene una o más
columnas y filas. Las columnas guardan una parte de la información sobre cada elemento que
se quiere guardar en la tabla, cada fila de la tabla conforma un registro. Entre las principales
características se pueden mencionar:
Independencia lógica y física de los datos.
Redundancia mínima.
Acceso concurrente por parte de múltiples usuarios.
Integridad de los datos.
Consultas complejas optimizadas.
Seguridad de acceso y auditoria.
Respaldo y recuperación.
Acceso a través de lenguajes de programación estándar.
1.2 Tipos de bases de datos
1.2.1 Relacionales
Son las que más se utilizan. Las bases de datos relacionales son un conjunto de tablas
relacionadas entre sí, cada tabla está definida por una serie de campos. Los campos forman
las columnas de las tablas; definen el tipo y la variedad de sus datos. Las filas de datos se
denominan registros (tuplas), cada tipo definido en un registro se le denomina atributo. Las
tablas pertenecientes a una base de datos pueden relacionarse entre sí utilizando campos clave
comunes entre las tablas.
1.2.2 Enfoque orientado a objetos
El esquema de una base de datos por objetos está representado por un conjunto de clases que
definen las características y el comportamiento de los objetos que poblarán la base de datos.
Con una base de datos orientada a objetos, los objetos memorizados en la base de datos
contienen tanto los datos como las operaciones posibles con tales datos. En cierto sentido, se
podrá pensar en los objetos como en datos a los que se les ha puesto una inyección de
inteligencia que les permite saber cómo comportarse, sin tener que apoyarse en aplicaciones
externas.
1.3 Lenguaje de consulta estructurado
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 472
Es un lenguaje de base de datos normalizado, utilizado por los diferentes manejadores de
bases de datos para realizar determinadas operaciones sobre los datos o sobre la estructura
de los mismos.
El lenguaje SQL (Structure Query Languaje) está compuesto por comandos,
cláusulas, operadores y funciones de agregado. Estos elementos se combinan en las
instrucciones para crear, actualizar y manipular las bases de datos.
1.3.1 Comandos
Existen dos tipos de comandos SQL:
o DLL que permiten crear y definir nuevas bases de datos, campos e índices.
o DML que permiten generar consultas para ordenar, filtrar y extraer datos de la base
de datos.
Tabla 11.1 Comandos DLL y DML de SQL.
Comandos DLL
Comando Descripción
CREATE Utilizado para crear nuevas tablas, campos e índices
DROP Empleado para eliminar tablas e índices.
Utilizado para modificar las tablas agregando campos o
ALTER
cambiando la definición de los campos.
Comandos DML
Comando Descripción
Utilizado para consultar registros de la base de datos que
SELECT
satisfagan un criterio determinado.
Utilizado para cargar lotes de datos en la base de datos en una
INSERT
única operación.
UPDATE Utilizado para modificar los valores de los campos y registros
especificados.
DELETE Utilizado para eliminar registros de una tabla de una base de
datos.
1.3.2 Cláusulas
Las cláusulas son condiciones de modificación utilizadas para definir los datos que desea
seleccionar o manipular.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 473
Tabla 11.2 Clausulas SQL.
Cláusula Descripción
Utilizada para especificar la tabla de la cual se van a
FROM
seleccionar los registros.
Utilizada para especificar las condiciones que deben
WHERE
reunir los registros que se van a seleccionar.
Utilizada para separar los registros seleccionados en
GROUP BY
grupos específicos.
HAVING Utilizada para expresar la condición que debe satisfacer
cada grupo.
Utilizada para ordenar los registros seleccionados de
ORDER BY
acuerdo con un orden específico.
1.3.3 Operadores lógicos
Los operadores lógicos comprueban la veracidad de alguna condición. Éstos, como los
operadores de comparación, devuelven el tipo de datos Boolean con el valor TRUE o
FALSE
Tabla 11.3 Operadores lógicos SQL.
Operador Uso
Es el "y" lógico. Evalúa dos condiciones y devuelve un
AND
valor de verdad sólo si ambas son ciertas.
Es el "o" lógico. Evalúa dos condiciones y devuelve un
OR
valor de verdad si alguna de las dos es cierta.
NOT Negación lógica. Devuelve el valor contrario de la
expresión.
BETWEEN Utilizado para especificar un intervalo de valores.
LIKE Utilizado en la comparación de un patrón.
IN Utilizado para especificar registros de una base de datos.
ALL Devuelve True si el conjunto de comparaciones en verdad.
7.3.4 Operadores de comparación
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 474
Los operadores de comparación comprueban si dos expresiones son iguales. Se pueden
utilizar en todas las expresiones excepto en las de los tipos de datos text, ntext o image.
Tabla 11.4 Operadores de comparación SQL.
Operador Uso
< Menor que
> Mayor que
<> Distinto de
<= Menor o igual que
>= Mayor o igual que
= Igual que
1.3.5 Funciones de agregado
Las funciones de agregado realizan un cálculo sobre un conjunto de valores y devuelven un
solo valor. Si exceptuamos la función COUNT, todas las funciones de agregado ignoran los
valores NULL. Las funciones de agregado se suelen utilizar con la cláusula GROUP BY de
la instrucción SELECT.
Tabla 11.5 Funciones de agregado SQL.
Función Descripción
Utilizada para calcular el promedio de los valores de un
AVG
campo determinado.
COUNT Utilizada para devolver el número de registros de la
selección.
Utilizada para devolver la suma de todos los valores de
SUM
un campo determinado.
MAX Utilizada para devolver el valor más alto de un campo
especificado.
MIN Utilizada para devolver el valor más bajo de un campo
especificado.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 475
1.4 Sentencias SQL básicas
Se describirá muy brevemente algunas de las sentencias SQL para la manipulación de los
datos de una tabla llamada usuarios. Para ello utilizaremos la siguiente estructura:
Tabla : Estructura de los campos de la tabla usuarios.
Campo Tipo de Longitud
Dato
id Texto 15
Nombres Texto 20
apellidos Texto 20
dirección Texto 25
Teléfono Texto 20
Ciudad_nac Texto 20
Fecha_nac dateTime
Y que contiene la siguiente información:
Tabla : Información de la tabla usuarios.
Id Nombre Apellido Dirección Teléfono Ciudad_na Fecha_nac
s s c
100 Carlos Romero Cra 7 # 20-10 4152584 Bogota 01/02/198
0
101 María Castro Calle 25 # 25- 3692581 Cali 15/03/198
10 4
112 José Peláez Av. 35 # 32-45 1234567 Medellín 20/05/196
0
114 Cristian Vanega Cra 7 # 29-58 9874561 Manizales 31/08/197
s 4
116 Rosa Cetina Calle 17 # 21- 3571596 Buga 15/12/198
14 5
118 Andrés Vanega Tranvs 48 # 8527419 Bogota 10/04/197
s 22-10 8
130 Angélic Morales Cra 68 # 21-11 6549518 Medellín 20/06/198
a 1
150 Johana Duarte Cra 2 # 45-38 9637534 Bogota 12/06/198
8
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 476
170 Mario Vargas Calle 1 # 99-18 6598743 Medellín 28/08/198
0
1.4.1 Sentencia SELECT
La sentencia SQL que más se utiliza es la instrucción de selección SELECT. Como su
nombre lo indica es una instrucción que permite seleccionar información de una tabla. Su
formato es:
SELECT campos_tabla FROM nombre_tabla
A continuación se realizarán algunos ejemplos:
Para visualizar toda la información que contiene la tabla usuarios se puede incluir con la
instrucción SELECT el carácter “*‟ o cada uno de los campos de la tabla.
SELECT * FROM usuarios
O
SELECT identificación, nombres,…….. FROM usuarios
Para visualizar solamente la identificación del usuario
SELECT identificacion FROM usuarios
Si se desea obtener los registros cuya identificación sea menor o igual que 116, se debe
utilizar la cláusula WHERE que especifica las condiciones que deben reunir los registros que
se van a seleccionar.
SELECT * FROM usuarios WHERE identificación<=”116”
Si se desea obtener los registros cuyos nombres sean Andrés o Cristian, se debe utilizar el
operador IN que especifica registros de una tabla.
SELECT nombres FROM usuarios WHERE nombres IN
(“Andres”,”Cristian”)
O se puede utilizar el operador OR
SELECT * FROM usuarios WHERE nombres=”Andrés” OR
nombres=”Cristian”
Si se desea obtener los registros cuya identificación sea menor de “130‟ y la ciudad sea
“Bogota‟, se debe utilizar el operador AND.
SELECT * FROM usuarios WHERE identificación <= ”130” AND ciudad =
”Bogota”
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 477
Si se desea obtener los registros cuyos nombres empiecen por la letra “C‟, se debe utilizar el
operador LIKE que utiliza los patrones “%‟ (todos) y “_‟ (carácter).
SELECT * FROM usuarios WHERE nombres LIKE “C%”
Si se desea obtener los registros cuyos nombres contenga la letra “i‟.
SELECT * FROM usuarios WHERE nombres LIKE “%i%”
Si se desea obtener los registros donde la segunda letra del nombre sea una “o‟.
SELECT * FROM usuarios WHERE nombres LIKE” _o%”
Si se desea obtener los registros cuya identificación este entre el intervalo 116 y 140, se debe
utilizar la cláusula BETWEEN, que sirve para especificar un intervalo de valores.
SELECT * FROM usuarios WHERE identificación BETWEEN “116” AND ”140”
1.4.2 Sentencia INSERT
La sentencia SQL de inserción de datos INSERT permite insertar información en una tabla.
Su formato es:
INSERT INTO nombre_tabla (campo1, campo2,….) VALUES (valor1,
valor2,….)
Para insertar un nuevo registro a la tabla usuarios se debería realizar la siguiente sentencia:
INSERT INTO usuarios (identificación, nombres, apellidos, dirección, teléfono,
ciudad_nac,fecha_nac) VALUES (“160”,”Carmen”,”Bolivar”,”Calle 100 # 115-
55”,”201420”,”Barranquilla”,”18/11/1692”)
1.4.3 Sentencia DELETE
La sentencia SQL de eliminación de datos DELETE permite borrar todos o un grupo
especifico de registros de una tabla. Su formato es:
DELETE FROM nombre_tabla
A continuación se realizarán algunos ejemplos:
Para eliminar todos los registros de la tabla usuarios.
DELETE FROM usuarios
Para eliminar solamente los registros cuya identificación sea mayor que “150‟.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 478
DELETE FROM usuarios WHERE identificación >”150”
Para eliminar los registros diferentes del nombre “Cristian”
DELETE FROM usuarios WHERE nombres NOT IN (“Cristian”)
1.4.4 Sentencia ALTER
La sentencia SQL ALTER permite insertar un nuevo campo en una tabla. Su formato es:
ALTER TABLE nombre_tabla ADD nombre_campo tipo_de_dato()
Para insertar un nuevo campo a la tabla usuarios llamado de tipo numérico se debería
realizar la siguiente sentencia:
ALTER TABLE usuarios ADD creditonumeric(18,0)
7.4.5 Sentencia UPDATE
La sentencia SQL de actualización UPDATE permite actualizar un campo de una tabla. Su
formato es:
UPDATE nombre_tabla SET nombre_campo=criterio
A continuación realizaremos algunos ejemplos:
Para actualizar el campo crédito con un valor de 100000 en la tabla usuarios.
UPDATE usuarios SET credito=100000
Para actualizar el campo credito en 200000 para los registros cuyo nombre empiecen por
”A‟.
UPDATE usuarios SET credito=credito +200000 WHERE nombres LIKE “A%”
Para actualizar el campo credito en 50000 para los registros cuya ciudad sea igual a “Bogota‟.
UPDATE usuarios SET credito=credito+50000 WHERE ciudad=”Bogota”
1.6. Acercándonos a [Link]
En este módulo, aprenderemos a trabajar con datos y fuentes de datos en Visual Basic
[Link] es la tecnología principal para conectarse a una base de datos, nos ofrece un
alto nivel de abstracción, ocultando los detalles de bajo nivel de la implementación de la
base de datos de un fabricante.
En este tutorial, encontrará las cosas más importantes que debe saber, para trabajar con
fuentes de datos con Visual Basic. De esta manera, aprenderá en poco tiempo, a
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 479
encontrarse cómodo en el entorno de clases de [Link] y podrá así, sacar el máximo
provecho a sus desarrollos. Las partes que forman parte de este módulo son las
siguientes:
[Link] ha sufrido a lo largo de los últimos años diferentes mejoras y actualizaciones,
desde que .NET apareció.El resumen de las diferentes versiones de [Link] podría quedar
de la siguiente forma.
[Link] 1.0 apareció con Microsoft .NET Framework 1.0. Posteriormente, [Link] 1.1
sufrió una pequeñas y casi inapreciables actualizaciones con la aparición de Microsoft .NET
Framework 1.1. En el caso del entorno Visual Studio, éste trabaja con Microsoft .NET
Framework 2.0 y por lo tanto, utiliza [Link] 2.0, el cuál añade algunas características
nuevas adicionales.
En nuestro caso, nos centraremos única y exclusivamente en [Link] como modelo de
objetos de acceso a datos para la plataforma .NET de Microsoft, ya que es el mismo para
cualquier tipo de versión de [Link].
¿Qué es [Link]?
[Link] es la tecnología principal para conectarse aun gestor de bases de datos, con un
alto nivel de abstracción, lo que nos permite olvidarnos de los detalles de bajo nivel de las
bases de datos. Además [Link] es una tecnología inter operativa. Aparte del
almacenamiento y recuperación de datos, [Link] introduce la posibilidad de integrarse
con el estándar XML, los datos pueden 'Serializarse' directamente a y desde XML lo que
favorece el intercambio de información.
[Link] proporciona diferentes clases del nombre de espacio [Link] dentro de las
cuáles, destacaremos por encima de todas, la clase DataView, la clase DataSet y la clase
DataTable.
Este conjunto de clases de carácter armónico, funcionan de igual forma con la capa inferior
que es la que corresponde a los proveedores de acceso a datos con los que podemos trabajar.
Esto facilita el trabajo en n-capas y la posible migración de aplicaciones que utilicen una
determinada fuente de datos y deseemos en un momento dado, hacer uso de otra fuente de
datos.
¿Qué capas o qué partes hay dentro de [Link]?
Dentro de [Link] tenemos dos partes importantes.
La primera de ellas es la que corresponde con el nombre de espacio [Link] y que
constituye los objetos y clases globales de [Link].
La otra parte es la que corresponde con los objetos que permiten el acceso a datos a una
determinada fuente de datos desde [Link] y que utilizan así mismo, las clases del nombre
de espacio [Link].
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 480
Esta última parte, queda constituida por las clases y objetos de los diferentes proveedores
de acceso a datos como se muestra en la figura 1.
Visión general de las clases de [Link]
Para resumir de alguna forma lo que estamos comentando, diremos que el trabajo de
conexión con la base de datos, la ejecución de una instrucción SQL determinada, una vista,
etc., la realiza el proveedor de acceso a datos.
Recuperar esos datos para tratarlos, manipularlos o volcarlos a un determinado control o
dispositivo, es acción de la capa superior que corresponde con el nombre de espacio
[Link].
A continuación veremos todo esto con más detalle y comprenderemos de una forma más
clara cada una de las partes que componen el modelo de trabajo con [Link].
¿Qué nos permite realmente [Link] cuando trabajamos con XML?
El entorno de Microsoft .NET Framework nos proporciona el trabajo con estándares y con
ello, la posibilidad de trabajar con diferentes tipos de aplicaciones, entornos, sistemas
operativos y lenguajes sin necesidad de conocer lo que hay al otro lado de nuestra
aplicación.
XML es sin lugar a dudas, el lenguaje de etiquetas por excelencia, válido para llevar a cabo
esta tarea sin tener un impacto relevante cuando trabajamos con diferentes soluciones en
entornos dispares.
Tanto la posibilidad de trabajar con Servicios Web XML como con documentos e
información en XML, sobre todo al trabajar con fuentes de datos en [Link], nos
proporciona a los desarrolladores las posibilidades necesarias que nos permite hacer que
la información con la que trabajamos, pueda ser tratada entre diferentes sistemas o
entornos, sin que por ello nos preocupemos de lo que hay al otro lado.
1.7. [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 481
Las clases del nombre de espacio [Link] son bastantes extensas y variadas. Quizás las
clases más importantes son la clase DataView, la clase DataSet y la clase DataTable.
La clase DataSet
El DataSet es una representación de datos residente en memoria que proporciona una
modelo de programación relacional coherente independientemente del origen de datos que
contiene. El DataSet contiene en sí, un conjunto de datos que han sido volcados desde el
proveedor de datos.
Debemos tener en cuenta que cuando trabajamos con DataSets, el origen de datos no es lo
más importante, ya que éste, puede ser cualquier tipo de origen de datos. No tiene porqué
ser una base de datos.
Un DataSet contiene colecciones de DataTables y DataRelations.
El DataTable contiene una tabla o tablas, mientras que la DataRelation contiene las
relaciones entre las DataTables. Sin embargo, no es necesario especificar todo esto hasta
el último detalle como veremos más adelante.
La clase DataView
Este objeto nos permite crear múltiples vistas de nuestros datos, además de permitirnos
presentar los datos. Es la clase que nos permite representar los datos de la clase DataTable,
permitiéndonos editar, ordenar y filtrar, buscar y navegar por un conjunto de datos
determinado.
La clase DataTable
Este objeto nos permite representar una determinada tabla en memoria, de modo que
podamos interactuar con ella.
A la hora de trabajar con este objeto, debemos tener en cuenta el nombre con el cuál
definamos una determinada tabla, ya que los objetos declarados en el DataTable es sensitivo
a mayúsculas y minúsculas.
Un pequeño ejemplo práctico
El siguiente ejemplo práctico, nos enseña a utilizar un DataSet y nos muestra cómo
podemos acceder a los objetos que dependen de un DataSet para recuperar por ejemplo,
los campos y propiedades de una determinada tabla o tablas.
Imports [Link]
Imports [Link]
Imports [Link]
Public Class Form1
Private Sub Form1_Load(ByVal sender As [Link], ByVal e
As [Link]) Handles [Link]
Dim Conexion As String =
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 482
"server=.;uid=sa;password=VisualBasic;database=MSDNVideo"
Dim MiTabla As DataTable
Dim MiColumna As DataColumn
Dim MiDataSet As New DataSet()
Dim Comando As New SqlDataAdapter("SELECT * FROM
ALQUILERES", Conexion)
[Link](MiDataSet, "ALQUILERES")
' Recorremos las tablas
For Each MiTabla In [Link]
[Link] += "Tabla: " & [Link] & vbCrLf
' Recorremos las Columnas de cada Tabla
For Each MiColumna In [Link]
[Link] += [Link] & vbTab &
"(" & [Link] & ")" & & vbCrLf
Next
Next
Comando = Nothing
End Sub
End Class
Nuestro ejemplo en ejecución es el que se muestra en la figura 1.
Ejemplo en ejecución del uso de DataSet, DataTable y DataColumn
1.8. Los proveedores de acceso a datos
Los proveedores de acceso a datos es la capa inferior de la parte correspondiente al
acceso de datos y es la responsable de establecer la comunicación con las fuentes de
datos. En este conjunto de nombres de espacio, encontraremos casi siempre las clases
Connection, Command, DataAdapter y DataReader como las clases más generales, las
cuales nos permiten establecer la conexión con la fuente de datos.
Proveedores de acceso a datos de .NET Framework
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 483
Dentro del entorno .NET Framework, encontramos un nutrido conjunto de
proveedores de acceso a datos. Estos son los siguientes:
● ODBC .NET Data Provider
● OLE DB .NET Data Provider
● Oracle Client .NET Data Provider
● SQL Server .NET Data Provider
Estos proveedores de acceso a datos incluidos en Microsoft .NET Framework, los
podemos encontrar en los nombres de espacio:
● [Link]
● [Link]
● [Link]
● [Link]
El proveedor ODBC .NET permite conectar nuestras aplicaciones a fuentes de datos a
través de ODBC.
El proveedor OLE DB .NET permite conectar nuestras aplicaciones a fuentes de datos a
través de OLE DB.
El proveedor Oracle Client .NET es un proveedor de acceso a datos especialmente
diseñado para bases de datos Oracle.
Por último, el proveedor SQL Server .NET es un proveedor de acceso a datos nativo, que
nos permite conectar nuestras aplicaciones a fuentes de datos Microsoft SQL Server 7 o
posterior. Se trata de un proveedor específico para bases de datos Microsoft SQL Server
7.0, Microsoft SQL Server 2000 y Microsoft SQL Server 2005; 2008
Nota:
Siempre que pueda, utilice para acceder a fuentes de datos, un proveedor de
acceso a datos nativo. Esto le permitirá aumentar considerablemente el
rendimiento a la hora de establecer la conexión con una determinada fuente de
datos
Los proveedores de acceso a datos que distribuye Microsoft en [Link] y algunos
desarrollados por otras empresas o terceros, contienen los mismos objetos, aunque los
nombres de éstos, sus propiedades y métodos, pueden ser diferentes.
Más adelante veremos algún ejemplo, y observará en la práctica cuáles son estas diferencias
más destacables.
Otros proveedores de acceso a datos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 484
Si bien el proveedor de acceso a datos es el mecanismo a través del cuál podemos establecer
una comunicación nativa con una determinada fuente de datos, y dado que Microsoft
proporciona los proveedores de acceso a datos más corrientes, es cierto que no los
proporciona todos, si bien, con OLE DB y ODBC, podemos acceder a la inmensa totalidad
de ellos.
Sin embargo, hay muchos motores de bases de datos de igual importancia como Oracle,
MySql, AS/400, etc. En estos casos, si queremos utilizar un proveedor de acceso a datos
nativo, deberemos acudir al fabricante o a empresas o iniciativas particulares para que nos
proporcionen el conjunto de clases necesarias que nos permitan abordar esta acción.
El objeto Connection
Este objeto es el encargado de establecer una conexión física con una base de datos
determinada. Para establecer la conexión con una determinada fuente de datos, no sólo
debemos establecer la cadena de conexión correctamente, sino que además deberemos
usar los parámetros de conexión y el proveedor de acceso a datos adecuado. Con este
objeto, podremos además abrir y cerrar una conexión.
El objeto Command
Este objeto es el que representa una determinada sentencia SQL o un Stored
Procedure. Aunque no es obligatorio su uso, en caso de necesitarlo, lo utilizaremos
conjuntamente con el objeto DataAdapter que es el encargado de ejecutar la instrucción
indicada.
El objeto DataAdapter
Este objeto es quizás el objeto más complejo y a la vez complicado de todos los que
forman parte de un proveedor de acceso a datos en .NET. Cuando deseamos establecer
una comunicación entre una fuente de datos y un DataSet, utilizamos como intermediario
a un objeto DataAdapter. A su vez, un DataAdapter contiene 4 objetos que debemos
conocer:
● SelectCommand es el objeto encargado de realizar los trabajos de selección de
datos con una fuente de datos dada. En sí, es el que se encarga de devolver y rellenar
los datos de una fuente deb datos a un DataSet.
● DeleteCommand es el objeto encargado de realizar las acciones de borrado de
datos.
● InsertCommand es el objeto encargado de realizar las acciones de inserción de
datos.
● UpdateCommand es el objeto encargado de realizar las acciones de
actualización de datos.
Los objetos DeleteCommand, InsertCommand y UpdateCommand son los objetos que se
utilizan para manipular y transmitir datos de una fuente de datos determinada, al contrario
del objeto SelectCommand que tan sólo interactúa con la fuente de datos para recuperar una
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 485
porción o todos los datos indicados en el objeto Command anteriormente comentado.
El objeto DataReader
Este objeto es el utilizado en una sola dirección de datos. Se trata de un objeto de acceso a
datos muy rápido. Este objeto puede usar a su vez el objeto Command o el método
ExecuteReader.
1.9.- El concepto DataBinding
DataBinding es una expresión de enlace a datos. Como veremos a continuación es una forma
rápida y sencilla de manejar la fuentes de datos mediante su enlace con controles o clases.
El uso de DataBind
El método DataBind se utiliza para rellenar de datos un determinado control o clase.
Muchos controles y clases, posee este método al que le asignaremos un conjunto de datos
para que se rellene con ellos, pudiendo después interactuar con los datos de forma directa.
En sí, un DataBinding es un enlace a datos que se encarga de rellenar de datos a un
determinado control o clase. Como ejemplo de esto, veremos como rellenar un control
TextBox con un dato utilizando este método.
Iniciaremos una nueva aplicación Windows y escribiremos el siguiente código fuente:
Imports [Link]
Imports [Link]
Imports [Link]
Public Class Form1
Private Sub Form1_Load(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim Conexion As String =
"server=.;uid=sa;password=VisualBasic;database=MSDNVideo"
Dim MiDataSet As New DataSet()
Dim Comando As New SqlDataAdapter("SELECT TITULO FROM
ALQUILERES, PELICULAS WHERE PELICULACODBARRAS = CODBARRAS
AND SOCIONIF = '111111'", Conexion)
' Rellenamos el DataSet con el contenido de la sentencia SELECT
[Link](MiDataSet, "PELIS")
' Rellenamos el control TextBox1 con el dato correspondiente a la primera fila
' de la sentencia SELECT ejecutada
[Link]("Text", MiDataSet,"[Link]")
Comando = Nothing
End Sub
End Class
Nuestro ejemplo en ejecución es el que se muestra en la figura.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 486
Ejemplo en ejecución del uso de DataBinding
1.10.- Otras consideraciones
Dentro de las conexiones a fuentes de datos, hay algunas partes de éstas que permanecen a
veces en el olvido y su importancia sin embargo, es bastante grande. La acción más pesada
cuando realizamos un acceso a una fuente de datos, se encuentra en la conexión con la fuente
de datos. Esa tarea, simple tarea, es la que más recursos del sistema consume cuando
Accedemos a fuentes de datos.
Esto lo debemos tener en cuenta, y por lo tanto, variante de esto que comentamos son
las siguientes premisas:
● La conexión debe realizarse siempre que se pueda, con los proveedores de acceso a
datos nativos, que por lo general salvo raras excepciones, serán más rápidos que los accesos
a fuentes de datos a través de proveedores del tipo OLE DB y ODBC.
● La conexión con la fuente de datos (apertura de la conexión), debe realizarse lo más
tarde posible. Es recomendable definir todas las variables que podamos, antes de realizar
la conexión.
● La conexión debe cerrarse lo antes posible, siempre y cuando no tengamos la necesidad
de utilizar la conexión previamente abierta.
Hay más particularidades a tener en cuenta cuando trabajamos con fuentes de datos. El
hecho de que con un DataSet podamos trabajar con datos desconectados, no significa que
dentro de él, podamos abrir una tabla con una cantidad de registros enormes, y trabajemos
sobre ella creyendo que esto nos beneficiará. Todo lo contrario.
1.11.- El paradigma de la conexión
Cuando abordamos un proyecto de acceso a fuentes de datos, siempre nos
encontramos con una duda existencial.
¿Debemos crear una conexión con la base de datos al principio de nuestra aplicación y
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 487
cerrarla cuando la aplicación se cierre?, ¿o debemos crear una conexión con la base de
datos sólo cuando vayamos a trabajar con la fuente de datos?. ¿Y si estamos trabajando
continuamente con una fuente de datos?, ¿cómo penalizarían todas estas acciones?.
Es difícil de asumir que acción tomar en cada caso, y es que dependiendo de lo que vayamos
a realizar, a veces es más efectiva una acción que otra, y en otras ocasiones, no está del todo
claro, ya que no existe en sí una regla clara que especifique qué acción tomar en un momento
dado.
Lo que sí está claro es que el modelo de datos de [Link] que hemos visto, quedaría
resumido en cuanto a la conectividad de la manera en la que se representa en la figura
Visión general de [Link] respecto a la conectividad con bases de datos
El objeto DataSet nos ofrece la posibilidad de almacenar datos, tablas y bases de datos de
una determinada fuente de datos. De esta manera, podemos trabajar con las aplicaciones
estando desconectados de la fuente de datos.
Sin embargo, a veces necesitamos trabajar con la fuente de datos estando conectados a ella.
El objeto DataReader nos ofrece precisamente la posibilidad de trabajar con fuentes de
datos conectadas.
Por otro lado, el objeto DataReader tiene algunas particularidades que conviene
conocer y que veremos a continuación.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 488
2.- Trabajando con datos
2.1.- Conociendo el objeto DataReader
El objeto DataReader nos permite como hemos indicado anteriormente, establecer una
conexión con una fuente de datos y trabajar con esta fuente de datos sin desconectarnos
de ella, sin embargo, hay diferentes cualidades y particularidades que conviene
conocer.
DataReader es de solo lectura
Lo que hemos dicho anteriormente, requiere sin embargo, que esta conexión se
establezca en un modo de sólo lectura, al contrario de lo que se puede hacer con el
objeto DataSet, con el que podemos interactuar con la fuente de datos en modo lectura
y modo escritura.
DataReader se maneja en una sola dirección
El objeto DataReader sólo permite que nos desplacemos por los datos en una sola dirección,
sin vuelta atrás. Por el contrario, el objeto DataSet nos permite movernos por los registros
para adelante y para atrás.
Además, sólo podemos utilizar el objeto DataReader con conexiones establecidas en una
sentencia SQL por ejemplo, pero no podemos variar esta. Para hacerlo, debemos entonces
modificar la conexión con el comando establecido.
DataReader es rápido
Debido a su naturaleza y características, este objeto es bastante rápido a la hora de
trabajar con datos. Como es lógico, consume además menos memoria y recursos que un
objeto DataSet por ejemplo. Sin embargo, dependiendo de las necesidades con las que
nos encontremos, puede que este método de acceso y trabajo no sea el más idóneo.
Analizando el flujo de trabajo de DataReader
Cuando trabajamos con fuentes de datos conectadas, trabajaremos con el objeto
DataReader.
Para trabajar con este objeto, utilizaremos los objetos siguientes del proveedor de
acceso a datos:
● Connection
● Command
● DataReader
Un resumen gráfico de esto es lo que podemos ver en la figura 1.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 489
El flujo de conectividad de DataReader
2.2.- Un primer contacto con el objeto DataReader
A continuación veremos un ejemplo sencillo sobre la forma de trabajar con DataReader
Un ejemplo simple para entenderlo mejor
Tenga en cuenta que en el siguiente ejemplo nos conectaremos a Microsoft SQL
Server y recorreremos los registros uno a uno en un ambiente conectado y
volcaremos estos registros en un control TextBox.
Imports [Link]
Imports [Link]
Imports [Link]
Public Class Form1
Private Sub Form1_Load(ByVal sender As [Link], ByVal e
As [Link]) Handles [Link]
Dim Conexion As String =
"server=.;uid=sa;password=VisualBasic;database=MSDNVideo"
Dim MiConexion As New SqlConnection(Conexion)
Dim MiDataReader As SqlDataReader
Dim Comando As New SqlCommand("SELECT TITULO FROM
ALQUILERES, PELICULAS WHERE PELICULACODBARRAS = CODBARRAS
AND
SOCIONIF = '111111'", MiConexion)
[Link]()
MiDataReader = [Link]()
While [Link]()
[Link] += MiDataReader("TITULO") & vbCrLf
End While
Comando = Nothing
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 490
[Link]()
End Sub
End Class
El código de ejemplo en ejecución es el que se muestra en la figura 1.
Ejemplo en ejecución del uso simple de DataReader
Este es un ejemplo simple del uso de DataReader.
Sin embargo, el objeto DataReader contiene un conjunto de propiedades y métodos que nos
proporcionan acciones determinadas. Por ejemplo, en el ejemplo anterior, hemos dado por
hecho que la ejecución de la instrucción Select nos devolverá uno o más valores, pero
podríamos también saber antes de manipular y trabajar con los posibles datos, si hay o no
información. Esto lo conseguimos con el método HasRows.
2.3.- ¿Trabaja DataReader en un ambiente conectado
Realmente?
Pese a todo esto, ¿que ocurre si trabajando en un ambiente conectado se desconecta el
servidor de acceso a datos?. Imaginemos por un instante, que la conexión con SQL Server
se establece correctamente y que en un momento dado se detiene el servicio del servidor
de base de datos. Esto es lo que veremos en el siguiente ejemplo.
Desenchufando la fuente de datos usando DataReader
Inicie un nuevo proyecto, inserte en el formulario de la aplicación un control TextBox y un
control Button, y escriba el código que se detalla a continuación:
Imports [Link]
Imports [Link]
Imports [Link]
Public Class Form1
Private Conexion As String =
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 491
"server=.;uid=sa;password=VisualBasic;database=MSDNVideo"
Private strSQL As String = "SELECT TITULO FROM ALQUILERES,
PELICULAS WHERE PELICULACODBARRAS = CODBARRAS AND SOCIONIF
= '111111'"
Private MiConexion As New SqlConnection(Conexion)
Private MiDataReader As SqlDataReader
Private Contador As Long = 0
Private Posicion As Long = 0
Private Sub Form1_Load(ByVal sender As [Link], ByVal e
As [Link]) Handles [Link]
' Establecemos la Conexión con la base de datos
Establecer_Conexion(True)
' Si hay datos los mostramos, sino deshabilitamos la opción (botón) para recorrerlos
If Not [Link] Then
[Link] = False
Else
Button1_Click(sender, e)
End If
End Sub
Private Sub Establecer_Conexion(ByVal bolAccion As Boolean)
Dim Comando As SqlCommand
If bolAccion Then
' True => Establecemos la conexión
Comando = New SqlCommand(strSQL, MiConexion)
' Abrimos la Conexión
[Link]()
' Ejecutamos la sentencia SQL
MiDataReader = [Link]()
' Obtenemos la cantidad de registros obtenidos
Contador = [Link]() + 1
Else
' False => Finalizamos la conexión
[Link] = False
' Cerramos la Conexión
Comando = Nothing
[Link]()
End If
End Sub
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' Recorremos los registros y los mostramos
Posicion += 1
[Link]()
[Link] = MiDataReader("TITULO")
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 492
' Si hemos recorrido el objeto por completo, finalizamos la Conexión y
' deshabilitamos el control Button que nos permite recuperar los registros
If Posicion = Contador Then
Establecer_Conexion(False)
End If
End Sub
End Class
Suponiendo que tenemos en nuestra base de datos varios registros, ejecute la aplicación. Si
todo ha ido como se esperaba, observaremos que nuestra aplicación tiene un aspecto como
el que se muestra en la figura
Ejemplo en ejecución del uso de DataReader en un ambiente conectado,
forzando la desconexión de la fuente de datos
En este punto, detenga el servicio de SQL Server y pulse el botón Siguiente >>. Observará
que la aplicación sigue funcionando. En este punto se hará la pregunta que todos nos hemos
hecho, ¿no es el objeto DataReader un objeto conectado?, ¿cómo es posible que funcione si
hemos detenido el servicio de SQL Server?. La respuesta es sencilla. El objeto DataReader
recupera un nutrido conjunto de valores llenando un pequeño buffer de datos e información.
Si el número de registros que hay en el buffer se acaban, el objeto DataReader regresará a
la fuente de datos para recuperar más registros. Si el servicio de SQL Server está detenido
en ese momento o en su caso, la fuente de datos está parada, la aplicación generará un error
a la hora de leer el siguiente registro.
En sí, DataReader es un objeto conectado, pero trabaja en background con un conjunto de
datos, por lo que a veces nos puede resultar chocante su comportamiento como el ejemplo
que comento.
2.4.- Usando DataSource con DataReader
¿Podemos usar el método DataSource con el objeto DataReader?.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 493
Demostración del uso de DataSource con DataReader
La respuesta es sí, en [Link] 2.0, se ha incorporado un nuevo método al objeto
DataTable que le permite tener mayor independencia respecto al modo en el que nos
conectemos y recuperemos datos de una fuente de datos. Recuerde que podemos
recuperar datos en modo conectado DataReader o en modo desconectado DataSet.
Este método que se ha incorporado a [Link] y que tiene por nombre Load, nos permite
cargar un DataReader para volcarlo a continuación dentro de un control como por ejemplo
el control DataGridView. Lo mejor es que veamos como funciona esto con un ejemplo que
nos ayude a comprender mejor la teoría. Inserte en un formulario un control DataGridView
y escriba el siguiente código:
Imports [Link]
Imports [Link]
Imports [Link]
Public Class Form1
Private Sub Form1_Load(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' Declaramos las variables a utilizar
Dim Conexion As String =
"server=.;uid=sa;password=VisualBasic;database=MSDNVideo"
Dim strSQL As String = "SELECT TITULO FROM ALQUILERES,
PELICULAS WHERE PELICULACODBARRAS = CODBARRAS AND SOCIONIF
= '111111'"
Dim MiConexion As New SqlConnection(Conexion)
Dim MiDataReader As SqlDataReader
Dim MiDataTable As New DataTable
Dim Comando As SqlCommand
' Establecemos la Conexión con la base de datos
Comando = New SqlCommand(strSQL, MiConexion)
' Abrimos la Conexión
[Link]()
' Ejecutamos la sentencia SQL
MiDataReader = [Link]()
' Cargamos los resultados en el objeto DataTable
[Link](MiDataReader, [Link])
' Volcamos los datos en el control DataGridView
[Link] = MiDataTable
' Cerramos la Conexión
Comando = Nothing
[Link]()
End Sub
End Class
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 494
Nuestro ejemplo en ejecución es el que podemos ver en la figura
Ejemplo en ejecución del uso de DataReader y DataSource en un control
DataGridView
Con todo y con esto, lo que realmente es curioso, es que hemos olvidado por un instante que
el objeto DataReader es un objeto de sólo lectura que funciona en una única dirección, hacia
delante. ¿Qué significa esto o como puede influir o como podemos aprovechar esta
circunstancia en nuestros desarrollos?.
Carga segmentada de datos con DataSource y DataReader
Si recuperamos los datos de una fuente de datos con DataReader y leemos algunos de sus
datos y posteriormente, ejecutamos el método DataSource, el resto de datos, aquellos datos
que quedan en el DataReader, serán los que se vuelquen en el control que definamos como
destino de los datos. Imaginemos el ejemplo anterior, y el siguiente código fuente.
Imports [Link]
Imports [Link]
Imports [Link]
Public Class Form1
Private Sub Form1_Load(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' Declaramos las variables a utilizar
Dim Conexion As String =
"server=.;uid=sa;password=VisualBasic;database=MSDNVideo"
Dim strSQL As String = "SELECT TITULO FROM ALQUILERES,
PELICULAS WHERE PELICULACODBARRAS = CODBARRAS AND SOCIONIF
= '111111'"
Dim MiConexion As New SqlConnection(Conexion)
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 495
Dim MiDataReader As SqlDataReader
Dim MiDataTable As New DataTable
Dim Comando As SqlCommand
' Establecemos la Conexión con la base de datos
Comando = New SqlCommand(strSQL, MiConexion)
' Abrimos la Conexión
[Link]()
' Ejecutamos la sentencia SQL
MiDataReader = [Link]()
' Leemos el primer registro y así nos posicionamos a partir del segundo de ellos
[Link]()
' Cargamos los resultados en el objeto DataTable
[Link](MiDataReader, [Link])
' Volcamos los datos en el control DataGridView
[Link] = MiDataTable
' Cerramos la Conexión
Comando = Nothing
[Link]()
End Sub
End Class
En este caso, lo que ocurre como ya hemos comentado, es que los datos que se cargan son
los que aún no han sido leídos en el objeto DataReader, por lo que se mostrarán todos los
datos desde el último leído hasta llegar al final del objeto.
2.5.- Usando los componentes de acceso a datos de .NET
Los componentes del entorno .NET nos proporcionan las características necesarias
para poder acceder a fuentes de datos de forma rápida y sencilla.
El mejor ejemplo de esto que comento es el que veremos a continuación.
Demostración del uso de BindingSource y BindingNavigator
Para ello, crearemos un proyecto nuevo e insertaremos un control BindingSource y un
control BindingNavigator dentro del formulario.
También insertaremos un control TextBox al formulario, dónde presentaremos la
información sobre la que navegaremos. Nuestro formulario con los controles insertados en
él, tendrá un aspecto similar al que se presenta en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 496
Controles de navegación y acceso a datos dispuestos en el formulario
Figura 1
Una vez llegado a este punto, lo que tendremos que hacer a continuación será escribir
el código fuente necesario para poder representar los datos de la sentencia SQL en el
control BingindNavigator, para que a su vez los presente en el control TextBox. A
continuación se indica el código fuente de esta parte de demostración de la aplicación.
Imports [Link]
Imports [Link]
Imports [Link]
Public Class Form1
Private Sub Form1_Load(ByVal sender As [Link], ByVal eAs
[Link]) Handles [Link]
' Declaramos las variables a utilizar
Dim Conexion As String =
"server=.;uid=sa;password=VisualBasic;database=MSDNVideo"
Dim strSQL As String = "SELECT TITULO FROM ALQUILERES,
PELICULAS WHERE PELICULACODBARRAS = CODBARRAS AND SOCIONIF
= '111111'"
Dim MiConexion As New SqlConnection(Conexion)
Dim MiDataReader As SqlDataReader
Dim MiDataTable As New DataTable
Dim Comando As SqlCommand
' Establecemos la Conexión con la base de datos
Comando = New SqlCommand(strSQL, MiConexion)
' Abrimos la Conexión
[Link]()
' Ejecutamos la sentencia SQL
MiDataReader = [Link]()
' Cargamos los resultados en el objeto DataTable
[Link](MiDataReader, [Link])
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 497
' Volcamos los datos en el control TextBox
[Link] = MiDataTable
[Link] = BindingSource1
[Link](New Binding("Text", BindingSource1, "TITULO",
True))
' Cerramos la Conexión
Comando = Nothing
[Link]()
End Sub
End Class
2.6.- Esquema general de la estructura desconectada de acceso a
datos
En los capítulos anteriores de este módulo, hemos visto ya el uso de la clase DataSet. Incluso
lo hemos visto con algún ejemplo.
La clase DataSet está pensada y diseñada para trabajar con fuentes de datos
desconectadas. Indudablemente, en este punto, debemos tener clara la estructura
general de cómo funciona el acceso desconectado con fuentes de datos. En la figura,
podemos observar el diagrama general de esta parte
Estructura general del uso de DataSet en el acceso desconectado a
datos
Connection, DataAdapter y DataSet
Como podemos observar en la figura 1, para comunicarnos con una fuente de datos, siempre
deberemos establecer una conexión, independientemente de si la conexión con la fuente de
datos va a permanecer a lo largo del tiempo o no.
El objeto Connection nos permite por lo tanto, establecer la conexión con la fuente de datos.
El objeto DataSet nos permite por otro lado, recoger los datos de la fuente de datos y
mandárselos a la aplicación.
Entre medias de estos dos objetos, encontramos el objeto DataAdapter que hace las
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 498
funciones de puente o nexo de unión entre la conexión y el objeto DataSet.
Esto es lo que veremos a continuación, como funciona el objeto DataAdapter, y como encaja
todo esto en el acceso a fuentes de datos desconectadas.
2.6.1- Conociendo el objeto DataAdapter
El objeto DataAdapter forma parte del proveedor de acceso a datos, tal y como se muestra
en la figura
Visión general de las clases de [Link]
Cada proveedor de acceso a datos posee su propio objeto DataAdapter. Cuando realizamos
alguna modificación o acción sobre la fuente de datos, utilizaremos siempre el objeto
DataAdapter a caballo entre el objeto DataSet y la fuente de datos establecida a través de
la conexión con el objeto [Link] el objeto DataAdapter, podremos además realizar
diferentes acciones sobre nuestras bases de datos, acciones como la ejecución general de
sentencias de SQL no sólo para seleccionar un conjunto de datos, sino para alterar el
contenido de una base de datos o de sus tablas.
Connection, DataAdapter y DataSet
Antes de entrar en materia más profundamente, diremos que en lo que respecta a los
proveedores de acceso a datos que vienen integrados con .NET, encontramos dos formas de
usar un DataAdapter.
La primera de ellas es utilizando los componentes del proveedor de acceso a datos. La
segunda de ellas es utilizando las clases del nombre de espacio del proveedor de acceso a
datos. La mejor forma de entender todo esto que comentamos, es trabajando con un ejemplo
práctico que nos enseñe a usar el objeto DataAdapter en Visual Studio
Utilizando las clases de .NET
En este primer ejemplo de demostración del uso de DataAdapter a través de código
usando para ello las clases de .NET, estableceremos una conexión con SQL Server y
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 499
mostraremos los datos recogidos en un control TextBox.
Iniciaremos Visual Studio y seleccionaremos un proyecto de formulario de Windows.
Dentro del formulario, insertaremos un control TextBox y añadiremos dos referencias al
proyecto. Las referencias añadidas serán a las librerías [Link] y [Link],
como se muestra en la figura
Referencias a las clases de acceso a datos de .NET
Una vez que hemos añadido las referencias necesarias para utilizar las clases que queremos
en nuestro proyecto, iremos al código y escribiremos las siguientes instrucciones:
Imports [Link]
Imports [Link]
Public Class Form1
Private Sub Form1_Load(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' Establecemos la cadena de conexión con la BBDD
Dim Conexion As String =
"server=.;uid=sa;password=VisualBasic;database=MSDNVideo"
' Declaramos el DataSet dónde volcaremos los datos
Dim MiDataSet As New DataSet()
' Declaramos el DataAdapter estableciendo
' la conexión con la fuente de datos SQL
Dim Comando As New SqlDataAdapter("SELECT SocioNIF,
FechaAlquiler FROM ALQUILERES", Conexion)
' Rellenamos el DataSet con el contenido de la instrucción
[Link](MiDataSet)
' Cerramos la conexión con la BBDD
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 500
Comando = Nothing
' Declaramos la propiedad Row para recorrer
' las filas contenidas en el DataSet
Dim Row
' Recorremos todas las filas y las tratamos
For Each Row In [Link](0).Rows
[Link] += Row("SocioNIF").ToString & vbTab &
Row("FechaAlquiler") & vbCrLf
Next
' Vaciamos el DataSet para liberar memoria
MiDataSet = Nothing
End Sub
End Class
El ejemplo en ejecución del uso de DataAdapter junto con las clases de .NET es el que se
muestra en la figura
Ejemplo del acceso a datos con DataAdapter a través de las clases de .NET
2.7.- Utilizando los componentes de .NET
Existe otro método de acceso a fuentes de datos diferente a las clases de .NET, el acceso a
través de componentes que nos faciliten esa tarea. Sin embargo, los componentes de acceso
a datos, utilizan por detrás las clases de .NET que hemos visto, lo que ocurre, es que
simplifica enormemente el trabajo y ahorra tiempo a la hora de desarrollar aplicaciones.
De todos los modos, todo depende de la utilidad o necesidades con las que nos encontremos
en un momento dado. Iniciaremos un proyecto Windows nuevamente, e insertaremos en él
un control TextBox.
A continuación, añadiremos los componentes de acceso a fuentes de datos SQL Server que
es la fuente de datos origen. Como hemos visto, para conectar a fuentes de datos SQL Server,
hemos utilizado el nombre de espacio [Link] y hemos importado en el proyecto los
nombres de espacio [Link] y [Link].
Los componentes .NET de acceso a fuentes de datos de SQL Server, se identifican por el
nombre Sqlxxx, siendo xxx el tipo de componente a utilizar. Para poder utilizarlos,
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 501
deberemos añadirlo a la barra de herramientas.
Para añadir los componentes a nuestro proyecto, haremos soble clic sobre el formulario y
posteriormente haremos clic con el botón secundario del mouse sobre la barra de
herramientas y seleccionaremos la opción Elegir elementos... como se muestra en la figura
Opción de la barra de herramientas para añadir componentes al entorno
Una vez que hemos hecho esto, seleccionaremos los componentes SqlCommand,
SqlCommandBuilder, SqlConnection, SqlDataAdapter y SqlDataSource, tal y como se
muestra en la figura
Componentes a añadir al entorno
Una vez que hemos añadido los componentes al entorno, estos quedarán dispuestos
dentro de la barra de herramientas como se indica en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 502
Componentes añadidos en la barra de herramientas
Lo primero que haremos será insertar un componente SqlConnection dentro del
formulario. Acudiremos a la ventana de propiedades del componente y
modificaremos la propiedad ConnectionString dentro de la cuál escribiremos la
instrucción:
server=.;uid=sa;password=VisualBasic;database=MSDNVideo
Entendiendo que ésta, es la cadena de conexión válida con nuestra base de datos. A
continuación añadiremos el componente SqlDataAdapter a nuestro formulario. Si se abre
alguna ventana, ciérrela.
Vamos a configurar el control con la ventana Propiedades. Podríamos haberlo hecho
desde el asistente que se nos ha abierto, pero lo vamos a hacer de otra forma menos
sencilla.
Sitúese sobre la propiedad SelectCommand, y dentro de ésta, en la propiedad Connection.
Lo que vamos a hacer, es asignar al componente SqlDataAdapter el componente de conexión
que vamos a usar para establecer la comunicación entre la fuente de datos y nuestra
aplicación.
Despliegue la propiedad Connection indicada, y seleccione el componente de conexión
SqlConnection1 anteriormente configurado, tal y como se muestra en la figura.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 503
Componente SqlDataAdapter con la conexión establecida para ser
usada en la ejecución de nuestra aplicación
Por último, inserte un componente DataSet al formulario. Todos los componentes
quedarán por lo tanto insertados, tal y como se indica en la figura
Componentes añadidos en el formulario de nuestra aplicación
Una vez que tenemos todo preparado, tan sólo nos queda escribir la parte de código fuente
necesario para poder realizar todas las operaciones y acciones que necesitamos. A
continuación, se expone el código fuente de nuestra aplicación de demostración:
Public Class Form1
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 504
Private Sub Form1_Load(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' Establecemos la cadena SQL a utilizar
[Link] = "SELECT
SocioNIF, FechaAlquiler FROM ALQUILERES"
' Abrimos la Conexión
[Link]()
' Rellenamos el DataSet con el contenido de la instrucción SQL
[Link](DataSet1)
' Cerramos la Conexión
[Link]()
' Declaramos la propiedad Row para recorrer las filas contenidas en el DataSet
Dim Row
' Recorremos todas las filas y las tratamos
For Each Row In [Link](0).Rows
[Link] += Row("SocioNIF").ToString & vbTab & Row("FechaAlquiler") &
vbCrLf
Next
End Sub
End Class
Ahora nos queda únicamente ejecutar nuestra aplicación para estudiar el resultado final.
Este es el que se puede ver en la figura
Ejemplo en ejecución del uso de componentes
Pese a todo lo que hemos visto, quizás se pregunte como es que en el caso del primer ejemplo
que hemos visto y en el que hemos declarado el uso de un DataAdapter sin usar componentes,
hemos tenido la obligatoriedad de añadir las referencias a los nombres de espacio
[Link] y [Link], mientras que en este segundo ejemplo, no hemos hecho
referencia a ellos.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 505
En realidad nosotros no hemos hecho referencia a ellos, pero al insertar los componentes
dentro del formulario, el entorno Visual Studio 2005 se ha encargado por nosotros de añadir
esas referencias al proyecto, tal y como puede verse en la figura.
Referencias añadidas automáticamente al trabajar con componentes de acceso a datos
2.7.1.- Insertando datos a través del objeto DataAdapter
Hasta ahora, todos los ejemplos que hemos visto del objeto DataAdapter, han sido ejemplos
del uso de selección de datos, pero aún no hemos visto como debemos trabajar cuando
realicemos otras acciones sobre la fuente de datos.
A continuación, veremos como realizar acciones de actualización de datos, utilizando
para ello el objeto DataAdapter.
Nota:
El DataSet permanece desconectado de la fuente de datos y si realizamos una
modificación o alteración de los datos de un DataSet, estos no son propagados a la
fuente de datos. Para ello, el DataAdapter debe recibir la orden que queramos
ejecutar.
Agregando datos con el objeto DataAdapter
Suponiendo que hemos recogido un conjunto de datos y que trabajando con el objeto
DataSet hemos realizado una inserción de datos y que a continuación, queremos propagar
dicha inserción a la base de datos, deberemos hacer uso del método Insert del objeto
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 506
DataAdapter.
El objeto DataAdapter se encargará de llamar al comando apropiado para cada una de las
filas que han sido modificadas en un determinado DataSet.
Esto lo realizará siempre a través del método Update.
Trabajando con un ejemplo
La mejor manera de ver esto es con un ejemplo que nos ayude a entender mejor como
funciona la inserción de datos a través del objeto DataAdapter.
Tenga en cuenta además, que la actualización y el borrado de datos funciona de la
misma manera. Iniciaremos un nuevo proyecto de formulario Windows y en él
insertamos los componentes SqlConnection, SqlDataAdapter, DataSet y SqlCommand.
Para el componente SqlConnection, estableceremos la propiedad ConnectionString con
el valor:
server=.;uid=sa;password=VisualBasic;database=MSDNVideo
A continuación seleccionaremos el componente SqlDataAdapter y modificaremos la
propiedad SelectCommand > Connection como vimos en el capítulo anterior.
De la lista de posibles conexiones que le aparezca, seleccione la conexión SqlConnection1.
Finalmente, inserte un control Button y un control DataGridView en el formulario. Éste
quedará como se indica en la figura.
Formulario con los componentes y controles insertados en él Figura 1
Finalmente, escribiremos el código necesario para ejecutar nuestra aplicación tal y como
queremos. Este es el que se detalla a continuación:
Public Class Form1
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 507
Private Sub Form1_Load(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' Establecemos la cadena SQL a utilizar
[Link] = "SELECT NIF, Nombre,
Apellido1, Apellido2, Telefono, Email, Direccion, Ciudad, Provincia, CP FROM
SOCIOS"
' Abrimos la Conexión
[Link]()
' Rellenamos el DataSet con el contenido de la instrucción sql
[Link](DataSet1, "Ejemplo")
' Cerramos la Conexión
[Link]()
' Asociamos el control DataGridView al DataSet
[Link] = [Link]("Ejemplo")
End Sub
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' Declaramos un objeto DataRow para insertar en él los nuevos datos
Dim MiDataRow As [Link]
' Creamos una nueva fila en el DataSet
MiDataRow = [Link]("Ejemplo").NewRow()
' Insertamos los datos en el DataSet
MiDataRow("NIF") = "222222"
MiDataRow("Nombre") = "María"
MiDataRow("Apellido1") = "Juárez"
MiDataRow("Apellido2") = "Fernández"
MiDataRow("Telefono") = "1112233"
MiDataRow("Email") = "maría@[Link]"
MiDataRow("Direccion") = "C\ Fernández de los Ríos, 77"
MiDataRow("Ciudad") = "Valladolid"
MiDataRow("Provincia") = "Valladolid"
MiDataRow("CP") = "11111"
[Link]("Ejemplo").[Link](MiDataRow)
' Si el DataSet tiene cambios ?
If [Link] Then
' Indicamos la instrucción SQL correspondiente
[Link] = "INSERT INTO SOCIOS(NIF,
Nombre, Apellido1, Apellido2, Telefono, Email, Direccion, Ciudad, Provincia, CP)
VALUES(@NIF, @Nombre, @Apellido1, @Apellido2, @Telefono, @Email,
@Direccion, @Ciudad, @Provincia, @CP)"
' Establecemos para el comando, la (conexión) que utilizaremos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 508
[Link] = SqlConnection1
' Le indicamos al DataAdapter, cuál es el comando de inserción que usaremos
[Link] = SqlCommand1
' Añadimos los parámetros y comandos correspondientes
' para cada campo a añadir en la base de datos
[Link]("@NIF", [Link], 10, "NIF")
[Link]("@Nombre",
[Link], 50, "Nombre")
[Link]("@Apellido1",
[Link], 50, "Apellido1")
[Link]("@Apellido2",
[Link], 50, "Apellido2")
[Link]("@Telefono",
[Link], 13, "Telefono")
[Link]("@Email",
[Link], 50, "Email")
[Link]("@Direccion",
[Link], 100, "Direccion")
[Link]("@Ciudad",
[Link], 50, "Ciudad")
[Link]("@Provincia",
[Link], 50, "Provincia")
[Link]("@CP", [Link], 5,"CP")
' Abrimos la conexión
[Link]()
' Realizamos la inserción de datos desde el DataSet a través del DataAdapter
[Link](DataSet1, "Ejemplo")
' Cerramos la conexión
[Link]()
' Indicamos con un mensaje que la inserción de datos se ha realizado con éxito
[Link]("Datos insertados correctamente")
End If
End Sub
End Class
Por último, ejecute la aplicación. Si todo ha ido correctamente, los datos habrán quedado
correctamente insertados en la base de datos. Un ejemplo de nuestra aplicación en
ejecución es la que puede verse en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 509
Aplicación de ejemplo de inserción de datos con DataAdapter y DataSet en ejecución
Como vemos, el uso de DataAdapter en el caso de manipular datos, varía ligeramente. Sin
embargo, no es mucho más complicado con la actualización y borrado de datos. De hecho,
la forma de actuar es la misma como veremos a continuación.
2.7.2.- Actualizando datos a través del objeto DataAdapter
De la misma manera que hemos insertado datos en nuestra base de datos, debemos hacer a
la hora de actualizar los mismos. Sobre la base del ejemplo anterior (componentes y
controles), escriba o modifique el siguiente código:
Public Class Form1
Private Sub Form1_Load(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' Establecemos la cadena SQL a utilizar
[Link] = "SELECT NIF, Nombre,
Apellido1, Apellido2, Telefono, Email, Direccion, Ciudad, Provincia, CP FROM
SOCIOS"
' Abrimos la Conexión SQL
[Link]()
[Link](DataSet1, "Ejemplo")
' Cerramos la Conexión
[Link]()
' Asociamos el control DataGridView al DataSet
[Link] = [Link]("Ejemplo")
End Sub
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' En nuestro ejemplo, sabemos que queremos modificar
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 510
' la fila 2, columna 4 (todos los elementos empiezan por 0)
[Link]("Ejemplo").Rows(1)(4) = "1112234"
' Si el DataSet tiene cambios ?
If [Link] Then
' Indicamos la instrucción SQL correspondiente
[Link] = "UPDATE SOCIOS SET
Telefono=@Telefono WHERE NIF=@NIF"
' Establecemos para el comando, la (conexión) que utilizaremos
[Link] = SqlConnection1
' Le indicamos al DataAdapter, cuál es el comando de actualización que usaremos
[Link] = SqlCommand1
' Añadimos los parámetros y comandos orrespondientes
' para cada campo a actualizar en la base de datos
[Link]("@NIF", [Link],10, "NIF")
[Link]("@Nombre",
[Link], 50, "Nombre")
[Link]("@Apellido1",
[Link], 50, "Apellido1")
[Link]("@Apellido2",
[Link], 50, "Apellido2")
[Link]("@Telefono",
[Link], 13, "Telefono")
[Link]("@Email",
[Link], 50, "Email")
[Link]("@Direccion",
[Link], 100, "Direccion")
[Link]("@Ciudad",
[Link], 50, "Ciudad")
[Link]("@Provincia",
[Link], 50, "Provincia")
[Link]("@CP", [Link], 5, "CP")
' Abrimos la conexión
[Link]()
' Realizamos la actualización de datos desde el DataSet a través del DataAdapter
[Link](DataSet1, "Ejemplo")
' Cerramos la conexión
[Link]()
' Indicamos con un mensaje que la actualización de datos se ha realizado con éxito
[Link]("Datos actualizados correctamente")
End If
End Sub
End Class
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 511
Nuestro ejemplo en ejecución es el que se puede ver en la figura 1.
Aplicación de ejemplo de actualización de datos con DataAdapter y DataSet
2.7.3.- Eliminando datos a través del objeto DataAdapter
De igual forma sucede con la eliminación de datos utilizando para ello el objeto
DataAdapter junto al objeto DataSet.
Utilizaremos nuevamente en este caso, la base del ejemplo anterior (componentes y
controles), y escribiremos el siguiente código:
Public Class Form1
Private Sub Form1_Load(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' Establecemos la cadena SQL a utilizar
[Link] = "SELECT NIF,Nombre,
Apellido1, Apellido2, Telefono, Email, Direccion, Ciudad,Provincia, CP FROM
SOCIOS"
' Abrimos la Conexión
[Link]()
' Rellenamos el DataSet con el contenido de la instrucción SQL
[Link](DataSet1, "Ejemplo")
' Cerramos la Conexión
[Link]()
' Asociamos el control DataGridView al DataSet
[Link] = [Link]("Ejemplo")
End Sub
Private Sub Button1_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' En nuestro ejemplo, sabemos que queremos eliminar
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 512
' la fila 2 (todos los elementos empiezan por 0) por lo que la fila 2 es aquí la 1
[Link]("Ejemplo").Rows(1).Delete()
' Si el DataSet tiene cambios ?
If [Link] Then
' Indicamos la instrucción SQL correspondiente
[Link] = "DELETE SOCIOS WHERE NIF=@NIF"
' Establecemos para el comando, la (conexión) que utilizaremos
[Link] = SqlConnection1
' Le indicamos al DataAdapter, cuál es el comando de eliminación que usaremos
[Link] = SqlCommand1
' Añadimos los parámetros y comandos correspondientes
' para cada campo a actualizar en la base de datos
[Link]("@NIF", [Link],10, "NIF")
[Link]("@Nombre",
[Link], 50, "Nombre")
[Link]("@Apellido1",
[Link], 50, "Apellido1")
[Link]("@Apellido2",
[Link], 50, "Apellido2")
[Link]("@Telefono",
[Link], 13, "Telefono")
[Link]("@Email",
[Link], 50, "Email")
[Link]("@Direccion",
[Link], 100, "Direccion")
[Link]("@Ciudad",
[Link], 50, "Ciudad")
[Link]("@Provincia",
[Link], 50, "Provincia")
[Link]("@CP", [Link], 5,"CP")
' Abrimos la conexión
[Link]()
' Realizamos la eliminación de datos desde el DataSet a través del DataAdapter
[Link](DataSet1, "Ejemplo")
' Cerramos la conexión
[Link]()
' Indicamos con un mensaje que la eliminación de datos se ha realizado con éxito
[Link]("Datos eliminados correctamente")
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 513
End If
End Sub
End Class
Nuestro ejemplo en ejecución es el que se puede ver en la figura .
Aplicación de ejemplo de eliminación de datos con DataAdapter y DataSet
2.8.- Trabajando con tablas Maestro Detalle.
El desarrollador de aplicaciones que debe trabajar con datos y fuentes de datos relacionadas
entre sí, encuentra con frecuencia problemas de desarrollo en aplicaciones con datos
interrelacionados. Además, este tipo de aplicaciones, consumen gran parte del tiempo de
desarrollo y son por lo general, acciones repetitivas.
Supongamos como ejemplo general, la tabla Socios de un videoclub. Además, relacionemos
los socios del videoclub, con una tabla Alquileres, para saber si un socio determinado tiene
películas alquiladas, y en ese caso, saber cuáles.
Este sencillo ejemplo, es un claro exponente de una aplicación que relaciona datos maestro
detalle. Ambas tablas deben estar relacionadas para recopilar la información que se
necesite en un momento dado.
Los datos maestros serían expuestos por los socios del videoclub, mientras que los datos
detalle estarían relacionados con los datos de los alquileres de los socios.
En nuestro caso, vamos a cambiar las palabras maestro y detalle por padre e hijo, y a partir
de ahora, nos referiremos a padre como la tabla Socios, e hijo como la tabla Alquileres. De
esta forma, ubicaremos sin problemas ambos conceptos dentro del entorno de Visual Studio
2008, ya que éste tiene alguna ligera connotación que podría infundirnos a error como
observará más adelante.
Por suerte, Visual Studio nos proporciona un conjunto de herramientas, que hace que
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 514
realizar una aplicación Windows con todas las características de una aplicación maestro
detalle, sea un auténtico juego de niños, que nos llevará aproximadamente un minuto de
nuestro tiempo como mucho. ¿No me cree?. Continúe el capítulo, y se sorprenderá de lo
que Visual Studio 2008 puede hacer por usted.
2.9.- Configurando la fuente de datos
Trabajar con fuentes de datos requiere como tarea inicial, que tengamos listo y preparado
un origen de fuentes de datos válido. Para esta tarea, deberemos configurar la fuente de
datos que vamos a utilizar, algo que vamos a aprender a hacer a continuación.
Configurando el origen de la fuente de datos
Iniciaremos una nueva aplicación Windows con Visual Studio y seleccionaremos el menú
Datos > Mostrar orígenes de datos como se indica en la figura
Menú para mostrar los orígenes de datos
En este punto, aparecerá una ventana como la que se muestra en la figura.
Ventana de orígenes de datos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 515
Como podemos apreciar, la ventana no tiene por defecto ningún origen de datos asignado,
además, esta ventana inicialmente, no está anclada a ningún sitio del entorno. Para situarla
en un lugar específico del entorno, haga clic sobre la ventana y arrástrela sobre la parte en
la que desee situarla, como se indica por ejemplo, en la figura
La ventana orígenes de datos podemos situarla dónde deseemos dentro de Visual
Studio
En este punto, la ventana de orígenes de datos, quedará anclada en el entorno de
desarrollo, como se muestra en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 516
La ventana orígenes de datos anclada en Visual Studio
Cada uno, puede situar esta ventana dónde considere oportuno. En mi caso la he situado
entre las ventanas del Explorador de soluciones y de Propiedades, pero podemos situarla
dónde consideremos oportuno. Sobre la configuración del origen de datos, haga clic sobre
la opción Agregar nuevo origen de datos... como se indica en la figura
Opción para agregar un nuevo origen de datos
Aparecerá una ventana como la que se muestra en la figura 6 en la cuál indicaremos el lugar
de dónde la aplicación obtendrá los datos, y que en nuestro caso será de una Base de datos.
Como tipo de origen de datos elegiremos una Base de datos
Una vez seleccionado la opción de Base de datos como tipo de origen de datos,
presionaremos el botón Siguiente.
En la siguiente ventana, elegiremos la conexión de la base de datos que vamos a utilizar, o
presionaremos sobre el botón Nueva conexión... sino tenemos seleccionada la conexión que
queremos utilizar.
En la figura podemos ver como hemos establecido la conexión con nuestra fuente de
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 517
datos, que utilizaremos en nuestro ejemplo de creación de la aplicación de acceso a
datos maestro detalle.
Ventana dónde elegimos la conexión de datos
A continuación, haremos clic en el botón Siguiente.
En la nueva ventana que aparece ahora dentro del asistente para la creación del origen de
datos, indicaremos el nombre de la cadena de conexión que crearemos. En nuestro caso, no
modificaremos el nombre de la cadena de conexión, dejándola por defecto como se muestra
en la figura
Asignamos un nombre para el nombre de la cadena de conexión
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 518
A continuación, haremos clic sobre el botón Siguiente.
En este punto, el asistente se conecta a la base de datos para recuperar la
información de la base de datos y mostrarla en la ventana del asistente como se
muestra en la figura
Ventana con los objetos de la base de datos seleccionada
A continuación, despliegue el objeto Tablas y seleccione las tablas Alquileres y Socios como
se indica en la figura
Selección de los objetos de la base de datos seleccionada
Una vez que hemos seleccionado los objetos de la base de datos, haremos clic sobre el botón
Finalizar para que el asistente concluya las opciones añadidas al asistente. La ventana del
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 519
origen de datos, quedará ahora configurado de una forma similar a la que se presenta en la
figura
Ventana de origen de datos con la configuración añadida
A partir de aquí, deberemos preparar las tablas del origen de datos para que se comporten
como auténticos datos e informaciones maestro detalle. Esto es lo que veremos en el
siguiente módulo.
2.9.1.- Preparando el origen de datos
Ya hemos aprendido a añadir nuestro origen de datos, y ahora aprenderemos a prepararlo
para poder utilizarlo posteriormente en la aplicación Windows.
La preparación del origen de datos, nos permitirá seleccionar que tabla o datos queremos
que actúen como maestro y cuales como detalle, o dicho de otra forma, que datos queremos
que sean padre y cuales hijo.
Nuestro objetivo principal es mostrar la tabla Alquileres como tabla hijo y la tabla Socios
como padre de la tabla anterior.
Prepararemos e incrustaremos primero la tabla Socios dentro del formulario Windows como
Detalle de la información, y posteriormente insertaremos la tabla Alquileres dentro del
formulario.
Por último, asignaremos alguna relación que permita trabajar con las dos tablas en nuestro
formulario Windows sin perder la conexión entre ambas tablas y permitiéndonos acceder a
la información que nos proporciona dicha relación.
Preparando la tabla padre
Lo primero que haremos será preparar la tabla padre para poderla añadir al formulario
Windows. Por esa razón, haremos clic sobre la tabla Socios de la ventana de Orígenes de
datos como se indica en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 520
Tabla Socios de la ventana de orígenes de datos
En la ventana de Orígenes de datos y en concreto con la tabla Socios desplegada,
centraremos nuestra atención en el campo NIF como se indica en la figura
Campo NIF de la tabla Socios
Pulse sobre la lista desplegable que aparece a la derecha del campo NIF y seleccione la
opción Label como se indica en la figura
Lista desplegable con la opción Label seleccionada como campo de la tabla
desplegada
En este caso, la ventana de Orígenes de datos quedará informada tal y como se indica
en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 521
Campo NIF modificado en la ventana de Orígenes de datos
A continuación, haremos clic sobre la tabla Socios como se indica en la figura, y
posteriormente presionaremos sobre la lista desplegable que aparece a la derecha de la
tabla.
Tabla Socios seleccionada en la ventana de Orígenes de datos
Si hacemos clic sobre la lista desplegable, aparecerá una lista de opciones o posibilidades,
para indicar cómo queremos que sean los campos de la tabla seleccionada con respecto a que
tipo de controles queremos que sean. Esto es lo que se indica en la figura
Lista desplegable de la tabla Socios de la ventana de Orígenes de datos
Por defecto, una tabla queda determinada con un icono que representa el control
DataGridView, aunque se puede modificar la representación que deseamos tengan los datos
dentro de un formulario seleccionando cualquiera de las opciones que tenemos de la lista
desplegable. Estas opciones pueden ser cualquiera de las siguientes:
Representa los datos volcados dentro de un control DataGridView
Representa los datos volcados dentro de controles estándar como TextBox u otros
controles para reflejarla como Detalle de la información
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 522
No representa ningún control como tipo de control de volcado de datos
En el caso de la tabla Socios que usaremos como tabla padre, cambiaremos la
representación por defecto de DataGridView para indicarle que nos represente la
información en controles, tal y como se indica en la figura
Tabla Socios seleccionada en la ventana de Orígenes de datos como Detalle
Ahora que tenemos la tabla maestra ya preparada, pasaremos a preparar la
tabla hija.
Preparando la tabla hija
Ahora que ya tenemos preparada la tabla tabla padre, prepararemos la tabla hija de los
alquileres de las películas de video, para poder usar su información dentro del formulario
Windows. Por esa razón, haga clic sobre la tabla Alquileres de la ventana de Orígenes
de datos como se indica en la figura
Tabla Alquileres de la ventana de orígenes de datos
Dentro de la ventana de Orígenes de datos y en concreto de la tabla Alquileres
desplegada, centraremos nuestra atención en el campo AlquilerID y SocioNIF como
se indica en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 523
Campos AlquilerID y SocioNIF de la tabla Alquileres
Sobre el campo AlquilerID y SocioNIF, haremos una pequeña modificación. Pulse sobre la
lista desplegable que aparece a la derecha del campo AlquilerID y SocioNIF y seleccione la
opción Label como se indica en la figura
Lista desplegable de opciones de un campo de la tabla desplegada
De esta manera, el campo AlquilerID y SocioNIF quedarán modificados en la ventana
Orígenes de datos como se indica en la figura
Campo AlquilerID y SocioNIF modificados en la ventana de Orígenes de datos
A continuación, haremos clic sobre la tabla Alquileres como se indica en la figura, y
posteriormente presionaremos sobre la lista desplegable que aparece a la derecha de la tabla.
Tabla Alquileres seleccionada en la ventana de Orígenes de datos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 524
Nos aseguraremos que está seleccionada la opción DataGridView que es la que
aparece por defecto. Esto es lo que se indica en la figura
En la tabla Alquileres, nos aseguraremos de seleccionar la opción DataGridView
Una vez que tenemos las tabla maestra y detalle preparadas para utilizarlas, las añadiremos
al formulario Windows para que tengan el funcionamiento esperado.
2.9.2.- Incrustando los datos maestro detalle
Ya sabemos como crear un origen de datos, también sabemos como preparar los datos
maestro y detalle, y por último, lo que nos queda es insertar esos datos en el formulario,
y relacionar todos sus datos para que funcionen de la forma esperada. A continuación,
veremos como llevar a cabo esta tarea y aprenderemos a hacerlo posible de forma muy
rápida y sencilla.
Incrustando la tabla padre en el formulario
Nuestra primera acción, será incrustar en el formulario los datos o tabla padre, que en
nuestro caso es la formada por la tabla Socios.
Para situar los datos de la tabla Socios dentro de un formulario y en concreto como una
información de detalle, bastará con arrastrar y soltar la tabla Socios sobre el formulario
como se indica en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 525
Para presentar la información como detalle, arrastraremos la tabla Socios de
la ventana Orígenes de datos sobre el formulario Windows
Observaremos que Visual Studio, generará por nosotros un conjunto de componentes y
controles, que por defecto tendrá una apariencia similar a la que se presenta en la figura
Controles y Componentes de la tabla maestra añadidos al formulario Windows
Observe por un momento, que el campo NIF que declaramos como Label en la ventana de
Orígenes de datos, aparece como tal en el formulario, tal y como se indica en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 526
Campo NIF de la tabla, representado como un control Label en el formulario
Windows
Si ejecutamos nuestra aplicación, observaremos que esta actúa como una típica aplicación
de acceso a datos que nos permite navegar a través de los campos de la tabla Socios, tal y
como se indica en la figura
Aplicación en ejecución de la tabla de detalle incrustada en el formulario Windows
A continuación, insertaremos en el formulario la tabla Alquileres y relacionaremos ambas
tablas para que se muestren los datos relacionados, dentro del formulario Windows.
Incrustando la tabla hija en el formulario
Ya tenemos la tabla padre insertada en nuestro formulario Windows. Nuestra segunda
acción, será la de incrustar en el formulario los datos o tabla hoja, que en nuestro caso es
la formada por la tabla Alquileres, la cuál además, posee una relación entre campos con la
tabla Socios insertada anteriormente.
Para llevar a cabo esta acción arrastraremos y soltaremos la tabla Alquileres sobre el
formulario como se indica en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 527
Para presentar la información de la tabla Alquileres, arrastraremos la tabla de
la ventana Orígenes de datos sobre el formulario Windows
Como podemos observar, el entorno de trabajo ha hecho por nosotros el trabajo más
complejo para representar los datos de forma rápida y sencilla.
El esquema de datos tipados, aparecía ya en nuestro proyecto cuando asignamos el
correspondiente origen de datos. Ahora lo que ha ocurrido, es que al arrastrar y soltar
la tabla padre Socios de la ventana de Orígenes de datos, en el entorno se ha añadido un
componente de nombre MSDNVideoDataSet que es el que permitirá relacionar el DataSet
tipado con nuestros datos.
Este componente será usado por la relación maestro detalle de las dos tablas añadidas al
formulario.
En la figura, podemos ver el esquema añadido a nuestro proyecto, y el componente del
que estamos hablando.
Esquema del DataSet tipado añadido al proyecto y su componente de relación
Ejecute la aplicación y observe el comportamiento de la misma.
Observará por lo tanto, que los datos entre detalle y maestra, no están relacionados. Si
navegamos a través de los datos de detalle a través del objeto SociosBindingNavigator, el
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 528
control DataGridView no representa la relación de los datos seleccionados.
Esto es lo que se muestra en la figura.
Ejecución de la aplicación confirmando que los datos mostrados no están relacionados
A continuación, la tarea que nos queda para completar el correcto funcionamiento de
nuestra aplicación, es la de relacionar la tabla detalle y la tabla maestra entre sí, para
que los datos que se muestran en la aplicación, estén relacionados entre sí.
Relacionando la tabla padre con la tabla hija
La tarea más sencilla es la de relacionar la tabla detalle con la tabla maestra. Es una tarea
sencilla, porque Visual Studio nos proporciona las herramientas necesarias para simplificar
al máximo esta tarea.
Para llevar a cabo esta tarea, haga clic sobre el control DataGridView que corresponde
a los datos de la tabla maestra, y acceda a la ventana de Propiedades.
Dentro de la ventana de Propiedades, acceda a la propiedad DataSource como se indica
en la figura.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 529
Propiedad DataSource del control DataGridView de la información maestra
Despliegue esta propiedad, y de la lista desplegable que aparece, seleccione la
opción FK_Alquileres_Socios como se indica en la figura
Asignación de la clave de relación entre las tablas
Cuando se asigna el campo de relación de las tablas, dentro de la aplicación se añade esta
relación para que cuando naveguemos entre los datos de la tabla Socios aparezca toda la
información de la tabla Alquileres relacionada con la tabla Socios.
Esto de lo que hablamos, está supeditado por el componente
FK_Alquileres_SociosBindingSource que es lo que se indica en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 530
Controles y componentes incluido el de relación entre tablas, añadidos al formulario
Windows
Para finalizar, ejecutaremos nuestra aplicación y comprobaremos que el funcionamiento de
esta, incluida la relación entre tablas, funciona como esperábamos. En la figura, podemos
observar el comportamiento de nuestra aplicación en ejecución.
Aplicación en ejecución, mostrando la correcta relación entre las tablas
2.9.3.- Manipulando los datos maestro detalle
Obviamente, los datos maestro detalle no nos sirve únicamente para insertar las tablas de
datos en un formulario, mostrarlos y navegar por ellos. Además de esto, podemos también
manipular los datos maestro detalle, modificarlos, actualizarlos, borrarlos, sin hacer
ninguna acción adicional. El control BindingNavigator ya proporciona todas las
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 531
características necesarias para realizar estas acciones.
Podemos personalizar el control para permitir o denegar estas acciones. Además, dentro de
la ventana de Orígenes de datos, podemos seleccionar diferentes campos de las tablas y
cambiar el tipo de control en el que queremos representar sus datos. A continuación veremos
un breve ejemplo de como manipular datos para que nos sirva de aprendizaje de cómo hacer
esto posible.
Modificando datos
Ejecute la aplicación de ejemplo que hemos diseñado hasta ahora y sitúese en alguno de
sus campos. Centrándonos en la información de la tabla Socios, cambiaremos un campo
determinado, como el que se muestra en la figura
Modificaremos el valor de un campo para que nos sirva de ejemplo
Acto seguido, cuando hayamos realizado la modificación, haremos clic sobre la opción
de Guardar datos, tal y como se muestra en la figura.
Opción del control BindingNavigator para guardar los datos modificados
Como vemos, la manipulación de datos es realmente sencilla y en la relación de datos
mostrada, no tiene porqué presentarnos ninguna dificultad.
Insertando y eliminando datos
Si queremos agregar datos, deberemos hacer clic sobre la opción Agregar nuevo del
control BindingNavigator como se muestra en la figura
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 532
Añadir un registro nuevo es realmente sencillo
De la misma manera funciona el mecanismo para eliminar un registro, tal y como se
muestra en la figura
Eliminar un registro de forma Rápida
2.-10.- Vistas y ordenación de datos con la clase DataView
La clase DataView nos permite la aplicación de vistas personalizadas a partir de una tabla
contenida en un DataSet, así como la ordenación y búsqueda de filas.
Partiendo de un objeto DataTable situado en un DataSet, vamos a definir varias vistas
simultáneamente, ordenar y buscar registros, con la ventaja de que el consumo de recursos
es menor, puesto que los objetos DataView se alimentan del mismo DataTable. Para realizar
algunas pruebas, se acompaña el proyecto Vistas
El DataSet del formulario de pruebas va a estar compuesto por dos tablas. El Código
fuente muestra el evento de carga del formulario.
Private Sub Form1_Load(ByVal sender As Object, ByVal e As [Link])
Handles [Link]
' crear conexión
Dim oConexion As New SqlConnection()
[Link] = "Server=(local);" & _
"Database=Northwind;uid=sa;pwd=;"
'crear dataset
oDataSet = New DataSet()
Dim oDataAdapter As SqlDataAdapter
' crear un adaptador de datos para la tabla Customers
oDataAdapter = New SqlDataAdapter("SELECT * FROM Customers",
oConexion)
' añadir tabla al dataset con el adaptador
[Link](oDataSet, "Customers")
oDataAdapter = Nothing
' crear un adaptador de datos para la tabla Products
oDataAdapter = New SqlDataAdapter("SELECT * FROM Products",
oConexion)
' añadir tabla al dataset con el adaptador
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 533
[Link](oDataSet, "Products")
oDataAdapter = Nothing
End Sub
Vistas por código y DefaultView
Podemos crear una vista instanciando un objeto de la clase DataView, o también
obteniendo la denominada vista por defecto de una tabla de un DataSet, a través de la
propiedad DefaultView del objeto DataTable. La opción de menú Vistas + Normal del
formulario, crea dos vistas de esta manera. Ver Código fuente .
Private Sub mnuNormal_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' crear una vista por código y asignarla a un datagrid
Dim dvNormal As DataView
dvNormal = New DataView([Link]("Customers"))
[Link] = "Customers"
[Link] = dvNormal
' tomar la vista por defecto de una tabla
' del dataset y asignarla a un datagrid
[Link] = "Products"
[Link] = [Link]("Products").DefaultView
End Sub
La Figura muestra estas vistas en sendos DataGrid del formulario.
Objetos DataView creados por código y obtenido de [Link].
Filtros con objetos DataView
La propiedad RowFilter de la clase DataView nos permite asignar a este objeto, una
cadena con la expresión de filtro, que en una consulta en lenguaje SQL sería la parte
correspondiente a la partícula Where.
El Código fuente muestra el código de la opción de menú Vistas + País, del
formulario de ejemplo, en la que se crea un filtro que se muestra posteriormente en un
DataGrid.
Private Sub mnuPais_Click(ByVal sender As [Link], ByVal e As
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 534
[Link]) Handles [Link]
' crear dataview
Dim oDataView As New DataView()
[Link] = [Link]("Customers")
' establecer un filtro
[Link] = "Country='Spain'"
[Link] = "Filtrar Customers por país Spain"
[Link] = oDataView
End Sub
La Figura muestra las filas de la tabla con el filtro aplicado.
DataView con filtro.
Como hemos comentado anteriormente, a partir de un DataTable podemos obtener
varios filtros mediante distintos objetos DataView, sin que ello suponga una
penalización en el consumo de recursos. Para demostrar este punto, la opción Vistas +
Combinada, crea una vista basada en un filtro combinado, y una vista normal, ambas
empleando la misma tabla base. Veamos el Código fuente
Private Sub mnuCombinada_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' tomar la tabla Customers del dataset y aplicar...
' ...filtro combinado por dos campos y depositar en un datagrid
Dim oDataView As New DataView()
[Link] = [Link]("Customers")
[Link] = "ContactTitle LIKE '%Manager%' AND Country IN
('Spain','USA')"
[Link] = "Filtro combinado por campos ContactTitle y
Country"
[Link] = oDataView
' ...filtro por un campo y depositar en otro datagrid
Dim oDV As New DataView()
[Link] = [Link]("Customers")
[Link] = "ContactName LIKE '%an%'"
[Link] = "Filtro por campo ContactName"
[Link] = oDV
End Sub
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 535
La Figura muestra el formulario con los diversos filtros establecidos
Filtros combinados con objetos DataView.
Búsquedas con DataView
Estableciendo el adecuado filtro a un objeto DataView, podemos realizar búsquedas de
registros en tablas, como muestra el Código fuente, correspondiente a la opción de menú
Vistas + Buscar fila, del formulario de ejemplo. Deberemos previamente, haber escrito
en el TextBox del formulario, el identificador de la tabla Customers a buscar.
Private Sub mnuBuscarFila_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' crear un dataview y buscar una fila en la vista
' estableciendo un filtro
Dim oDataView As New DataView()
[Link] = [Link]("Customers")
[Link] = "CustomerID = '" & [Link] & "'"
[Link] = "Buscar ID cliente: " &
[Link]
[Link] = oDataView
End Sub
En la Figura vemos el resultado de una búsqueda, mostrado en uno de los
DataGrid del formulario.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 536
Búsqueda de una fila en una tabla de un DataSet, empleando un DataView.
Ordenación de filas mediante DataView
Para ordenar las filas en un DataView emplearemos su propiedad Sort, asignándole una
cadena con el nombre de columna/s a ordenar, tal y como muestra el Código fuente ,
de la opción de menú Ordenación + Normal, en el formulario del ejemplo.
Private Sub mnuOrdNormal_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' crear dataview y ordenar las filas con la propiedad Sort
Dim oDataView As New DataView()
[Link] = [Link]("Customers")
[Link] = "Country"
[Link] = "Ordenar por campo Country"
[Link] = oDataView
End Sub
Veamos el resultado al ejecutar en la Figura
Si necesitamos ordenar por múltiples columnas de la tabla, sólo tenemos que asignar a Sort
una cadena con la lista de columnas requeridas. Ver Código fuente .
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 537
DataView ordenando las filas por la columna Country.
[Link] = "Country, PostalCode"
También es factible asignar a un DataView una combinación de filtro y ordenación,
utilizando en la misma operación las propiedades RowFilter y Sort. El menú del
formulario Ordenación + Con filtro realiza este trabajo, que vemos en el Código fuente .
Private Sub mnuOrdenFiltro_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
Dim oDataView As New DataView()
[Link] = [Link]("Customers")
' establecer un filtro al dataview
[Link] = "Country='USA'"
' ordenar las filas del filtro
[Link] = "City"
[Link] = "Filtrar por USA. Ordenar por campo City"
[Link] = oDataView
End Sub
Los datos con el filtro y orden podemos verlos en el DataGrid del formulario, que
muestra la Figura .
Resultado de DataView con filtro y orden.
2.11.-Obtener el esquema de un DataSet
El esquema de un DataSet consiste en toda la información contenida por este objeto,
acerca de los nombres de tablas, columnas, relaciones, etc.; es decir, se trata de
metainformación sobre los datos que contiene el DataSet.
Podemos obtener estos metadatos del DataSet recorriendo la colección que nos interese en
cada caso: Tables, Columns, etc. El Código fuente muestra como tras crear un DataSet,
recorremos sus tablas, y dentro de estas, sus columnas, mostrando la información obtenida
en un ListBox.
Private Sub btnEsquema_Click(ByVal sender As [Link], ByVal e As
[Link]) Handles [Link]
' crear conexión
Dim oConexion As New SqlConnection()
[Link] = "Server=(local);" & _
"Database=Northwind;uid=sa;pwd=;"
' crear dataset
Dim oDataSet As New DataSet()
' crear adaptadores de datos para las tablas
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 538
' y añadir cada tabla al dataset con el adaptador
Dim oDataAdapter As SqlDataAdapter
oDataAdapter = New SqlDataAdapter("SELECT * FROM Customers",
oConexion)
[Link](oDataSet, "Customers")
oDataAdapter = Nothing
oDataAdapter = New SqlDataAdapter("SELECT * FROM Orders", oConexion)
[Link](oDataSet, "Orders")
oDataAdapter = Nothing
oDataAdapter = New SqlDataAdapter("SELECT * FROM Products",
oConexion)
[Link](oDataSet, "Products")
oDataAdapter = Nothing
oDataAdapter = New SqlDataAdapter("SELECT * FROM Territories",
oConexion)
[Link](oDataSet, "Territories")
oDataAdapter = Nothing
' crear un objeto tabla y columna para mostrar
' la información del esquema que el dataset contiene
Dim oDataTable As DataTable
Dim oDataColumn As DataColumn
[Link]("Estructura del DataSet")
' recorrer la colección de tablas del DataSet
For Each oDataTable In [Link]
[Link]("Tabla: " & [Link])
Next
' recorrer la colección de columnas de la tabla
For Each oDataColumn In [Link]
[Link]("Campo: " & _
[Link] & " --- " & _
"Tipo: " & [Link])
Next
End Sub
La Figura muestra el ListBox relleno con el esquema del DataSet tras haber pulsado el
botón del formulario.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 539
Obtención del esquema de un DataSet.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 540
Adendum
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 541
PASOS PARA CREAR UN ORIGEN DE DATOS TIPO SDF EN VISUAL
[Link]
1.-Ventana Explorador de proyecto – boton derecho-> agregar->componente
Paso 2.-
Seleccionar base de datos local, si desea cambiar el nombre de la base local puede hacerlo
En este momento, al base local se guardara donde está ubicado la aplicación.
Paso 3.- Seleccionar conjunto de datos -> siguiente
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 542
Paso 4.-
La pantalla envía un mensaje es nueva y que no contiene objetos, por lo tanto solo crea “el
cascaron” de la base de datos, finalizar
Ahora crearemos las tablas que usaremos en la aplicación:
En la barra de menú seleccione ver-> exploradores de servidores, seleccione la base de
datos
De trabajo, seleccione tabla botón derecho-> crear tabla
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 543
Aparecerá algo asi:
Llena los campos nombre de la tabla, nombre de columna, tipo de dato longitud, etc
Por cada uno de los campos de la tabla de trabajo
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 544
Para terminar le da aceptar y listo, ahora solo tenemos que introducir datos a la tabla.
Se va explorador de servidores, se ubica en la tabla, botón derecho-> mostrar datos de tabla
Si la tabla contiene registros estos se verán:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 545
Si la tabla no tiene registros se verá así:
Entonces procedemos agregar registros…
Ahora procederemos a agregar nuestra tabla en la aplicación:
Barra de menú-> orígenes de datos-> agregar nuevo origen de datos
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 546
Seleccionamos la tabla y la arrastramos al form de trabajo,
Esto crea automáticamente un datagridview con los registros de la tabla y una barra de
navegación de los mismos, observe los componentes que se agregan por defecto a la
aplicación.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 547
En la corrida se miraría asi:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 548
Acceso a datos *.mdf con Visual [Link]
REQUISITOS A TENER INSTALADO EN SU COMPUTADOR:
Vamos a trabajar por pasos el primero paso por supuesto es abrir VISUAL [Link].
Justo en esa imagen pueden ver como yo estoy agregando un nuevo proyecto seleccionen
Aplicacion de Windows Form y le colocan un nombre en mi caso yo le coloque
“Accesoadatos” ustedes le pueden colocar el nombre que quieran
Ya al tener este paso cumplido vamos a observar que no queda una pantalla donde diseñar
nuestro sistema con una pantalla principal llamada Form1:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 549
Vamos a ir al Explorador de soluciones que es donde se van a encontrar todos los elementos
de tu proyecto de programación para abrir el explorador de soluciones lo puedes encontrar
del lado derecho o si no esta activo puedes ir al MENU ver y activas la que dice Explorador
de Objetos. A lo que lo tengan activo van a presionar click derecho sobre el nombre de su
solución en mi caso fue “Accesoadatos” (presiono click derecho) y selecciono Agregar
Nuevo elemento (Add New ítem).
En la lista que aparece para agregar nuevos elementos a nuestro proyecto debemos
seleccionar el objeto Base de datos basada en servicio para poder tener una base de datos
donde almacenar y funcionar bajo windows la otra opción muy parecida se utiliza para base
de datos para aplicaciones Móviles.. por eso no seleccionamos bases de datos local, debes
cuidar que la extensión del archivo que agregas a la solución es .MDF así estarás mas seguro
cambia el nombre de la base de datos a tu gusto en mi caso le coloque [Link] aquí
pueden ver el ejemplo en pantalla:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 550
Al dar click al botón agregar va a realizar unos procesos y va a aparecer un asistente para
base de datos al cual debes darle aceptar de lo contrario ese asistente creara un Dataset
Tipado propio y lo ideal es que tu sepas como agregarlo manualmente.
Una vez que ya nuestra base de datos esta creada procedemos a darle desde el explorador
de objetos dos veces click a la base de datos para poder visualizar del lado izquierdo el
Explorador de base de datos muy importante para crear nuestras tablas y procedimientos
te fijaras que hay una parte que dice TABLAS presionando click derecho y seleccionar
agregar nueva Tabla lo puedes ver en la siguiente imagen:
Al presionar podemos agregar los campos que tendrá nuestra tabla para hacerlo mas
sencillo vamos a agrega solo tres campos de manera que expliquemos hoy como agregar
un elemento y como mostrar los datos de la tabla. Los Campos será Cedula que sera un
campo clave, nombre y apellido. Ninguno va a permitir valores nulo la cedula será de tipo
numérico y nombre y apellido nvarchar(50). Lo pueden ver en la imagen:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 551
Solo queda presionar salir y te pedirá que guardes la tabla con el nombre que tu quieras en
mi caso le coloque alumnos, ahora procedemos a agregar unos datos de ejemplo a nuestra
tabla asi como agregamos nueva tabla: le van a dar click derecho al nombre de la tabla que
acaban de agregar y le dan a la Opcion Mostrar datos de tabla hay podrán agregar algunos
datos de ejemplo.
Solo queda presionar guardar y ahora es hora de diseñar el formulario para poder dar el
ejemplo solamente se usaran los siguientes controles: Un Datagridview para mostrar los
datos tres Botones uno para guardar otro para cargar los datos y otro para salir del sistema,
tres textbox para agregar los tres datos de la base de datos de ejemplo y tres controles
label para identificar a que dato corresponde cada textbox. Para ello debemos hacer uso
del cuadro de herramientas para agregar los controles al formulario se puede ver del lado
izquierdo y si no esta activo pueden ir al pestaña menú Ver y activar Cuadro de
herramientas.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 552
Aquí como puede observar ya he agregado los controles, les recuerdo que .NET es
Orientado a objetos y todo objeto tiene sus propiedades estados y métodos., por ellos es
importante saber con que propiedades vamos a trabajar la mayoría de los controles
encontramos en sus propiedades valga la redundancia la propiedad TEXT y la propiedad
NAME, text en el nombre que se va a visualizar y NAME el nombre como se reconocerá
programáticamente ese objeto las propiedades las podemos observar del lado Derecho al
momento de seleccionar uno o varios objetos si no salen puedes ir al menu ver y activas
ventana propiedades.
si pueden observar modifique la propiedad TEXT de los label para identificar que dato va en
cada textbox y los nombres de cada botón ahora vienen haciendo a la propiedad name que
no va a producir ningún cambio solo lo verán mas adelante como ejemplo deben saber que
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 553
cada control tiene un nombre clave para saber que tipo es por ejemplo los Label llevan LBL
los textbox llevan TXT y los botones CMD si quiero identificar los tres botones y los tres
textbox programáticamente modifico la propiedad name de cada uno y usaría TXTcedula,
TXTnombre. TXTapellido, CMDguardar, CMDsalir, CMDcargar y aun falta el datagrid yo
personalmente le coloco DGW es decir en este caso le colocaría DGWdatos. de esta manera
estarán organizados los nombres programáticamente y mas adelante verán la importancia
de hacer esto.
Ahora toca agregar un sistemas de tipos a nuestro proyecto al igual que agregamos la base
de datos vamos a presionar en el Explorador de soluciones click derecho sobre el nombre
de nuestro proyecto y agregar un nuevo elemento, es este caso debemos agregar un
conjunto de datos que tiene extensión .XSD por nombre yo le coloque DSprueba ustedes le
colocar el nombre que ustedes quieran una vez que agregamos su nombre le damos
agregar:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 554
Una vez que agregamos aparecerá una pantalla de fondo celeste con el siguiente mensaje:
Utilice el diseñador de base de datos para trabajar con un conjunto de tablas con tipo
Solo queda arrastrar la tabla que creamos a ese diseñador de datos con tipo:
Una vez agregada nos aparecerá la tabla con sus campos y en la parte de abajo métodos
para buscar esos datos donde a este vamos a agregar dos consultas de las cuales una ya la
tiene por defecto y la otra es para guardar los datos es decir vamos a usar sentencias
TRANSAC SQL para insert y para select. quiza te sea un poco extraño esto pero poco a poco
te vas acostumbrando solo es cosa de practicar querer aprender y no tenerle miedo , el
método que se agrega por defecto se llama FILL,Getdata a este método le vamos presionar
click derecho y le damos a la opcion agregar consulta,
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 555
Al presionar esta opción tendremos un asistente que nos ayudara con esto del transact SQL
que ya les voy a explicar.. la primera opción que sale es que si queremos crear un sentencia
SQL, un procedimiento almacenado y un procedimiento almacenado ya existente por
experiencia es mejor usar procedimientos almacenados los invito a que investigues sobre
ellos son recomendados en las buenas practicas de programación y acceso a datos en si
todos vamos a elegir la segunda opción y nos saldrá entonces la siguiente pantalla:
donde podrán ver que la primera opción es un select que devuelve una fila en este caso es
si quieres el valor de una o varias filas dependiendo del dato que desees por ejemplo dame
el dato donde la cedula sea tal, en este ejemplo solo obtendrás un resultado por que es
imposible hayan dos personas con el mismo numero de cedula pero si fuera apellido si es
posible tener mas de dos resultados esta es la que usaremos pero ya por defecto ya esta
realizado, en el segundo caso es un Select que devuelve un solo valor: en esta opción
podrán obtener resultados como cuantos registros tienen en su tabla hacer una suma de
una columna que contenga valores como sueldos entre otras esta no la usaremos en este
caso.
El tercer caso es un UPDATE se utiliza para actualizar datos de un registro que ya existe es
decir la función MODIFICAR, para el cuarto se trata de un DELETE lógicamente se utiliza
para eliminar registros de la tabla y por ultimo un INSERT es lo mismo que guardar datos y
es el que utilizaremos para darle función al botón guardar así que este es el que vamos a
seleccionar y visualizaras luego la siguiente pantalla:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 556
Esta es la consulta o TRANSAC SQL si no estás de acuerdo con lo que el asistente hizo puedes
modificarlo y personalizarlo presionando GENERADOR DE CONSULTAS. En otra ocasión
explico más profundamente esta parte al presionar generador de consulta le dan aceptar
para mejorar esa consulta sql que debe quedar de esta forma para los datos que trabajo y
nombre de la tabla
INSERT INTO Alumnos
(Cedula, Nombre, Apellido)
VALUES (@Cedula,@Nombre,@Apellido)
Si aparece algo mas luego de presionar aceptar sobre el generador de consulta bórrenlo y
deje solo esto que les coloque normalmente se agrega algo como esto
SELECT Cedula, Nombre, Apellido FROM Alumnos WHERE (Cedula = @Cedula)
Y se utiliza para que luego de agregar los datos llamarlos de una vez pero en este caso no lo
vamos a usar.
Luego de presionar en siguiente solo les pedirá el nombre del procedimiento almacenado y
el nombre de la función ya listo ya tenemos nuestro diseñador de dataset con dos funciones
una que se agregó por defecto llama da fill,GET y la segunda agregada por nosotros para
guardar datos llamada en mi caso le coloque como nombre INSERALUM ustedes pueden
colocarle el que quiera pero este nombre lo utilizaremos más adelante. Así nos debe quedar
nuestro dataset en el diseñador.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 557
Ahora toca agregar código a los botones lo primero que haremos es agregar código al botón
guardar le daremos dos veces click para ir al evento click de ese botón así a lo que
presionemos click se ejecutara el código que le coloquemos, Debemos aprender como
llamar a los datos de un Dataset Tipados Básicamente hay que hacer dos instanciar de
nuevo programación orientada a objetos estos datos estas almacenados en unas clases que
crea visual studio debemos llamar a esas clases para que nos permita trabajar con los
métodos insertalum y FILL para ellos se agrega el siguiente código:
Dim ds As New [Link]
Dim dt As [Link]
Quiza lo puedan ver mejor desde la imagen:
se declararon dos variables ds y dt dt es la que usaremos para acceder al método inseralumn
agregando el código
[Link]([Link], [Link], [Link])
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 558
en la imagen notamos como a agregar el código [Link]( nos ayuda a ver que valores
debemos agregar pidiéndonos cedula, nombre y apellido, hay es donde se justifica el por
que agregar nombre programático a cada text box ya con solo hacer esto el botón guardar
funciona vamos a agrega el método fill al botón cargar debemos hacer lo mismo si
queremos lo que hacemos es sacar las primeras dos líneas de código para que funcione
generalmente para cualquier botón así solo agregamos el siguiente código presionando dos
veces click en el botón cargar.
[Link]([Link])
[Link] = [Link]
De esta manera al presionar sobre el botón cargar el datagrid se llenara de los datos de la
tabla alumnos solo falta el botón salir presiona dos veces click y escribe el código
End
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 559
USO DEL CONTROL DATAGRIDVIEW [Link]
Caracteristicas:
Permite visualizar datos en una cuadricula personalizable.
Manipulación (operaciones)
Modificación (cambiar, guardar) de datos procedentes de una base de datos (tablas) tales
como consultas vistas etc.
También datos ingresados en tiempo de ejecución, o por el código directamente.
En este caso les presentamos en tiempo de ejecución.
PROPIEDADES MÁS USADOS DEL CONTROL:
Las propiedades de este control aparecen como los demás en la ventana de propiedades.
Las propiedades de las columnas son diferentes a las del control, a ellas se tiene acceso por
medio de la flecha desplegable que aparece en la parte derecha de la cuadricula, de la cual se
despliega un cuadro con las opciones de AGREGAR COLUMNAS y EDITAR
COLUMNAS
AGREGAR COLUMNAS: Nos permite adicionar la cantidad de columnas que se
considere necesarias para el proyecto. La propiedad NAME de las columnas aparece por
defecto como culmn1, column2, column3…, columnn etc.
EDITAR COLUMNAS: Nos permite agregar título a cada una de las columnas.
PROPIEDAD HEADER TEXT= texto, si no se requiere titulo en la columna se pone la
propiedad en blanco.
EJEMPLO 1: CALCULAR SUMA, RESTA MULTIPLICACION Y PROMEDIO
Para este ejemplo crear un formulario llamado: operaciones DataGridView, y agregar los
siguientes controles:
Dos buttons. 1)- Propiedad texto = AGREGAR VALORES A LA MATRIZ.
2)-Propiedad Texto = EJECUTAR OPERACIONES
Dos textbox con la propiedad name = por defecto.
Dos Label, 1)-Name = por defecto, texto = SUMA TOTAL.
2)- Name=por defecto, texto = PROMEDIO TOTAL.
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 560
Un DataGridView con la propiedad name = por defecto.
Haz click aquí para cambiar el nombre de las columnas y el tamaño…..
Diseño autosizemode esto te dara el tamaño de la columnaAgregar al DataGridView 10
columnas de las cuales su nombre serán por defecto y su texto = así
Header text =
Header text=
Header text =
Header text =
Header text =
Header text =
Header text = SUMA
Header text = PROMEDIO
Header text = RESTA
Header text = MULTIPLICACION
Haz click aquí para cambiar el nombre de las columnas y el tamaño…..
Diseño autosizemode esto te dara el tamaño de la columna
DISEÑO DE FORMULARIO:
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 561
CODIGO:
Public Class Form1
'Declaracion de la matriz'
Dim M(5, 5) As Integer
Dim sumatotal As Integer
Dim promediototal As Double
Private Sub Form1_Load(ByVal sender As [Link], ByVal e As -
[Link]) Handles [Link]
'Declaracion de la matriz contenida en el datagridview1'
‘ asignamos los valores de 0 a cada campo
[Link] = 6
For i As Integer = 0 To 5
For j As Integer = 0 To 5
M(i, j) = 0 ‘ primero a la matriz que declaramos
[Link](i, j).Value = M(i, j) ‘ Igual al data gridView1
Next
Next
End Sub
‘LLENAMOS LA MATRIZ DE FORMA INTERACTIVAS (LO HACE EL USUARIO)'
Private Sub btnAgregar_Click(ByVal sender As [Link], ByVal e As -
[Link]) Handles [Link]
Try
For i As Integer = 0 To 5
For j As Integer = 0 To 5
M(i, j) = CInt(InputBox("digite el valor"))
[Link](j, i).Value = M(i, j)
Next
Next
MsgBox("llena")
Catch ex As Exception
MsgBox([Link])
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 562
End Try
End Sub
‘ CON LOS DATOS OBTENIDOS EJECUTAMOS LAS OPERACIONES
Private Sub btnejecutar_Click(ByVal sender As [Link], ByVal e As -
[Link]) Handles [Link]
Try
'suma fila 0'
Dim suma = 0
For i = 0 To 5
suma = suma + M(0, i)
Next
[Link](6, 0).Value = suma
'promedio fila 0'
Dim promedio As Double
promedio = suma / 6
[Link](7, 0).Value = promedio
'resta fila 0'
Dim resta As Integer
resta = suma - promedio
[Link](8, 0).Value = resta
'multiplicacion fila 0'
Dim multiplicacion As Integer
multiplicacion = promedio * resta
[Link](9, 0).Value = multiplicacion
'suma fila1'
Dim suma1 = 0
For i = 0 To 5
suma1 = suma1 + M(1, i)
Next
[Link](6, 1).Value = suma1
'promedio fila 1'
Dim promedio1 As Double
promedio1 = suma1 / 6
[Link](7, 1).Value = promedio1
'resta fila 1'
Dim resta1 As Integer
resta1 = suma1 - promedio1
[Link](8, 1).Value = resta1
'multiplicacion fila 1
Dim multiplicacion1 As Integer
multiplicacion1 = promedio1 * resta1
[Link](9, 1).Value = multiplicacion1
'suma fila 2'
Dim suma2 = 0
For i = 0 To 5
suma2 = suma2 + M(2, i)
Next
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 563
[Link](6, 2).Value = suma2
'promedio fila 2'
Dim promedio2 As Double
promedio2 = suma2 / 6
[Link](7, 2).Value = promedio2
'resta fila 2'
Dim resta2 As Integer
resta2 = suma2 - promedio2
[Link](8, 2).Value = resta2
'multiplicacion fila 2'
Dim multiplicacion2 As Integer
multiplicacion2 = promedio2 * resta2
[Link](9, 2).Value = multiplicacion2
'suma fila 3'
Dim suma3 = 0
For i = 0 To 5
suma3 = suma3 + M(3, i)
Next
[Link](6, 3).Value = suma3
'promedio fila 3'
Dim promedio3 As Double
promedio3 = suma3 / 6
[Link](7, 3).Value = promedio3
'resta fila 3'
Dim resta3 As Integer
resta3 = suma3 - promedio3
[Link](8, 3).Value = resta3
'multiplicacion fila 3'
Dim multiplicacion3 As Integer
multiplicacion3 = promedio3 * resta3
[Link](9, 3).Value = multiplicacion3
'suma fila 4'
Dim suma4 = 0
For i = 0 To 5
suma4 = suma4 + M(4, i)
Next
[Link](6, 4).Value = suma4
'promedio fila 4'
Dim promedio4 As Double
promedio4 = suma4 / 6
[Link](7, 4).Value = promedio4
'resta fila 4'
Dim resta4 As Integer
resta4 = suma4 - promedio4
[Link](8, 4).Value = resta4
'multiplicacion fila 4'
Dim multiplicacion4 As Integer
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 564
multiplicacion4 = promedio4 * resta4
[Link](9, 4).Value = multiplicacion4
'suma fila 5'
Dim suma5 = 0
For i = 0 To 5
suma5 = suma5 + M(5, i)
Next
[Link](6, 5).Value = suma5
'promedio fila 5'
Dim promedio5 As Double
promedio5 = suma5 / 6
[Link](7, 5).Value = promedio5
'resta fila 5'
Dim resta5 As Integer
resta5 = suma5 - promedio5
[Link](8, 5).Value = resta5
'multiplicacion fila 5'
Dim multiplicacion5 As Integer
multiplicacion5 = promedio5 * resta5
[Link](9, 5).Value = multiplicacion5
'sumatoria de la columna de SUMA'
sumatotal = Val(suma + suma1 + suma2 + suma3 + suma4 + suma5)
'guardar en textbox la sumatoria total'
[Link] = sumatotal
'Promedio total de la columna promedio'
promediototal = Val(promedio + promedio1 + promedio2 + promedio3 + promedio4 +
promedio5)
'guardar en textbox el promedio total'
[Link] = promediototal / 6
Catch ex As Exception
MsgBox([Link])
End Try
End Sub
End Class
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 565
Buscar fila en DataGridView
Buscar un registro o fila en un control de tipo DataGridView
Código de ejemplo que usa el método Find del componente BindingSource para buscar un
registro en un campo específico en una tabla
formulario
Controles
Un control DataGridView llamado DataGridView1
Un control Button llamado Button1 ( botón para buscar )
Un control textBox llamado textBox1 ( para ingresar el dato )
Indicar el campo por el cual buscar ( Primer parámetro del método Find)
Establecer la cadena de conexión a utilizar
Código fuente
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 566
Option Explicit On
Option Strict On
Imports [Link]
Imports [Link]
Public Class Form1
' ConnectionString para SQL server EXPRESS
Private Const cs As String = "Data Source=(local)\SQLEXPRESS;" & _
"Integrated Security=True;" & _
"Initial Catalog=la_base_de_datos"
'Declarar un BindingSource
Private BindingSource1 As [Link] = New BindingSource
Private Sub Form1_FormClosed( _
ByVal sender As Object, _
ByVal e As [Link]) Handles [Link]
[Link]()
End Sub
Private Sub Form1_Load( _
ByVal sender As [Link], _
ByVal e As [Link]) Handles [Link]
[Link] = "Buscar fila"
Try
' Declarar la conexión y abrir
Using cn As SqlConnection = New SqlConnection(cs)
[Link]()
' Crear un DataAdapter y pasarle el comando para traer los registros
Dim da As New SqlDataAdapter("SELECT * FROM la_tabla", cn)
' DataTable
Dim dt As New DataTable
' llenar el DataTable
[Link](dt)
' enlazar el DataTable al BindingSource
[Link] = dt
' propiedades para el DataGridview
'''''''''''''''''''''''''''''''''''''''
With DataGridView1
' opcional: Sin selección múltiple
.MultiSelect = False
' seleccioanr fila completa al hacer clic en un registro
.SelectionMode = [Link]
' enlazar los controles
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 567
.DataSource = [Link]
End With
End Using
' errores
Catch ex As Exception
MsgBox([Link])
End Try
End Sub
' Función que retorna el índice de la fila
'' ''''''''''''''''''''''''''''''''''''''''''''''''''''
Function Buscar( _
ByVal Columna As String, _
ByVal texto As String, _
ByVal BindingSource As BindingSource) As Integer
Try
' si está vacio salir y no retornar nada
If [Link] Is Nothing Then
Return -1
End If
' Ejecutar el método Find pasándole los datos
Dim fila As Integer = [Link]([Link], texto)
' Mover el cursor a la fila obtenida
[Link] = fila
' retornar el valor
Return fila
' errores
Catch ex As Exception
MsgBox([Link], [Link])
End Try
' no retornar nada
Return -1
End Function
' Botón para buscar en el DataGridView
Private Sub Button1_Click( _
ByVal sender As [Link], _
ByVal e As [Link]) Handles [Link]
' Pasar el nombre del campo por el cual buscar ,
' el dato, y el BindingSource enlazado al DataGridView
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 568
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim ret As Integer = Buscar( _
"Nombre", _
[Link], _
BindingSource1)
' si no se encontró ....
If ret = -1 Then
' mostrar un mensaje
MsgBox("No se encontró la fila", [Link])
Else
With DataGridView1
' volver a enlazar
.DataSource = BindingSource1
' Pasarle el índice para Visualizar la fila al comienzo de la grilla
.FirstDisplayedScrollingRowIndex = ret
End With
End If
End Sub
End Class
Buscar usando el método find de la propiedad DefaultView
Código similar al anterior , pero que usa el método Find de la propiedad Defaultview de un
Dataset accediendo a la base de datos mediante OLEDB
( Button1 , dataGridView1 y TextBox1)
Nota: indicar la cadena de conexión, el comando sql en el oledbdataAdapter y también el
nombre del campo por el cual buscar, en la propiedad Sort
Option Explicit On
' Espacio de nombres para para acceder al proveedor OleDb
Imports [Link]
Public Class Form1
' declaración del ConnectionString
Private Const cadena_conexion As String = "Indicar la cadena"
' declaración del dataset
Private oledb_dataset As DataSet
Private Sub Form1_Load( _
ByVal sender As [Link], _
ByVal e As [Link]) Handles [Link]
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 569
[Link] = "Buscar"
[Link] = [Link]
'Configurarar propiedades para el DataGridView
With DataGridView1
.MultiSelect = False
.SelectionMode = [Link]
End With
Try
' Inicializar nueva conexión OLEDB y abrirla
Using cn As New OleDbConnection(cadena_conexion)
[Link]()
' Inicializar nuevo adaptador de datos OleDb
Dim da As New OleDbDataAdapter("Select * From una Tabla", cn)
' Crear y cargar el DataSet
oledb_dataset = New DataSet
[Link](oledb_dataset, "Mi Tabla")
With oledb_dataset.Tables("Mi Tabla")
' Indicar en la propiedad Sort el campo por el cual buscar
.[Link] = "Clientes"
' asignar el origen de datos a la grilla
[Link] = .DefaultView
End With
End Using
Catch ex As Exception
MsgBox([Link])
Finally
[Link] = [Link]
End Try
End Sub
Private Sub Button1_Click( _
ByVal sender As [Link], _
ByVal e As [Link]) Handles [Link]
' buscar y retornar el índice de la fila encontrada
Dim fila As Integer = oledb_dataset.Tables("Mi tabla").[Link](Text
[Link])
' si el índice es -1 no se encontró
If fila <> -1 Then
With DataGridView1
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 570
' Establecer el índice de la primera fila del DataGridview
' para visualziarlo arriba de todo
.FirstDisplayedScrollingRowIndex = fila
' asignar la celda al CurrentCell para seleccionarla
.CurrentCell = .Rows(fila).Cells(0)
' seleccionar el control
.Select()
'mostrar el índice en el caption del formulario
[Link] = "índice de la fila actual : " & .[Link]
End With
Else
' No se encontró
MsgBox("No se encontró el elemento en el DataGridView")
End If
End Sub
End Class
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 571
Ejemplo de programa de uso de clase en Visual Basic NET
Ejemplo Calcular el salario de los empleados de una tienda, información a sacar por pantalla
Nombre del empleado y Salario semanal, datos conocidos: nombre, número de horas trabajadas
y pago por hora del empleado
El salario se calcula de la manera siguiente:
Si el número de horas trabajadas es mayor que 40, el excedente de 40 se paga al doble de la
cuota por hora, en caso de no ser mayor que 40 se paga a la cuota por hora normal.
Realicemos la solución de acuerdo al modelo-vista-controlador
Algoritmo Calcular Salario de un empleado
Public Class Empleado
Algoritmo Calcular Salario de un empleado
'Declaraciones de Datos
Private NombreEmpleado As String
Clase Empleado
Private HorasTrabajadas As Integer
1.- Declaraciones
Private PagoHora As Double
Datos
Private Salario As Double
NombreEmpleado: Cadena
HorasTrabajadas: Entero
Public ReadOnly Property obtenerNombre()
PagoHora: Real
As String
Salario: Real
' bloque Get obtener para devolver el
valor de la propiedad
2.- Metodo EstablecerNombre( nom: cadena)
Get
NombreEmpleado = nom
Return NombreEmpleado
Fin Metodo EstablecerNombre
End Get
End Property
3.- Metodo Establecerhoras(horas: Entero)
HorasTrabajadas = horas
Public WriteOnly Property establecerNombre()
Fin Metodo EstablecerHoras
As String
' bloque Set (Establecer) para asignar
4.- Metodo EstablecerPago( pago: Real)
valor a la propiedad
PagoHora = pago
Set(ByVal Value As String)
Fin Metodo EstablecerPago
NombreEmpleado = Value
End Set
5.-Metodo CalcularSalario( )
End Property
If HorasTrabajadas<= 40 Then
Salario = HorasTrabajadas * PagoHora
Public ReadOnly Property obtenerHoras() As
Else
Integer
Salario= (40*PagoHora)+
' bloque Get para devolver el valor de la
(( HorasTrabajadas -40) *( PagoHora * 2))
propiedad
Endif
Get
Fin Metodo EstablecerNombre
Return HorasTrabajadas
End Get
6.- Metodo ObtenerNombre() : Cadena
End Property
Return NombreEmpleado
Fin Metodo ObtenerNombre
Public WriteOnly Property EstablecerHoras()
As Integer
7.- Metodo ObtenerSalario( ) : Real
' bloque Set para establecer valor a la
Return Salario
propiedad
Fin Metodo ObtenerSalario
Set(ByVal hora As Integer)
HorasTrabajadas = hora
Fin de clase empleado End Set
MSc. Ing. Jorge Prado D. Docente: EndNacional
Universidad Property de Ingeniería 572
Diseño en Visual Basic
Public WriteOnly Property EstablecerPago() As
Double
' bloque Get para devolver el valor de la
propiedad
Set(ByVal value As Double)
PagoHora = value
End Set
End Property
Public ReadOnly Property ObtenerPagoHora()
As Double
' bloque Set para estsblecer el valor a la
propiedad
Get
Return PagoHora
End Get
End Property
Public Sub CalcularSalario()
' en este método calculamos el salario del
empleado
If HorasTrabajadas <= 40 Then
Salario = HorasTrabajadas * PagoHora
Else
Salario = (40 * PagoHora) +
((HorasTrabajadas - 40) * (PagoHora * 2))
End If
End Sub
Public ReadOnly Property ObtenerSalario()
As Double
Get
Return Salario
End Get
End Property
End Class
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 573
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 574
Algoritmo y programa OO usando selección múltiple en Visual Basic NET
Ejercicio: Elaborar un algoritmo que dado un numero del 1 al 7, el programa imprima
por pantalla “Domingo ”,si es 1, “Lunes”, si es 2… “Sábado”, si es 7.
Solución:
Algoritmo PresentaDia de la semana Public Class PresentaDia
Clase PresentaDia REM Declaraciones de Datos
Declaraciones Private INumDia As Integer
Datos Public SNombreDia As String
NumDia : Entero ' Metodo obtener nombreDia de solo
NombreDia : Cadena escritura
ReadOnly Property Nombre() As String
Metodo EstablecerNDia( num: Entero) Get
NumDia = Num Nombre = SNombreDia
Fin de método EstablecerDia End Get
Metodo CalcularNombredia() End Property
Swith NumDia
1: Nombredia = “Domingo” 'Metodo establecer Numero del Dia
2: Nombredia = “Lunes” solo lectura
3: Nombredia = “Martes” WriteOnly Property Dia() As Integer
4: Nombredia = “Miércoles” Set(ByVal value As Integer)
5: Nombredia = “Jueves” INumDia = value
6: Nombredia = “Viernes” End Set
7: Nombredia = “Sábado” End Property
DEFAULT
NombreDia = “No está en el rango de 1 a 7 “ ' Metodo CalcularNombredia()
ENDSWITCH Public Sub CalcularDia()
Fin Metodo CalcularNombreDia Select Case (INumDia)
Metodo ObtenerNombreDia() : Cadena Case 1
Return NombreDia SNombreDia = "Domingo"
Fin Metodo ObtenerDia Case 2
SNombreDia = "Lunes"
Fin clase PresentaDia Case 3
SNombreDia = "Martes"
Case 4
SNombreDia = "Miercoles"
Case 5
SNombreDia = "Jueves"
Case 6
SNombreDia = "Viernes"
Case 7
SNombreDia = "Sabado"
Case Else
SNombreDia = "No existe ese dia"
End Select
End Sub
End Class
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 575
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 576
Algoritmo y programa OO usando Estructura de repetición DO…WHILE en
Visual Basic NET
Ejemplo: Elaborar un algoritmo para calcular e imprimir el sueldo de varios empleado
de una empresa.
Datos disponibles: Nombre, Horas Trabajadas, Cuota por Hora
Proceso: Sueldo = Horas Trabajadas * cuota por Hora
Imprimir: Nombre, Sueldo.
Solución:
Clase Empleado Public Class Empleado
Declaraciones Private NombreE As String
Datos Public Property Nombre() As
NombreE : Cadena String
HorasT : Entero Get
PagoH : Real Nombre = NombreE
Sueldo : Real End Get
Set(ByVal valor As String)
Metodo EstablecerNombreE(nom : Cadena) NombreE = valor
NombreE = nom End Set
Fin método EstablecerNombreE End Property
Metodo EstablecerHorasT (Horas : Enterol) Private HorasT As Double
HorasT = Horas Public Property Horas() As String
Fin de método EstablecerHorasT. Get
Horas = HorasT
Metodo EstablecerPagoH( Pago : Real) End Get
PagoH = Pago Set(ByVal valor As String)
Fin Metodo EstablecerPagoH HorasT = valor
End Set
End Property
Metodo CacularSueldo()
Sueldo = HorasT * PagoH
Private PagoH As Double
Fin método CalcularSueldo
Public Property Pago() As String
Get
Metodo ObtenerNombreE(): Cadena
Pago = PagoH
Return NombreE
End Get
Fin Metoddo ObtenerNombreE
Set(ByVal valor As String)
PagoH = valor
Metodo ObtenerSueldo() : Real End Set
Return Sueldo End Property
[Link]. JorgeObtenerSueldo
método Prado D. Docente: Universidad Nacional de Ingeniería 577
Private Sueldo As Double
Fin Clase Empleado ReadOnly Property Salario() As
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 578
Algoritmo y programa OO usando arreglos unidimensionales en Visual Basic
NET
Ejercicio:
Se conoce el número de unidades producidas por un obrero en cada uno de los 30 días
del mes. Elaborar un algoritmo que permita leer la producción de cada uno de los 30 días
y luego los visualice.
Clase Obrero
1.- Declaraciones
Datos
Producción: Arreglo[30] : Entero
2.- Método establecerProduccion(pro[]:
Entero)
Producción = pro
Fin método establecerProduccion
3.- Metodo obtenerProduccion():
Arreglo[] Entero
Return producción
Fin método obtenerProduccion
Fin Clase Obrero
Clase Ejecutaobrero
1.- Metodo principal
Declaraciones
MSc. [Link]
Jorge Prado D. Docente: Universidad Nacional de Ingeniería 579
Prod, prod2:arreglo[30] Entero
I : Entero
Algoritmo y programa OO usando herencia en Visual Basic NET
Ejercicio:
En cierta empresa se tienen empleados; los empleados se dividen en dos tipos, empleados
por hora, a los que se les paga de acuerdo con el número de horas trabajadas y a una
cuota por hora. El otro tipo son los empleados asalariados, a quienes se les paga de
acuerdo a un sueldo fijo mensual.
Clase empleado
Declaraciones: Datos
# nombreEmpleado : cadena
# deptoEmple : cadena
# puestoTrabajo: cadena
Método establecerNombre(nom : cadena)
nombreEmpleado = nom
Fin método establecerNombre
Método establecerDepto(dep: cadena)
depatoEmple = dep
Fin de método establecerDepto
Método establecerPuesto(pues : cadena)
puestoTrabajo = pue
fin método establecerPuesto
[Link]
Ing. Jorge Prado D.
obtenerNombre() Docente: Universidad Nacional de Ingeniería
: cadena 580
Return nombreEmpleado
Fin método obtenerNombre
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 581
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 582
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 583
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 584
Algoritmo y programa OO usando polimorfismo en Visual Basic NET.
Ejercicio: El mismo ejercicio anterior, pero utilizando el concepto de polimorfismo
Clase abstracta Empleado2
Declaraciones
Datos
# nombreEmpleado: Cadena
# deptoEmple : Cadena
# puestoTrabajo : Cadena
# SueldoQna: Real
Metodo establecerNombre(nom: Cadena)
nombreEmpleado = nom
Fin método establecerNombre
Método establecerDepto(dep: cadena)
deptoEmple = dep
Fin de método establecerDepto
Método establecerPuesto(pues : cadena)
puestoTrabajo = pue
fin método establecerPuesto
Metodo abstracto calcularSueldoQna()
Metodo obtenerNombre() : cadena
Return nombreEmpleado
Fin método obtenerNombre
Método obtenerPuesto() : cadena
Return puestoTrabajo
Fin método obtenerPuesto
Método obtenerDpto() : cadena
Return deptoEmple
Fin método obtenerDpto
Método obtenerSueldoQna() : Real
Return SueldoQna
Fin método obtenerDpto
Fin clase Empleado2
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 585
MSc. Ing. Jorge Prado D. Docente: Universidad Nacional de Ingeniería 586