Documentos de Académico
Documentos de Profesional
Documentos de Cultura
3.1 Comparación y evaluación de los Lenguajes Orientados a Objetos (Visual Basic, Eiffel,
Smalltalk, C++, Java, etc.).
1.1.1.- Introducción
ESTRUCTURADO
LOGICO
Paradigmas
FUNCIONAL
ORIENTADO A OBJETO
El Paradigma Estructurado:
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.
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.
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.
Campos de aplicación
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).
Ante dicho "programa" es posible establecer hipótesis que no son más que preguntas o
incógnitas, por ejemplo:
¿ "pichurri" vuela ?
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:
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.
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.
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.
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).
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.
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.
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 .
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 :
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
1.2.1.- 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
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)
Roles o papeles jugados o representados por personas (gerentes, operarios, usuarios cliente)
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.
Cuando hemos determinados los posibles objetos pasamos a identificar los posibles
atributos y las operaciones sobre ellos
Ejemplos :
Atributos: Nombre
Dirección
Ubicación
Nombre del departamento
Nivel de estudio
Objeto: Película
Atributos: Nombre
Director
Genero
Duración
Color
Objeto: Alumno
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
Objeto: Alumno
Objeto A
mensajes Objeto B
Datos Datos
Objeto C
Datos
Objeto D
Datos
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.
|
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
Clase A
Ejemplo de clases:
3.- Carlos Andrés Pérez, Violeta Barrios, Bill Clinton, pertenecen a la clase “Ex presidentes
de América”
3.- Los vuelos de aerolíneas de la empresa XYZ pertenecen a una clase: ____________
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:
Ejemplos de clases
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.
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 java.io.*;
Class Primero {
Public static void.main (String args[] ) throws IOException
{
System.out.print (“Este es una aplicación en Java.\n”);
Sytem.out.print (“Esta es una clase llamada para realizar
impresiones.\n”);
} // Fin de la clase
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:
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++
class clasenombre
{
lista de variable miembro
lista de funciones miembro (usualmente prototipos o encabezados miembros
};
// 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
};
MUY
IMPORTANTE
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…
Métodos públicos
Variables de instancias
privadas
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.
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
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 …
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.
Podemos afirmar que por lo general todo lo que hacemos con la herencia múltiple se puede
realizar con la herencia simple.
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
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.
Un enlace se refiere al tiempo real cuando se anexa o se une el código a una función dada.
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.
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.
En Conclusion:
El paradigma orientado a objeto tiene sus propias características que lo definen como tal entre
las principales tenemos:
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.
1.- Describa y justifique los objetos que obtiene de cada uno de los enunciados:
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.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?
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.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:
¿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:
Realice un algoritmo por cada método u operación dada en el ejercicio. Prepare la respuesta
y preséntela con sus compañeros
¿Qué es un
analista de
sistema?
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.
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.
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 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:
Sistemas expertos:
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.
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.
1.- Realice un esquema resumen de media página con sus propias palabras
sobre el diseño estructurado
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.
Diseño de
Producir hardware
diseño
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.
desktop laptop
Teclado monitor
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.
factura
credito contado
especial normal
Cuenta cliente
NEUMATICOS RADIO
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.
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
persona vehiculo
1 0..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
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:
Persona
Atributos
Nombre relevantes Persona
Dirección
Edad
Notación reducida
Leer() Operaciones
Establecer_limite() Funciones
. Metodos
.
VerificadorDeDatos Colaboradores
Llame al SelectorDeActividad
CLIENTE
Nombre
Dirección
….
Explicación
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
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.
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:
Por ejemplo, tenemos la clase de CLIENTE donde tenemos que calcular el saldo
del cliente, tenemos que cada objeto se representa mediante los datos:
Entonces para cada dato se debe establecer un método setter y/o getter , en el
ejemplo se requieren los siguientes métodos:
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.
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.
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
Puede observar que las instancias de la clase tienen los mismos tipos de datos y
métodos, pero NO la misma información
Arquitectura modelo-vista-controlador
Un programa orientado a objeto que utilice la arquitectura modelo-vista-
controlador.
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
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
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:
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
Clase Empleado
1.- Declaraciones
Datos
NombreEmpleado: Cadena
HorasTrabajadas: Entero
PagoHora: Real
Salario: Real
5.-Metodo CalcularSalario( )
If HorasTrabajadas<= 40 Then
Salario = HorasTrabajadas * PagoHora
Else
Salario = (40 * PagoHora) + (( HorasTrabajadas -40) *( PagoHora * 2))
Endif
Fin Metodo EstablecerNombre
Clase EjecutaEmpleado
Calcular ObjEmpleado.CalcularSalario()
Imprimir objEmpleado.ObtenerNombre()
objEmpleado.ObtenerSalario()
Fin Metodo principal
Fin clase EjecutaEmpleado
Ejemplo:
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
Clase PresentaDia
Declaraciones
Datos
NumDia : Entero
NombreDia : Cadena
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
Clase EjecutaPresentaDia
Metodo Principal
Declaraciones
Variables
Ndia : Entero
Declarar, crear e iniciar objeto
PresentaDia Objdia = new PresentaDia
Solicitar numero de dia
Leer Ndia
Establecer Objdia.EstablecerNDia(Ndia)
Calcular ObjDia.CalcularNombreDia()
Obtener ObjDia.ObtenerNombreDia()
Ejemplo:
Solución:
Diagrama de Clases
Empleado
NombreE
HorasT
PagoH
Sueldo
EstablecerNombreE() EjecutaEmpleado
EstablecerHorasT()
EstablecerPagoH()
CalcularSueldo()
ObtenerSueldo()
ObtenerNombreE()
Clase Empleado
Declaraciones
Datos
NombreE : Cadena
Metodo CacularSueldo()
Sueldo = HorasT * PagoH
Fin método CalcularSueldo
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
ObjEmpleado.EstablecerNombreE(NomEmple)
ObjEmpleado.EstablecerHorasT(HTraba)
ObjEmpleado.EstablecerPagoH(PagoHora)
Ejemplo:
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
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.
EmpleadoPorHora EmpleadoAsalariado
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()
Clase empleado
Declaraciones
Datos
# nombreEmpleado : cadena
# deptoEmple : cadena
Metodo calcularSueldoQnal()
SueldoQnal = horasTrabajadas * cuotaHora
Fin método CalcularSueldoQnal
Clase EmpleadoAsalariado
Declaraciones
Datos
SueldoQnalAsal : Real
SueldoMensual : Real
Método calcularrSueldoQnalAsal()
SueldoQnalAsal = SueldoMensual/2
Fin método calcularSueldoQnalAsal
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
Ejemplo:
# nombreEmpleado
# deptoEmple
EjecutaEmpleado2
# puestoTrabajo
# SueldoQna
establecerNombre()
establecerDepto()
establecerPuesto()
calcularSueldoQna() **
obtenerNombre()
obtenerPuesto()
obtenerDpto()
obtenerSueldoQna()
EmpleadoPorHora2 EmpleadoAsalariado2
horasTrab SueldoMensual
cuotaHora
calcularSueldoQnalAsal()
establecerHoras()
establecerSueldoMensual()
establecerCuota()
calcularSueldoQnal()
Clase EmpleadoAsalariado2
Declaraciones
Datos
SueldoMensual : Real
Método calcularrSueldoQnalAsal()
SueldoQnalAsal = SueldoMensual/2
Fin método calcularSueldoQnalAsal
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)
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.
Es como analizar una estructura compleja, que se va armando por partes, sub
partes, sub sub partes, etc.
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.
Clase: los nombres de las clases se crea el vocabulario con el que se formulara el
diseño.
Colaboradores: todos los objetos guardan relación con otro objeto del sistema.
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()
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
Ejercicios de la II unidad.
Problemas para visualizar clases:
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:
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.
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
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.
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
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
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)
18.- Elaborar un programa que lea los datos de varios estudiantes: Nombre y tres
calificaciones parciales, visualizar los siguientes datos:
Reporte de Calificaciones
X------------------------------X 999.99
Estado de cuenta
Adendum
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.
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 Microsoft.NET 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.
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
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...).
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 System.Xml. La funcionalidad
fundamental para crear aplicaciones Web está en el espacio de nombres System.Web. Éste a
su vez contiene otros espacios de nombres más
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.
ADO.NET 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.
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.
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.
Este es el aspecto que presenta parte del código que genera la interfaz mostrada en la
anterior figura:
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.
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:
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.
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.
Formato:
Const variables As tipo = valor
Ejemplos
Se presentara: valor2: 5
Structure <nombre>
Public <nombre> As <tipo>
End Structure
Tambien podemos utilizar la palabra reservada With para realizar acciones que se repiten,
evitando escribir una parte del código, analicemos el siguiente ejemplo:
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:
En escencia una variable local solo es conocida por el codigo de esa funcion o procedimiento
y es desconocida por otras funciones o procedimientos.
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
OPERADOR OPERACIÓN
+ Suma
- Resta
* Multiplicacion
/ Division flotante
\ Division Entera
^ Potencia
MOD Modulo
= 5^8/3
= 9^1/2
En Visual Basic el operador (MOD) devuelve el residuo entero de una division entre enteros,
ejemplo:
Otro ejemplo;
8
alfa = 108 MOD 10
Ejercicios de programacion
1.-
2.-
3.-
Ejemplos:
a) 2 + 3 * 4 = 20 (incorrecto)
2 + 3 * 4 = 14 (correcto)
En Visual Basic NET recordar siempre, que antes de plantear una formula en un programa
se debera evaluar respecto al orden siguiente:
1.- Parentesis
Ordenes de
2.- Potencias y raices operacion
5.- Dos o más de la misma jerarquia u orden, entonces resolver de izquierda a derecha
Ejemplo:
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
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:
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
2.- Objetos que permitan capturar y desplegar datos, de momento se usaran los dos
objetos de entrada / salida más comunes:
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
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.
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.
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.
NomObjeto.Propiedad = nvovalor;
Ejemplo: Form2.BackColor = 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:
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.
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.
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.
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
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:
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.
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.
AREA.Text=(BASE.Text*ALTURA.Te
xt / 2)
End Sub
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).
Regresando al código:
a.- Son las propiedades TEXT de los TEXTBOX'S quienes contienen los datos tanto
capturados como los de salida.
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.
Ejemplo;
Label1.Text = alfa.ToString(”#.##”)
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.
NOMBREFORMA.NOMBRECOMPONENTE.NOMBREPROPIEDAD
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 FORM1.vb y FORM2.vb.
Recordar que si se quiere que FORM1 haga otro proceso u operación solo agregarle
componentes y mas BUTTON's
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 Me.Close() sería
equivalente a FORM2.CLOSE() 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:
1.- Instrucciones Condicionales que en VISUAL BASIC NET se implementan con las
instrucciones if y select case.
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:
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.
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ó
Una condicion simple en visual basic NET se define como el conjunto de variables y/o
constantes unidas por los llamados operadores relacionales.
Los operadores relacionales que reconoce Visual Basic NET se presentan en la siguiente
tabla:
If condicion Then
Instrucciones cuando la condicion sea cierta
Else
Instrucciones cuando la condicion sea falsa
End If
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.
Una condicion compuesta se define como dos o más condiciones simples unidas por los
llamados operadores lógicos.
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.
La evaluacion final, se obtiene usando la regla anteriormente descrita para una condicion
compuesta, que contiene el operador “AND”.
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:
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.
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)
EJERCICIOS DE PROGRAMACION
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.
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.
Programa ejemplo :
Ejemplo:
Dim X As Integer
LISTA.Items.Clear()
For X = 1 To 10
LISTA.Items.Add(X & "= MAMA")
Next X
End Sub
FOR X=5 TO 28
Desplegar X
NEXT
FOR X= -5 TO 18
Desplegar X
NEXT
4.- Los incrementos tambien pueden ser diferentes al de uno en uno, ej.;
5.1.- el valor inicial de la variable debe ser mayor que el valor final y usar un step negativo.
For … Each
Instrucciones…
Next
EJERCICIOS DE PROGRAMACION
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).
DO WHILE CONDICION(ES)
INSTRUCCION(ES) CIERTAS
INSTRUCCION(ES) DE SALIDA DE CICLO
LOOP
Programa
Dim X As Integer
X=1
LISTA.Items.Clear()
Do While X <= 10
LISTA.Items.Add(X & "= GATO")
X=X+1
Loop
End Sub
Corrida
Nota:
EJERCICIOS DE PROGRAMACION
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.
DO
INSTRUCCION (ES) CIERTAS
INSTRUCCION (ES) DE SALIDA DE CICLO
LOOP WHILE CONDICION (ES)
Programa
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.
En Visual Basic NET dado un problema o programa cualesquiera que sea el tipo de ciclo que
se utilice, se resuelve con:
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.
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.
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 VB.NET podrá llamar a un método
de un objeto escrito en C# que devuelva un array, y dicho array, será manejado desde
VB.NET.
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, VB.NET como
lenguaje, ha obtenido toda la potencia de base inherente en el sistema para la creación
En VB.NET 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
VB.NET 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.
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.
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.
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
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:
El Código fuente siguiente, muestra la diferencia entre crear un array del modo habitual,
y empleando CreateInstance( ).
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.
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.
Copia
Si intentamos copiar un array asignando la variable que contiene un array a otra, el resultado
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:
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 Button1.Click…
TextBox1.Text = “ “
' 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
Array.Clear(sLetras, 0, 1)
TextBox1.Text = TextBox1.Text & "Array sLetras" & VbCrLf
MostrarArray6(sLetras)
TextBox1.Text = TextBox1.Text & VbCrLf
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 button1.Click….
TextBox1.Text = “ “
' ordenar todo el array
Dim sLetras1() As String = {"z", "a", "g", "m", "w", "i", "c", "b"}
TextBox1.Text = TextBox1.Text &"arreglo original" & VbCrLf
MostrarArray7(sLetras1)
Array.Sort(sLetras1)
TextBox1.Text = TextBox1.Text &"Ordenar todos el array" & VbCrLf
MostrarArray7(sLetras1)
' ordenar parte del array
Dim sLetras2() As String = {"z", "a", "g", "m", "w", "i", "c", "b"}
Array.Sort(sLetras2, 4, 3)
TextBox1.Text = TextBox1.Text & "Ordenar parte del array" & VbCrLf
MostrarArray(sLetras2)
' invertir valores dentro del array
Dim sLetras3() As String = {"z", "a", "g", "m", "w", "i", "c", "b"}
Array.Reverse(sLetras3, 2, 4)
TextBox1.Text = TextBox1.Text & "Invertir valores del array" & VbCrLf
MostrarArray7(sLetras3)
TextBox1.Text = TextBox1.Text & vbCrLf
End Sub
Private Sub MostrarArray7(ByVal sMiLista() As String)
Dim iContador As Integer
For iContador = 0 To sMiLista.Length - 1
TextBox1.Text = TextBox1.Text &"Elemento: “ & iContador & VbTab & ” _
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 Button1.click…
TextBox1.Text = “ “
Dim sNombres() As String = {"Alberto", "Juan", "Ana", "Paco", "Miguel", "Ana"}
' buscar una cadena a partir del índice 0 del array
TextBox1.Text = TextBox1.Text & "Paco está en la posición “ & VbTab & _
Array.IndexOf(sNombres, "Paco") & VbCrLf
' buscar una cadena a partir del índice 3 del array
TextBox1.Text = TextBox1.Text & "Ana está en la posición" & _
" comenzando a buscar desde índice 3" & VbTab & _
Array.IndexOf(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 = Array.IndexOf(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
TextBox1.Text = TextBox1.Text & vbCrLf
iNumeros = New Integer() {10, 20, 30, 10, 50, 60, 10, 70, 80}
TextBox1.Text = TextBox1.Text & " En el arreglo {10, 20, 30, 10, 50, 60, 10, 70,
80}"_
& vbCrLf
1.- Capturar y desplegar 5 precios de productos cualesquiera usando dos panel uno para
capturar y uno para desplegar
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.
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 Form1.Load…
' crear array multidimensional y rellenar de valores
Dim iDatos(2, 4) As Integer
Ejemplo:
Recordar que va a generar una matriz que tendra cuatro renglones y cinco columnas
empieza en sueldo(0,0)
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
Diseño: Corrida:
Ejemplo:
MiArreglo.Length
MessageBox.Show(MiArreglo.Length)
MiArreglo = Nothing
If MiArreglo IsNothing then
MessageBox.Show(“ Nada”)
Else
MessageBox.Show(MiArreglo.Length) ‘presenta la dimension
Endif
Importante: Si deseamos copiar una matriz en otra podemos hacerlo de esta forma:
MiArreglo.CopyTo(OtroArreglo,0)
Ejemplo:
Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim MiArreglo() As String = {“Mercurio”,”Venus”,”Tierra”}
Dim OtroArreglo() As String
ReDim OtroArreglo(MiArreglo.Lenght – 1)
MiArreglo.CopyTo(OtroArreglo,0)
MessageBox.Show(OtroArreglo(0))
End Sub
Actividades de reforzamiento de lo a
aprendido
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).
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
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
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
Format(Expresión[,CadenaFormato][,PrimerDíaSemana[,PrimeraSemanaAño]).
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
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.
, Separador de millar.
. Separador decimal.
Funciones matemáticas
Las principales funciones matemáticas provistas por Visual Basic son:
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.
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
Sub PROC1()
Label2.Text = EDAD.Text * 12
End Sub
Corrida
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.
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 PROC1(ByVal deci As Single, ByVal nom As String, ByVal suma As Integer)
' pero siempre se recibe en una variable
Label2.Text = EDAD.Text + deci + suma
Label3.Text = nom
End Sub
Actividad de reforzamiento de lo
aprendido
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:
Programa
Ejemplo;
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.
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
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 System.Object, ByVal e As System.EventArgs)
Handles Button1.Click
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
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”.
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.
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,
Windows
Forms
Form
TextBox
5.2.1.Objeto Formulario
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.
Métodos
Método
Descripción
Activate Activa el formulario y le da el foco.
Eventos
Evento
Descripción
Activated Ocurre al activarse el formulario.
Controles Label.
Propiedades
Propiedad
Descripción
Anchor Es una nueva propiedad que permite ajustar el ancho del
control.
Métodos
Método
Descripción
FindForm Devuelve el formulario en el que se encuentra el control.
Eventos
Evento
Descripción
Click Se desencadena al dar clic con 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.
Font Cambia el tipo de letra y todas las características del tipo elegido.
Métodos
Método
Descripción
AppendText Añade texto al final del texto actual.
Eventos
Evento
Descripción
KeyDown Ocurre al pulsar hacia abajo una tecla extendida.
La Figura muestra un formulario con varios controles TextBox, a los cuales se han
aplicado diferentes efectos mediante sus propiedades.
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.
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
System.EventArgs) Handles txtOrigen.TextChanged
' calculamos la longitud del texto escrito
Me.lblContador.Text = Me.txtOrigen.TextLength
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 pulsar este botón, seleccionar por código texto del control txtOrigen y
' pasarlo al control txtDestino
Private Sub btnSeleccionar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnSeleccionar.Click
Me.txtOrigen.SelectionStart = Me.txtPosicion.Text
Me.txtOrigen.SelectionLength = Me.txtLongitud.Text
Me.txtDestino.Text = Me.txtOrigen.SelectedText
End Sub
La Figura muestra este ejemplo en ejecución.
5.2.4.-Control Button
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.
Métodos
Método
Descripción
NotifyDefault Indica si el botón será el control por defecto. Es de tipo lógico.
Eventos
Evento
Descripción
Click Se desencadena al dar clic con el mouse sobre la etiqueta.
La Figura muestra un ejemplo de control Button, sobre el que se han modificado algunos
valores por defecto de sus propiedades.
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 ListBox.ObjectCollection, 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
Propiedades
Propiedad
Descripción
Name Generalmente usaremos el prefijo lst.
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.
Eventos
Evento
Descripción
DoubleClick Ocurre al dar dos veces clic sobre la lista.
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.
Método
Descripción
Add Añade un elemento al final de la lista.
En resumen:
listBox1. Items.Sorted = true; Ordena los elementos de la lista usada solo al tiempo de
diseno.
encuentra en la lista.
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 System.Object, ByVal e As
System.EventArgs) Handles btnSelecCod.Click
' para seleccionar elementos de un ListBox por código
' podemos utilizar el método SetSelected()
Me.rbtMultiple.Checked = True
Me.lstValores.SetSelected(1, True)
Me.lstValores.SetSelected(3, True)
Me.lstValores.SetSelected(5, True)
End Sub
Ejemplo programa
For r = 0 To cant - 1
meses = LISTA.Items(r)
meses = meses * 12
LISTA.Items(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:
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
Propiedades de ComboBox
Propiedad
Descripción
Name Generalmente usaremos el prefijo cbo.
Métodos
Método
Descripción
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.
Colección Items
Propiedades
Propiedad
Descripción
All Devuelve un objeto con todos los elementos del combo.
Métodos
Método
Descripción
Add Añade un elemento al final del combo.
Primero aprenderemos a insertar un nuevo ítem, hacemos doble clic en el botón INSERTAR
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 ButtonEditar.Click…..
'primero verificamos que TEXBOX1 y TEXBOX2 no estén vacío
If TextBox1.Text.Length > 0 And TextBox1.Text.Length > 0 Then
' eliminamos el ítem de la posición TEXBOX1
ComboBox1.Items.RemoveAt (CInt(TextBox1.Text))
' inserta el Nuevo elemento TEXBOX2
ComboBox1.Items.Insert (CInt(TextBox1.Text), TextBox2.Text)
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.
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.
CheckState Devuelve el estado del checkbox, que puede ser: Unchecked (sin
marcar), Checked (marcado) o Indeterminate (gris).
Método
Descripción
Focus Pone el foco sobre el checkbox.
Eventos
Evento
Descripción
CheckedChanged Ocurre al cambiar el valor de la propiedad Checked del 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 System.Object, ByVal
e As System.EventArgs) Handles chkPonColor.CheckedChanged
If Me.chkPonColor.CheckState = CheckState.Checked Then
Me.BackColor = Color.LightBlue
Else
Me.ResetBackColor()
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
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
CheckOnClick Establece si el control podrá ser fijado la primera vez al dar click.
Métodos
Método
Descripción
GetItemChecked Devuelve true si un cierto item ha sido seleccionado o false si no.
Eventos
Evento
Descripción
ItemCheck Ocurre al seleccionar un elemento y poner el check en true.
5.2.9.-Control RadioButton
Propiedades
Métodos
Método
Descripción
Focus Pone el foco sobre 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.
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
Métodos
Método
Descripción
Focus Pone el foco sobre el control.
Eventos
Evento
Descripción
GotFocus Ocurre al ingresar el foco sobre el control.
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.
Escribir código
Seleccione el objeto barra1, dé doble clic para abrir el editor del procedimiento
barra1_Scroll y escriba el siguiente código:
Seleccione el objeto barra2, dé doble clic para abrir el editor del procedimiento
barra2_Scroll y escriba el siguiente código:
Seleccione el objeto barra3, dé doble clic para abrir el editor del procedimiento
barra3_Scroll y escriba el siguiente código:
Ejecutar el proyecto
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
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
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 System.Object, ByVal e As
System.EventArgs) Handles mnuFuente.Click
Dim oFuente As New Font("Comic", 15)
Me.txtValor.Font = oFuente
End Sub
La Figura muestra el aspecto del menú contextual, cuando es utilizado desde el control
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 System.Object, ByVal e As
System.EventArgs) Handles btnActivar.Click
' utilizando la propiedad focus para el control textbox1
Textbox1.focus
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.
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.
5.7.1.-Función InputBox:
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.
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:
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
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:
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.
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.
Form1.Visible = False 'Aca puse una acción que usted ya conoce
End If
End Sub
En estilo podrían ir por ejemplo las siguientes opciones:
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.
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
Label1.text =Date.now.TolongTimeString
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
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
5.8.2.-Control ImageList
Este control actúa como repositorio de imágenes, del que se alimentarán otros controles del
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.
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.
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.
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
System.EventArgs) Handles MyBase.Load
' modificar fecha del DateTimePicker
Me.dtpFNacim.Text = "15/06/2002"
'....
End Sub
Podemos restringir el rango de fechas a mostrar por este control con las propiedades
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 System.Object, ByVal e As
System.EventArgs) Handles btnCambiosFecha.Click
' configurar por código el control DateTimePicker
Me.dtpFNacim.MinDate = "1/4/2002"
Me.dtpFNacim.MaxDate = "1/10/2002"
Me.dtpFNacim.CustomFormat = "d-MMM-yy"
Me.dtpFNacim.Format = DateTimePickerFormat.Custom
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 System.Object, ByVal e As
System.EventArgs) Handles nupEdad.ValueChanged
Select Case Me.nupEdad.Value
Case 20 To 30
Me.nupEdad.BackColor = Color.Gold
Case 30 To 40
Me.nupEdad.BackColor = Color.LimeGreen
Case Else
Me.nupEdad.BackColor = Me.nupEdad.DefaultBackColor
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.
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 System.Object, ByVal e As
System.EventArgs) Handles btnTamCalendario.Click
Me.mclCalendario.CalendarDimensions = New Size(2, 2)
End Sub
En la Figura vemos el resultado de expandir el tamaño del control.
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 System.Object, ByVal e As
La Figura muestra este formulario en ejecución tras añadir los nuevos elementos.
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.
CheckPathExits Chequea que exista la ruta del archivo antes de regresar del
diálogo.
InitialDirectory Muestra un cierto directorio inicial para los archivos del diálogo.
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.
Eventos
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.
Métodos
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.
Métodos
Método
Descripción
ShowDialog Muestra el diálogo de colores.
Evento
Descripción
HelpRequested Ocurre al dar clic sobre el botón de ayuda del diálogo de color.
5.9- Interfaces
Introducción
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.
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.
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ú:
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:
frmPadre.LayoutMDI(MDILayout.Cascade)
5.11.1.-Tipos de Errores
Una ayuda para corregir errores de sintaxis, es usar la sentencia Option Explicit que
fuerce a declarar variables y evitar expresiones inválidas.
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.
Inicio Procedimiento()
On Error GoTo <Etiqueta>
<Instrucciones>
Exit Sub
<Etiqueta>:
<Instrucciones>
[Resume ¦ Resume Next ¦ Resume Etiqueta]
Fin Procedimiento
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]
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
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
Catch ex As System.IO.IOException
End Try
Try
' código que queremos controlar
Catch ex As Exception
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
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.
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
Dim x, y, r As Integer
Try
x = CInt(InputBox(“Introduzca un numero “))
y = CInt(InputBox(“Introduzca otro numero “))
r =x\y
MessageBox.Show("El resultado es: " & r)
Catch ex As Exception When y = 0
MessageBox.Show("No se puede dividir por cero.")
Catch ex As Exception
MessageBox.Show(ex.Message)
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.
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
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
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.
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.
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
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:
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:
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:
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.
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.
Como campo.
Como procedimiento de propiedad.
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.
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.
Por ejemplo, un procedimiento de propiedad para una propiedad Name, de la clase Personas,
podría ser como el que sigue:
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.
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
Personas.Nombre = "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.
Quedará así:
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.
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:
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.
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.
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.
Ejemplo:
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:
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.
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.
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.
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.
Otro ejemplo:
Para utilizar y probar la clase Persons, debemos crear primero un proyecto de prueba y
agregar una referencia al módulo de clase.
Quizás se preguntén por qué tuvimos que escribir dos veces Persons, pues porque la
primera instancia es el módulo de clase Persons.vb y la segunda instancia es la clase
Persons de ese módulo.
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.
person1.PrimerNombre = Textbox1.Text
person1.SegundoNombre = Textbox2.Text
person1.Apellido = Textbox3.Text
person1.FechaCumpleaños = Textbox4.Text
person1.Casado = CheckBox1.Checked
MsgBox(person1.NombreCompleto)
MsgBox(CStr(person1.Edad) & " años")
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.
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 " & loEmp.FechaCrea)
End Sub
End class
Public Class Empleado
Private mdtFechaCrea As Date
Public Property FechaCrea() As Date
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.
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,
Nota
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:
Niveles de acceso
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
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( )
GuardaCuenta.TasaInteres = 0.03
Dim miCuenta As New GuardaCuenta( )
Dim tuCuenta As New GuardaCuenta( )
MessageBox.Show(miCuenta.CalculaInteres( ))
MessageBox.Show(tuCuenta.CalculaInteres( ))
End Sub
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
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
El siguiente código muestra cómo invocar una propiedad compartida cualificándola con el
nombre de la clase:
GuardaCuenta.Tasa = 0.03
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.
6.11.-¿Qué es el polimorfismo?
Definición
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.
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.
Múltiples clases comparten los mismos atributos y operaciones, permitiendo una eficaz
reutilización del código
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
La palabra clave Inherits se utiliza para definir una clase derivada que heredará de una
clase base existente.
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.
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.
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.
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
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.
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.
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.
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.
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
Hemos creado una clase Jugadores, derivada de la clase Personas. Ahora haremos una nueva
aplicación para probar la clase Jugadores.
Player1.FirstName = "Marvin"
Player1.LastName = "Garcia"
Player1.Number = 13
Playere1.Position = "Shortstop"
MsgBox(player1.Posicion & " " & player1.FullName & ", #" &
CStr(player1.Numero) & " esta ahora al bate.")
9. Presionamos F5 para ejecutar el programa. Hacemos clic en cada botón para ver los
resultados.
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…
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.
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.
End Sub
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
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.
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.
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
System.Drawing.Printing como System.Windows.Forms 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:
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:
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.
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.
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.
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,
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:
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.
If chkSelAntes.Checked Then
If seleccionarImpresora() = False Then Return
End If
If prtDoc Is Nothing Then
prtDoc = New System.Drawing.Printing.PrintDocument
AddHandler prtDoc.PrintPage, AddressOf prt_PrintPage
End If
If esPreview Then
Dim prtPrev As New PrintPreviewDialog
prtPrev.Document = prtDoc
prtPrev.Text = "Previsualizar documento"
prtPrev.ShowDialog()
Else
prtDoc.Print()
End If
End Sub
La clase PrintPreviewControl
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).
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.
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:
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.
Seleccionamos Informe:
Desde el panel Origenes de Datos arrastramos los campos sobre fila del medio de la tabla.
Como se ve en la imagen:
Mostraremos como podemos hace un reporte con datos agrupados en visual basic .net.
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.
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.
Abrimos el reporte sobre el cual trabajaremos, se verá más o menos como este:
Podemos aplicar el tipo de letra a varias celdas al mismo tiempo seleccionando varias
celdas y aplicando el formato.
Para cualquier texto que querramos que aparesca en el informe utilizamos un Cuadro de
Texto.
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.
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í.
Elemento.
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 –> ADO.NET 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.
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.
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.
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.
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.
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.
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.
23.- Ahora le pondremos un nombre tanto en la parte donde dice Fill a DataTable como
en Return a DataTable, damos clic en siguiente.
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.
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
Posteriormente seleccionaremos la o las tablas que queremos agregar y los campos que
queremos que aparezcan en el reporte
Este código sólo realiza consultas de acuerdo al valor colocado en el txtUsuario (nombre
del usuario).
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
End Sub
El siguiente paso consiste en crear un menú para poder abrir los formularios hijos a
través de sus opciones. Ver Figura
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 System.Object, ByVal e As
System.EventArgs) Handles mnuCascada.Click
Me.LayoutMdi(MdiLayout.Cascade)
End Sub
Private Sub mnuHorizontal_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles mnuHorizontal.Click
Me.LayoutMdi(MdiLayout.TileHorizontal)
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.
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,
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 System.Object, ByVal e As
System.EventArgs) Handles mnuUsuario.Click
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
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.
Entre las clases que están basadas en esta clase abstracta tenemos las siguientes:
Nota:
Las clases DeflateStream y GZipSteam están incluidas en el espacio de
nombres System.IO.Compression.
La clase CryptoStream está incluida en el espacio de nombres
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.
En este primer ejemplo veremos lo complicado que pude parecer acceder a un fichero
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:
Dim fs As New
System.IO.FileStream(fichero, _
System.IO.FileMode.OpenOrCreat
e, _ System.IO.FileAccess.Write)
' 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 (Encoding.Default)
Dim enc As New System.Text.UTF8Encoding
' convertimos la cadena en un array de bytes
datos = enc.GetBytes(cadena)
' lo escribimos en el stream
fs.Write(datos, 0,
datos.Length)
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.
Como podemos apreciar, esta es una forma mucho más "compacta" que la anterior, ya
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.
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.
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.
Module Module1
Const fic1 As String = "E:\Pruebas\Prueba CryptoStream.txt"
Const fic3 As String = "E:\Pruebas\Prueba CryptoStream
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 = enc.GetBytes(texto)
Dim ms As New MemoryStream(datos)
' El fichero de salida
Dim fs As New FileStream(ficSalida, FileMode.Create, FileAccess.Write)
' El proveedor criptográfico
Dim r As New DESCryptoServiceProvider
'
' Establecer la clave secreta
r.Key = Encoding.Default.GetBytes(sKey.Substring(0, 8))
r.IV = Encoding.Default.GetBytes(sKey.Substring(0, 8))
'
' Crear una secuencia de cifrado
Dim cs As New CryptoStream(fs,r.CreateEncryptor(), _
CryptoStreamMode.Write)
'
' Escribir el fichero cifrado cs.Write(datos, 0,
datos.Length)
cs.Close()
'
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
r.Key() = Encoding.Default.GetBytes(sKey.Substring(0, 8))
r.IV = Encoding.Default.GetBytes(sKey.Substring(0, 8))
'
' crear la secuencia para leer el fichero cifrado
Dim fs As New FileStream(fichero, FileMode.Open, FileAccess.Read)
'
Dim cs As New CryptoStream(fs,r.CreateDecryptor(), _
CryptoStreamMode.Read)
'
' guardar el contenido de fichero descifrado
Dim sw As New StreamWriter(ficSalida) Dim sr As New StreamReader(cs)
sw.Write(sr.ReadToEnd)
sw.Flush()
sw.Close()
'
' devolver el texto
sr = New StreamReader(fic3)
Dim ret As String = sr.ReadToEnd()
sr.Close()
'
Return ret
End Function
End Module
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.
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.
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 VB.NET creada desde VS.NET, 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.
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
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
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.
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.
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
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.
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.
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
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.
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.
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:
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:
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:
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.
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.
Una vez creado un ArrayList, podemos utilizar algunos de los métodos indicados a
continuación para añadir valores a la colección.
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.
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
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
¿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.
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.
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.
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.
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.
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.
PrivateSub Botton1.Click…
TextBox1.Text = “”
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
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.
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.
Por otra parte, el método Remove( ), elimina un elemento del objeto, pasándole como
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.
' obtener algunos valores del objeto Hashtable que se han pasado al array normal
Dim oEntradaDicc As DictionaryEntry
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:
El método Enqueue( ) añade nuevos valores, que quedan situados al final de la lista,
del modo ilustrado en la figura anterior.
End Sub
TextBox1.Text = TextBox1.Text & "Obtenemos el primer valor sin eliminar: " &
aqListaMensa.Peek())
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.
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.
Colecciones personalizadas
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.
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.
' 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
MyBase.Add(value) ' llamamos al método base
Me.Sort() ' ordenamos el array
Return Me.Count ' 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:
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.
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 System.Collections, los cuales definen las
características que deben tener los arrays y colecciones del entorno.
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:
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 :
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 VB.NET 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.
System.Drawing
Para utilizar las clases relacionadas con la manipulación de gráficos, es preciso importar
este espacio de nombres.
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.
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.
Vamos por lo tanto a observar las diferencias codificando el mencionado evento Paint( ),
en el que dibujaremos un rectángulo. Ver Código fuente
End Sub
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.
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.
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
End Sub
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
End Sub
' pintar con brocha de tipo hatch; para utilizar este tipo de brocha
' necesitamos importar System.Drawing.Drawind2D
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
End Sub
End Sub
La Figura muestra todas las formas dibujadas con objetos de los tipos derivados de Brush.
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
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.
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
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.
El proyecto FondoFormPicB contiene esta aplicación para que el lector pueda realizar las
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.
End Sub
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.
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.
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.
para acceder a este ejemplo), y consiste en crear un formulario con un ComboBox que
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.
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 System.IO. 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 System.IO
Public Class Form1
Inherits System.Windows.Forms.Form
Case ".GIF"
Me.lstFicheros.Items.Add(oArchInfo.Name, 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.
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.
Con ello, todos los lenguajes compatibles con .NET podrán utilizar este conjunto de
objetos.
Las clases incluidas en System.IO, nos van a permitir realizar labores de lectura y escritura
Objetos Stream
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.
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
Cierre del Stream con el método Close( ). Esta acción vuelca el contenido del
búfer del objeto en el archivo.
Imports System.IO
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\NOTAS.txt")
' escribir líneas
swEscritor.WriteLine("esta es la primera línea")
swEscritor.WriteLine("segunda línea de texto")
' ahora escribimos texto pero sin provocar un salto de línea
swEscritor.Write("Juan y Luna ")
swEscritor.Write("van de paseo")
swEscritor.Write(swEscritor.NewLine) ' esto introduce el salto de línea
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
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
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
Console.WriteLine()
Console.WriteLine("**Ahora leemos el resto del archivo**")
Dim Texto As String
Texto = srLector.ReadToEnd()
Console.WriteLine("El texto restante contiene --> {0}", Texto)
srLector.Close()
' ***********************************************
' leer línea a línea mediante un bucle
Dim srLector As StreamReader = New StreamReader("\pruebas\Datos.txt")
Dim Linea As String
Dim ContadorLin As Integer = 1
Linea = srLector.ReadLine()
Do While Not (Linea Is Nothing)
Console.WriteLine("Línea: {0} - Contenido: {1}", ContadorLin, Linea)
ContadorLin += 1
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 System.IO
Imports System.Text
Module Module1
Sub Main()
' crear un Stream de lectura
Dim srLector As StreamReader = New StreamReader("\pruebas\NOTAS.txt")
Codigos(Codigos.GetUpperBound(0)) = Valor
Valor = srLector.Read()
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 = Codificador.GetString(Codigos)
Console.WriteLine("Resultado de la lectura con ReadBlock()")
Console.WriteLine(Parte2)
Console.ReadLine()
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.
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
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.
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.
Valor = oFileStream.ReadByte()
Console.WriteLine("Se ha leido el valor: {0}", Valor)
Console.WriteLine("La posición actual del stream es: {0}", _
oFileStream.Position)
' leer varios valores, pasándolos a un array previamente dimensionado
Dim VariosValores(3) As Byte
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
Console.ReadLine()
Manipulación de archivos mediante File y FileInfo
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.
swEscritor = File.CreateText(sNombreFich)
swEscritor.WriteLine("este es")
swEscritor.WriteLine("un nuevo archivo")
swEscritor.Close()
End If
MsgBox("Proceso finalizado")
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.
Case 2
Console.WriteLine("Vamos a mover el archivo {0}", oFInfo.Name)
Console.WriteLine("que está en la ruta {0}", oFInfo.DirectoryName)
File.Move(sNombreFich, "\pruebas\" & oFInfo.Name)
Console.WriteLine("Completado")
Console.ReadLine()
Case 3
File.Delete(sNombreFich)
End Select
' mover uno de los directorios a otra ubicación del disco actual
Directory.Move(sDirectorios(0), "\temp\BIS")
Console.WriteLine("Completado")
Console.ReadLine()
La clase Path
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.
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()
'....
'....
Sub Main()
' instanciar objeto FileSystemWatcher
oFSW = New FileSystemWatcher()
' configurar objeto
oFSW.Path = "C:\pruebas"
oFSW.Filter = "*.txt"
oFSW.IncludeSubdirectories = True
' activar
oFSW.EnableRaisingEvents = True
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.
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.
Sub Main()
' instanciar objeto FileSystemWatcher
Dim oFSW As New FileSystemWatcher()
oFSW.EnableRaisingEvents = True
' mientras que no pulsemos S, el objeto inspeccionará
' el sistema de archivos del equipo
While (Console.ReadLine() <> "S")
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( ).
Sub Main()
'....
oFSW.Path = "\pruebas"
'....
oFSW.Path = "C:\pruebas"
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.
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.
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
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.
Control de versiones
Agrupe módulos que deban tener la misma información de versió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.
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.
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.
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++.
C# VB
csc myCode.cs
Para crear un ensamblado con una extensión .exe y especificar el nombre del
archivo de resultados
C# VB
csc /out:myAssembly.exe myCode.cs
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.
C# VB
csc /out:myCodeLibrary.dll /t:library myCode.cs
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.
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).
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:
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:
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.
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
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.
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 Setup1.msi, si no estamos seguro de que
tenga el Windows Installer 2.0, usaremos los 5 ficheros incluidos en el directorio.
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.
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.
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).
ADENDUM
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.
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.
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.
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.
1.3.2 Cláusulas
Las cláusulas son condiciones de modificación utilizadas para definir los datos que desea
seleccionar o manipular.
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.
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
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.
Operador Uso
< Menor que
> Mayor que
<> Distinto de
<= Menor o igual que
>= Mayor o igual que
= Igual que
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.
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.
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.
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.
Si se desea obtener los registros cuya identificación sea menor de “130‟ y la ciudad sea
“Bogota‟, se debe utilizar el operador AND.
Si se desea obtener los registros donde la segunda letra del nombre sea una “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.
La sentencia SQL de inserción de datos INSERT permite insertar información en una tabla.
Su formato es:
Para insertar un nuevo registro a la tabla usuarios se debería realizar la siguiente sentencia:
Para eliminar solamente los registros cuya identificación sea mayor que “150‟.
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)
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‟.
En este módulo, aprenderemos a trabajar con datos y fuentes de datos en Visual Basic
ADO.NET 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
ADO.NET 1.0 apareció con Microsoft .NET Framework 1.0. Posteriormente, ADO.NET 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 ADO.NET 2.0, el cuál añade algunas características
nuevas adicionales.
En nuestro caso, nos centraremos única y exclusivamente en ADO.NET 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 ADO.NET.
¿Qué es ADO.NET?
ADO.NET 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 ADO.NET es una tecnología inter operativa. Aparte del
almacenamiento y recuperación de datos, ADO.NET 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.
ADO.NET proporciona diferentes clases del nombre de espacio System.Data 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.
La otra parte es la que corresponde con los objetos que permiten el acceso a datos a una
determinada fuente de datos desde ADO.NET y que utilizan así mismo, las clases del nombre
de espacio System.Data.
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.
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 ADO.NET.
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 ADO.NET, 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. System.Data
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.
Imports System.Data
Imports System.Data.SqlClient
Imports System.Xml
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles MyBase.Load
Dim Conexion As String =
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
Más adelante veremos algún ejemplo, y observará en la práctica cuáles son estas diferencias
más destacables.
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.
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.
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 System.Data
Imports System.Data.SqlClient
Imports System.Xml
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
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
Comando.Fill(MiDataSet, "PELIS")
' Rellenamos el control TextBox1 con el dato correspondiente a la primera fila
' de la sentencia SELECT ejecutada
TextBox1.DataBindings.Add("Text", MiDataSet,"PELIS.TITULO")
Comando = Nothing
End Sub
End Class
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.
¿Debemos crear una conexión con la base de datos al principio de nuestra aplicación y
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.
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 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.
Para trabajar con este objeto, utilizaremos los objetos siguientes del proveedor de
acceso a datos:
● Connection
● Command
● DataReader
Imports System.Data
Imports System.Data.SqlClient
Imports System.Xml
Imports System.Data
Imports System.Data.SqlClient
Imports System.Xml
Public Class Form1
Private Conexion As String =
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
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.
Este método que se ha incorporado a ADO.NET 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 System.Data
Imports System.Data.SqlClient
Imports System.Xml
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
' 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'"
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?.
Imports System.Data
Imports System.Data.SqlClient
Imports System.Xml
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
' Declaramos las variables a utilizar
Dim Conexion As String =
"server=.;uid=sa;password=VisualBasic;database=MSDNVideo"
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.
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.
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 System.Data
Imports System.Data.SqlClient
Imports System.Xml
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal eAs
System.EventArgs) Handles MyBase.Load
' 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
MiConexion.Open()
' Ejecutamos la sentencia SQL
MiDataReader = Comando.ExecuteReader()
' Cargamos los resultados en el objeto DataTable
MiDataTable.Load(MiDataReader, LoadOption.OverwriteChanges)
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
Entre medias de estos dos objetos, encontramos el objeto DataAdapter que hace las
El objeto DataAdapter forma parte del proveedor de acceso a datos, tal y como se muestra
en la figura
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 Connection.Con 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.
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 System.Data
Imports System.Data.SqlClient
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
' 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)
Comando.Fill(MiDataSet)
' Cerramos la conexión con la BBDD
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
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 System.Data y hemos importado en el proyecto los
nombres de espacio System.Data y System.Data.SqlClient.
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,
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
Una vez que hemos hecho esto, seleccionaremos los componentes SqlCommand,
SqlCommandBuilder, SqlConnection, SqlDataAdapter y SqlDataSource, tal y como se
muestra en la figura
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
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.
Ahora nos queda únicamente ejecutar nuestra aplicación para estudiar el resultado final.
Este es el que se puede ver en la figura
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
System.Data y System.Xml, mientras que en este segundo ejemplo, no hemos hecho
referencia a ellos.
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.
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.
Finalmente, escribiremos el código necesario para ejecutar nuestra aplicación tal y como
queremos. Este es el que se detalla a continuación:
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
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.
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:
SqlDataAdapter1.Fill(DataSet1, "Ejemplo")
' Cerramos la Conexión
SqlConnection1.Close()
' Asociamos el control DataGridView al DataSet
DataGridView1.DataSource = DataSet1.Tables("Ejemplo")
End Sub
SqlCommand1.Parameters.Add("@Apellido1",
Data.SqlDbType.NVarChar, 50, "Apellido1")
SqlCommand1.Parameters.Add("@Apellido2",
Data.SqlDbType.NVarChar, 50, "Apellido2")
SqlCommand1.Parameters.Add("@Telefono",
Data.SqlDbType.NVarChar, 13, "Telefono")
SqlCommand1.Parameters.Add("@Email",
Data.SqlDbType.NVarChar, 50, "Email")
SqlCommand1.Parameters.Add("@Direccion",
Data.SqlDbType.NVarChar, 100, "Direccion")
SqlCommand1.Parameters.Add("@Ciudad",
Data.SqlDbType.NVarChar, 50, "Ciudad")
SqlCommand1.Parameters.Add("@Provincia",
Data.SqlDbType.NVarChar, 50, "Provincia")
SqlCommand1.Parameters.Add("@CP", Data.SqlDbType.NChar, 5,"CP")
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
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.
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
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.
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
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
A continuación, despliegue el objeto Tablas y seleccione las tablas Alquileres y Socios como
se indica en la figura
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
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.
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.
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
En este caso, la ventana de Orígenes de datos quedará informada tal y como se indica
en la figura
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
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
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
Una vez que tenemos las tabla maestra y detalle preparadas para utilizarlas, las añadiremos
al formulario Windows para que tengan el funcionamiento esperado.
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.
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
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
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
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.
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
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.
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.
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
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
Si queremos agregar datos, deberemos hacer clic sobre la opción Agregar nuevo del
control BindingNavigator como se muestra en la figura
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.
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
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.
Vamos a trabajar por pasos el primero paso por supuesto es abrir VISUAL BASIC.NET.
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:
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 BDejemplo.mdf aquí
pueden ver el ejemplo en pantalla:
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:
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.
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
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:
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,
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:
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
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.
dt.Fill(ds.alumnos)
DGWdatos.DataSource = ds.alumnos
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
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.
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.
DISEÑO DE FORMULARIO:
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
Código fuente
Try
' si está vacio salir y no retornar nada
If BindingSource1.DataSource Is Nothing Then
Return -1
End If
' Ejecutar el método Find pasándole los datos
Dim fila As Integer = BindingSource.Find(Columna.Trim, texto)
' Mover el cursor a la fila obtenida
BindingSource.Position = fila
' retornar el valor
Return fila
' errores
Catch ex As Exception
MsgBox(ex.Message.ToString, MsgBoxStyle.Critical)
End Try
' no retornar nada
Return -1
End Function
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
Option Explicit On
Catch ex As Exception
MsgBox(ex.Message.ToString)
Finally
Me.Cursor = Cursors.Default
End Try
End Sub
With DataGridView1
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
Solución:
Solución:
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. Ing.Variables
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