Documente Academic
Documente Profesional
Documente Cultură
1
Prólogo Unidad 30. Enumeraciones en VB
Introducción a la programación • 30.1. Objetivos del tema.
Unidad 1. Programación • 30.2. Introducción.
• 1.1. Objetivos del tema.
• 30.3. Creación.
• 1.2. Introducción.
• 30.4. Recorrido
• 1.3. Elementos de programación.
• 30.5. Conclusiones.
• 1.4. Lo principal de un programador. Unidad 31. Colecciones
• 1.5. Características. • 31.1. Objetivos del tema.
• 1.6. Problemas en los programas. • 31.2. Introducción.
Unidad 2. Estructura y representación de un programa • 31.3. Motivos para el uso de una colección.
• 2.1. Objetivos del tema.
• 31.4. Direccionamiento en una colección.
• 2.2. Introducción.
• 31.5. Operaciones con una colección.
• 2.3. Escribir un programa.
• 31.6. Tipos de colección.
• 8.8. Iniciar.
Unidad 37. Archivos
• 8.9. Crear un nuevo proyecto.
• 37.1. Objetivos del tema.
• 8.10. Estructura de un programa VB.
• 37.2. Introducción.
• 8.11. Ejecutar el programa.
• 37.3. Gestión de los archivos.
2
• 8.12. Añadir una clase. • 37.4. Estructura de un archivo.
• 8.13. Renombrar una clase. • 37.5. Tipos de archivos, por su direccionamiento.
• 8.14. Eliminar una clase del proyecto. • 37.6. Tipos de archivos, por su contenido.
Unidad 9. Procedimientos • 37.7. Tipos de archivos, por su duración en el tiempo.
• 9.1. Objetivos del tema. • 37.8. Estructuras de los registros.
• 9.2. Introducción. • 37.9. Actuaciones con archivos.
• 9.3. ¿Procedimientos o funciones? Unidad 38. Archivos en VB
• 9.4. Procedimientos. • 38.1. Objetivos del tema.
• 9.5. Ámbito de los procedimientos. • 38.2. Introducción.
• 9.6. Ambito de validez de las variables. • 38.3. Abrir, acceder al archivo.
• 9.7. Paso de variables a los procedimientos. • 38.4. Grabar.
• 9.8. Formas de paso de datos a los procedimientos. • 38.5. Leer.
• 9.9. Uso de variables en los procedimientos. • 38.6. Cerrar.
• 9.10. Públicos o privados. • 38.7. Matices.
Unidad 10. Primer programa en VB, procedimientos Unidad 39. Archivos secuenciales, formatos
• 10.1. Objetivos del tema. • 39.1. Objetivos del tema.
• 10.2. Introducción. • 39.2. Introducción.
• 10.3. Primer ejercicio. • 39.3. Formatos.
• 10.4. Parámetros en los procedimientos. • 39.4. Estructuras.
• 10.5. Estructuras en los procedimientos. • 39.5. Escritura.
• 10.6. Conclusiones. • 39.6. Lectura.
Unidad 11. Funciones • 39.7. Ejemplos de formatos.
• 11.1. Objetivos del tema. • 39.8. Utilización.
• 11.2. Introducción. • 39.9. Actualización.
• 11.3. Creación. Unidad 40. Archivos secuenciales en VB
• 11.4. ¿Funciones o Procedimientos.? • 40.1. Objetivos del tema.
• 11.5. Tipos de la función. • 40.2. Introducción.
• 11.6. Ámbito de las funciones. • 40.3. Abrir un archivo.
• 11.7. Paso de variables a las funciones. • 40.4. Grabar una estructura de datos.
• 11.8. Formas de paso de datos a las funciones. • 40.5. Leer un registro.
• 11.9. Estructura de una función. • 40.6. Lectura de un archivo secuencial.
Unidad 12. Funciones en VB • 40.7. Proceso de actualización.
• 12.1. Objetivos del tema. • 40.8. Cierre
• 12.2. Introducción. Unidad 41. Archivos Random
• 12.3. Escribir la función. • 41.1. Objetivos del tema.
• 12.4. Envío y recepción de los datos. • 41.2. Introducción.
• 12.5. Conclusiones. • 41.3. Registros.
Unidad 13. Las clases en los datos • 41.4. Acceso a los registros.
• 13.1. Objetivos del tema. • 41.5. Ubicación de los registros.
• 13.2. Introducción. • 41.6. Libre u ocupado.
• 13.3. Datos. • 41.7. Diseño del registro.
• 13.4. Datos internos, variables. • 41.8. Cómo diseñar los registros.
• 13.5. Datos externos, propiedades. • 41.9. Utilización.
• 13.6. Ambito de los datos. • 41.10. Altas, inserción.
• 13.7. Conclusiones. • 41.11. Modificación, actualización.
Unidad 14. Clases en VB • 41.12. Borrado, eliminación.
• 14.1. Objetivos del tema. • 41.13. Proceso del archivo.
• 14.2. Introducción. • 41.14. Resumen de acciones.
• 14.3. Crear la clase. • 41.15. Comentarios.
• 14.4. El objeto. Unidad 42. Archivos Random en VB
• 14.5. Los datos. • 42.1. Objetivos del tema.
• 14.6. Inicializar el objeto. • 42.2. Introducción.
• 14.7. Creemos un objeto. • 42.3. Abrir el archivo.
• 14.8. Cómo gestionar las propiedades, los datos. • 42.4. Definir la estructura de un registro.
• 14.9. Propiedades solo lectura. • 42.5. Lectura.
• 14.10. Propiedades solo escritura. • 42.6. Grabación de un registro.
• 14.11. Utilizar los datos, las propiedades. • 42.7. Inserción, Alta.
• 14.12. Clase como estructura de datos. • 42.8. Modificación, actualización.
• 14.13. Conclusiones. • 42.9. Baja eliminación.
• 42.10. Bucle de lectura.
3
Unidad 15. Las clases en el código • 42.11. Integrar todas las acciones.
• 15.1. Objetivos del tema. • 42.12. Conclusiones.
• 15.2. Introducción. Utilizando entorno gráfico
• 15.3. Código en la clase. Unidad 43. Programación en un entorno gráfico
• 15.4. En las Propiedades. • 43.1. Preliminares.
• 15.5. En las Funciones, Procedimientos. • 43.2. Objetivos del tema.
• 15.6. En los Métodos. • 43.3. Introducción.
• 15.7. Creamos un método. • 43.4. Propiedades.
• 15.8. Métodos, procedimientos. • 43.5. Eventos.
• 15.9. Métodos, funciones. • 43.6. Métodos.
• 15.10. Conclusiones. • 43.7. Objetos.
Unidad 16. Clases, Código en VB • 43.8. Tipos de ventanas, formularios.
• 16.1. Objetivos del tema. • 43.9. Crear un programa.
• 16.2. Introducción. • 43.10. Fases de un programa.
• 16.3. Código en las Funciones, Procedimientos. Unidad 44. ¿Cómo se hace un programa?
• 16.4. Código en los Métodos. • 44.1. Objetivos del tema.
• 16.5. Métodos, procedimientos. • 44.2. Introducción.
• 16.6. Métodos, funciones. • 44.3. Interfaz de usuario.
• 16.7. Conclusiones. • 44.4. Diseñar la interfaz.
Unidad 17. Ciclo de vida de una clase • 44.5. Escribir el código.
• 17.1. Objetivos del tema. • 44.6. Complementos.
• 17.2. Introducción. • 44.7. Inicio del programa.
• 17.3. Iniciar la clase, crear una instancia. • 44.8. Finalización del programa.
• 17.4. Proteger nuestra clase. Unidad 45. Objetos, mostrar datos
• 17.5. Ejecución de la clase. • 45.1. Objetivos del tema.
• 17.6. Finalización de la clase. • 45.2. Introducción.
Unidad 18. Ciclo de vida de una clase en VB • 45.3. Etiqueta, Label.
• 18.1. Objetivos del tema. • 45.4. Visualizar imágenes.
• 18.2. Introducción. • 45.5. Grupos de objetos.
• 18.3. Iniciar la clase, crear una instancia. Unidad 46. Objetos, el teclado
• 18.4. Proteger nuestra clase. • 46.1. Objetivos del tema.
• 18.5. Ejecución de la clase. • 46.2. Introducción.
• 18.6. Finalización de la clase. • 46.3. Caja de texto, text box.
Unidad 19. La herencia en las clases • 46.4. Filtrado.
• 19.1. Objetivos del tema. • 46.5. Validaciones.
• 19.2. Introducción. • 46.6. Ejemplo de filtrado en el tratamiento de teclado.
• 19.3. Clase base, origen. • 46.7. Validación.
• 19.4. Clase derivada. Unidad 47. Botones de órdenes
• 19.5. Tipos de herencia. • 47.1. Objetivos del tema.
• 19.6. Sobre escritura. • 47.2. Introducción.
• 19.7. Limitaciones en la herencia. • 47.3. Características.
• 19.8. Conclusiones. • 47.4. Utilización.
Unidad 20. La herencia en las clases en VB Unidad 48. Seleccionar una opción
• 20.1. Objetivos del tema. • 48.1. Objetivos del tema.
• 20.2. Introducción. • 48.2. Introducción.
• 20.3. Clase base, origen. • 48.3. Características.
• 20.4. Clase derivada. • 48.4. RadioButton, utilización.
• 20.5. Resultado de la herencia. • 48.5. CheckBox, utilización.
• 20.6. Referencias en el código de una clase, MyClass, MyBase, Me. Unidad 49. Selección de datos
• 20.7. Limitaciones en la herencia. • 49.1. Objetivos del tema.
Unidad 21. La sobrecarga en las clases • 49.2. Introducción.
• 21.1. Objetivos del tema. • 49.3. Características.
• 21.2. Introducción. • 49.4. Utilización.
• 21.3. Creación. Unidad 50. Los menús
• 21.4. Conclusiones. • 50.1. Objetivos del tema.
Unidad 22. La sobrecarga en las clases en VB • 50.2. Introducción.
• 22.1. Objetivos del tema. • 50.3. Menús.
• 22.2. Introducción. • 50.4. Creación del menú clásico.
• 22.3. Creación. • 50.5. Creación de un menú contextual.
4
• 22.4. Conclusiones. • 50.6. Barra de herramientas.
Unidad 23. Cómo programar una clase Unidad 51. Cuadros de diálogo
• 23.1. Objetivos del tema. • 51.1. Objetivos del tema.
• 23.2. Introducción. • 51.2. Introducción.
• 23.3. Utilización de las clases. • 51.3. Abrir archivo.
• 23.4. Como escribir una clase. • 51.4. Guardar archivo.
• 23.5. Declarar un objeto de nuestra clase. • 51.5. Seleccionar impresora.
• 23.6. Asignar valores a las propiedades de la clase. • 51.6. Seleccionar color.
• 23.7. Variables públicas. • 51.7. Seleccionar fuente.
• 23.8. Desarrollar los métodos de la clase. • 51.8. Grabar los resultados.
• 23.9. Utilización de los objetos de una clase. Unidad 52. Otros objetos
• 23.10. Secuencia de uso de un objeto. • 52.1. Objetivos del tema.
• 23.11. Recuperar los recursos utilizados que están libres. • 52.2. Introducción.
Unidad 24. Cómo programar una clase en VB • 52.3. Barra de progresión.
• 24.1. Objetivos del tema. • 52.4. Incremento numérico.
• 24.2. Introducción. • 52.5. Pestañas.
• 24.3. Declarar un objeto de esa clase. • 52.6. Calendario, DateTimePicker.
• 24.4. Asignar valores a las variables de la clase. Unidad 53. DataGrid
• 24.5. Asignar valores a las propiedades de la clase. • 53.1. Objetivos del tema.
• 24.6. Utilización de los objetos de una clase. • 53.2. Introducción.
• 24.7. Secuencia de uso de un objeto. • 53.3. Formas de utilización.
• 24.8. Recuperar los recursos utilizados que están libres, clase GC. • 53.4. Configuración.
Unidad 25. Utilizar clases • 53.5. Crear la estructura del Grid.
• 25.1. Objetivos del tema. • 53.6. Carga de datos.
• 25.2. Introducción. • 53.7. Borrado de datos.
• 25.3. Cuando utilizar las clases. • 53.8. Edición.
• 25.4. Para que utilizar las clases. • 53.9. Recorrido.
• 25.5. Las clases como estructuras de datos. • 53.10. Intercambio de filas.
• 25.6. Como incluir una clase en nuestra aplicación. • 53.11. Objetos ComboBox.
Unidad 26. Utilizar clases en VB • 53.12. Objetos ChekBox.
• 26.1. Objetivos del tema. • 53.13. Mensajes de ayuda.
• 26.2. Introducción. • 53.14. El evento CellFormatting.
• 26.3. Compilar la clase, primer paso. Unidad 54. Impresión
• 26.4. Como incluir una clase en nuestra aplicación. • 54.1. Objetivos del tema.
Unidad 27. Utilizar y definir datos • 54.2. Introducción.
• 27.1. Objetivos del tema. • 54.3. Secuencia de funcionamiento.
• 27.2. Introducción. • 54.4. Fases de un listado.
• 27.3. Tipos de datos. • 54.5. Procedimientos.
• 27.4. Tipos de usuario. • 54.6. El conjunto.
• 27.5. Ventajas. • 54.7. Más situaciones.
• 27.6. Anidamiento de los tipos de usuario. • 54.8. Acabando.
• 27.7. ¿Dónde utilizar los tipos de usuario.? Unidad 55. Bases de datos
• 27.8. Conclusiones. • 55.1. Objetivos del tema.
• 27.9. Ejercicios propuestos. • 55.2. Introducción.
• 27.10. Solución a los ejercicios propuestos. • 55.3. Utilización.
Unidad 28. Utilizar y definir datos en VB • 55.4. Tipos de objetos.
• 28.1. Objetivos del tema. • 55.5. Las clases.
• 28.2. Introducción. • 55.6. Los objetos.
• 28.3. Tipos de datos. Unidad 56. Enlazar VB y MySQL
• 28.4. Declaración. • 56.1. Objetivos del tema.
• 28.5. Conversión de tipos. • 56.2. Introducción.
• 28.6. Nombres, estructuras. • 56.3. Objetos necesarios.
• 28.7. Tipos de estructuras. • 56.4. Utilización.
• 28.8. Ambito de las variables. • 56.5. Uso de VB con MySQL.
• 28.9. Tipos de usuario, estructuras. • 56.6. Creamos la base de datos.
• 28.10. Tipos de usuario anidados. • 56.7. Creamos las tablas.
• 28.11. Ventajas. • 56.8. Resto de acciones.
Unidad 29. Enumeraciones
• 29.1. Objetivos del tema.
5
• 29.2. Introducción.
• 29.3. ¿Qué son?
Ejercicios propuestos
• 1. Programación •
• 2. Estructura y representación de un programa • 20. La herencia en las clases en VB
• 3. Los datos • 22. La sobrecarga en las clases en VB
• 4. Las expresiones • 26. Utilizar clases en VB
• 5. Las instrucciones • 27. Utilizar y definir datos
• 6. Programa • 28. Utilizar y definir datos en VB
• 7. Las clases • 30. Enumeraciones en VB
• 10. Primer programa en VB, procedimientos • 32. Colecciones en VB
• 12. Funciones en VB • 34. Arrays en VB
• 14. Clases en VB • 38. Archivos en VB
• 16. Clases, Código en VB • 40. Archivos secuenciales en VB
• 18. Ciclo de vida de una clase en VB • 42. Archivos Random en VB
Prólogo.
Lo que deseamos en este curso es ofrecer un punto de entrada al mundo de la programación.
Un punto de entrada lo más asequible, pero serio, para quien quiera tomarlo como hobby lo pueda utilizar, quien desee introducirse en
ese mundo por curiosidad, pueda encontrar respuesta a algunas de sus dudas, y quien quiera comprobar si éste puede ser su futuro, pues lo
mismo.
Se van a hacer dos niveles, un primer nivel de iniciación a lo que son las estructuras básicas de programación y dar a conocer los
conocimientos básicos para realizar un buen programa.
Los conocimientos se van a dar sin depender del corsé de un lenguaje de programación, es decir se van a mostrar todas las herramientas
de programación, desde la unidad mínima de un dato, la variable, hasta llegar a lo que sería las bases de datos en el segundo nivel.
Pero claro, para poder aprender a ir en bici hay que tener una bicicleta, por lo tanto los conocimientos teóricos los tendremos que aplicar
en un lenguaje de programación, esa parte práctica se va a ver en Visual Basic en el entorno de .Net, concretamente Visual Basic 2005.
No entraremos en peleas de que lenguaje es más adecuado, o no, de los lenguajes existentes en el mercado, cada uno tiene su
aplicación y lo que hay que hacer es aplicarlos adecuadamente, personalmente pienso que lo que hay que saber es programar, y si conoces esa
técnica, después la podrás aplicar en cualquier lenguaje de programación.
Después de algunos años de programación, la técnica de programación ha evolucionado, pero los lenguajes han aparecido y
desaparecido.
1º Nivel
Iniciación a la programación.
Estructuras de programación.
Instrucciones.
Operadores.
Estructuras de datos.
Procedimientos.
Funciones.
Clases.
Arrays.
Listas.
Cadenas, strings.
2º Nivel
Programación en un entorno gráfico.
Eventos.
Propiedades.
Métodos.
Objetos.
Tipos de objetos.
Archivos secuenciales.
Archivos random.
Bases de datos.
6
Comunicaciones.
Formato del curso.
Huiremos de los excesos de texto, pero evidentemente, hay que explicarse, y eso solo se puede hacer así, escribiendo, pero vamos a
intentar a hacerlo lo menos pesado posible, o sea ameno, ya veremos.
Empezaremos sin aplicar ningún lenguaje en concreto, para aplicarlo posteriormente.
Los temas procuraremos que sean cortos, para que no se hagan pesados, así, tampoco se tiene que dedicar tiempo excesivo a la
materia.
Se irán publicando, o intentaremos, de forma que cada semana haya materia nueva, pero eso no indica que ese sea el ritmo a seguir, si
no que ese es el ritmo de lo que se puede ir preparando, así que sin agobiarse.
Contenidos del curso.
Los contenidos no son estancos, son acumulativos, por lo que un fallo de comprensión en el tema dos, implicará problemas en el resto de
contenidos.
No hay prisa, no se tienen plazos, no hay controles, exámenes o evaluaciones, la única prisa es la que se quiera usted marcar, pero eso
sí, no corra, es más importante comprender que correr.
Tipos o clases de programación.
Actualmente la programación que se genera es orientada a objetos. P. O. O.
Se basa en la generación de clases de las cuales se derivan posteriormente los objetos que son los que toman el protagonismo en el
programa.
Las clases en su interior lo que contienen en código, y ese código está escrito de una forma que denominamos estructurada, y como hay
que empezar la casa por el tejado, primero empezaremos con las vocales, aquello de “Mi mama me mima mucho”, y después ya leeremos a
Shespil, perdón a Shakespeare.
Ejercicios.
Vamos a exponer ejercicios sencillos, pero que son complicados, porque la dificultad radica no en entenderlos, que la mayoría serán
fáciles de entender, si no en que hay que resolverlos, y no hay que pensar eso es muy fácil, me paso al siguiente, hay que resolverlo, porque de
esa forma se van afianzando los conocimientos.
Los ejercicios, en más de una ocasión, su única dificultad radicará en su excesiva facilidad aparente, y que nos llevará a mentalmente
decirnos, eso es muy fácil, voy a hacer el siguiente.
La resolución de los ejercicios se puede hacer por el sistema que cada uno estime más oportuno, como ya veremos más adelante, con
seudocódigo o con ordinogramas, escritos o gráficamente.
Basta de moralina, empecemos y como dicen siempre, todo esto está sujeto a modificación sin previo aviso.
Técnica.
Diseño.
Imaginación.
Técnica, que se puede aprender, y que es lo que se quiere enseñar en este curso de iniciación.
Diseño, estilo, gusto, que es más difícil enseñarlo, pues es una cuestión personal, y se trata de ofrecer nuestro producto en un formato
agradable para quien lo va a utilizar.
Imaginación, conocida la técnica de programación, está capacidad se puede adquirir con la experiencia, es más difícil, porque la
capacidad de poder crear, imaginar la solución, o forma en la cual se desea plantear o mostrar lo que se quiere obtener, es una capacidad
individual que cada uno tiene más o menos desarrollada.
Estos elementos nos permitirán combinar otros tres elementos, que son
El hardware, el ordenador.
Los procedimientos, funciones, clases y objetos.
Las estructuras de datos.
Hardware, conocer los distintos elementos con los que se puede contar para poder llegar a obtener una solución optima a nuestro
problema.
En programación hay una gran variedad de tipos de programas, y un amplio espectro de periféricos en el mercado.
Su conocimiento nos puede facilitar la solución de un problema.
Procedimientos, funciones, son las herramientas de las que nos valemos en la programación para la resolución de un programa, para
resolver un problema.
Estructuras de datos, los dos elementos anteriores nos permiten sacar el rendimiento de un programa, pero un programa utiliza datos,
pocos o muchos, pero siempre información, por lo tanto hay que manejar de forma adecuada dicha información.
1.3. Elementos de programación.
Podríamos denominar los siguientes apartados como elementos de la programación.
7
– Tener claro que queremos hacer.
– Dominar los elementos a nuestro alcance.
– Imaginar espacialmente la solución que deseamos obtener.
– Aplicar dicha solución.
Tener claro que queremos hacer, en condiciones normales, la creación de un programa parte de una fase de diseño que da como
resultado final como tiene que ser un programa y lo que hay que hacer es transcribir a código dicho resultado.
Por lo tanto antes de iniciar la escritura de un programa es imprescindible saber de forma clara y sin paliativos que es lo que queremos
hacer, si una silla o un barco.
Normalmente una buena aplicación suele conllevar un ahorro en el tiempo final, por que no hay que retroceder ni tampoco corregir.
Dominar los elementos a nuestro alcance, implica tener un conocimiento y dominio de los elementos mencionados anteriormente.
Imaginar espacialmente la solución que deseamos obtener, la progresión en la técnica de la programación, con el tiempo nos llevará a
imaginar, por decirlo de alguna forma, la solución o la forma de enfocar como deseamos hacer el programa que nos encargan, pero eso a otro
nivel, os irá pasando a lo largo del curso, ya que con los ejercicios que iremos planteando, a medida que los vayamos leyendo de forma
inconsciente os ira apareciendo la forma de enfocarlos.
Aplicar dicha solución, y solo quedará con todos los datos aplicarlos a la solución que en principio creemos más adecuada, y que luego
modificaremos muchas veces.
Hay un principio, “si funciona no lo toques”, pero claro ..., así que cada cual decida cuando parar.
Levantarse
Asearse
Desayunar
Realizar las actividades matutinas
Almorzar ...
Existe varias formas de representar un programa de forma previa a su codificación y a partir de los datos que nos entregan como
consecuencia de la fase previa de análisis.
Seudocódigo
Ordinogramas.
Inicio
Escribir “Cálculo del área de un triángulo”
Como se puede comprobar, es una forma sencilla de describir un programa en un formato muy próximo al ser humano, pero también se
puede desarrollar de forma gráfica.
9
Y a continuación vemos el ejemplo de antes representado mediante organigrama.
Ambos sistemas son válidos, cada cual puede elegir el que más le guste.
Pág. 2.1
Instrucción Escribir
Literal “Cálculo …”
El fin de ésta instrucción es el de poder comunicarse con la persona que está utilizando el programa, y poder emitir mensajes, de ayuda,
de título, etc…
Instrucción Leer
Literal “Introduzca …”
Dato Base
El fin de ésta instrucción es el de poder recibir datos por teclado desde la persona que está utilizando el programa.
Inicio
.. / ..
Fin
10
Esta es la forma de delimitar el programa en su inicio y final, cada lenguaje dispone de una sintaxis más o menos similar, Begin End,
Todos los programas de una u otra forma tienen delimitado donde empieza y donde acaban, el sistema cambia en función de la sintaxis
de cada uno de los lenguajes de programación.
Los programas no son solamente como lo visto en el ejemplo, son algo más complejos e incorporan estructuras que ya incorporaremos
más adelante.
Pág. 2.2
Ejercicios unidad 2: Estructura y representación de un programa
Siguiendo cualquiera de los dos sistemas expuestos, realizar los siguientes ejercicios.
1º Introducir dos números y calcular la suma de los mismos, visualizando el resultado final. Repetir para la resta y la
multiplicación.
2º Hallar el área y la longitud de una circunferencia, solicitando el radio de la misma R . Area = PI * R al cuadrado,
Longitud = 2 * PI * R .
3º Hallar el área de un triángulo. Area = Base por Altura / 2.
4º Introducir un número A y calcular B. B= A * (A+5) / A + (A*5), comprobar el resultado.
El dato numérico utilizará en memoria un espacio adecuado para el valor que puede tomar.
Como la memoria en un ordenador es vital, conviene aprovecharla al máximo.
Un valor numérico puede tomar un valor desde cero, olvidemos los números negativos, hasta ...., hasta un valor que es imposible escribir,
o sea, infinito.
Pero eso en un ordenador es imposible de asumir.
Por lo tanto lo que hacemos es que creamos rangos, y a cada rango le asignamos un tipo de dato.
11
¿Cómo se crean los rangos?
Pensemos en que un ordenador solo sabe utilizar un uno y un cero, ausencia de voltaje y presencia de voltaje
eléctrico, sistema binario, pero nosotros utilizamos lo que denominamos el sistema decimal, es decir diez elementos en
lugar de dos.
En este sistema, cada uno de los dígitos utilizados se denomina bit, (Binary digit).
Por lo tanto para almacenar un número del cero al nueve, necesitaremos una combinación de ceros y unos que
permitan representar cada uno de esos números, y como son diez, se necesitan diez combinaciones.
0 0
1 1
2 10
3 11
4 100
5 101
6 110
7 111
8 1000
9 1001
Esa sería la combinación para representar los diez dígitos del cero al nueve.
Cada uno de esos dígitos los denominamos bits, por lo tanto el cinco necesita tres bits para representarlo.
Si siguiéramos esa secuencia podríamos ir creando todos los números decimales en binario.
1 bit.
4 bit un cuarteto.
8 bit un octeto, un octeto es un byte.
1024 bytes, es un Kilobyte. Kb.
1024 Kb son un Megabyte, Mgb
1024 Mgb. son un Gigabyte.
Si nos preguntamos porque se usa 1024 en lugar de 1000, la respuesta es que hay que buscar bloques de 8 bits,
que son un byte, 1024 es 2 10 .
Los datos alfanuméricos no tiene problema en su representación, pues cada carácter ocupa un byte en memoria,
tantos caracteres tantos bytes, dentro de las limitaciones del lenguaje de programación que se este utilizando.
El motivo de utilizar un byte para cada carácter es que el número de caracteres máximo distintos en un idioma
latino, o anglosajon, tomando los números como caracteres independientes, incluidos letras acentuadas y caracteres de
puntuación no supera los 256, con un byte podemos obtener 256 combinaciones distintas, del 0 al 255.
Actualmente se utiliza un sistema de dos bytes que de forma unilateral implanto una empresa de software, por lo
cual, aunque nosotros usemos un carácter para almacenarlo se utilizarían dos.
Esto permite que se puedan representar hasta 65535 combinaciones de símbolos, necesario para los lenguajes
orientales, que usan símbolos en lugar de letras.
Pero los números son datos compactos, no se pueden andar separando de forma arbitraria, ya que hay que realizar
operaciones de cálculo con ellos, por lo tanto han de ocupar uno, dos o x bytes, pero contiguos, para así poder operar
matemáticamente.
Por lo tanto los números que podemos representar en un sistema dependerá del número de bytes que pongamos
juntos para representar ese número.
Por ejemplo si ponemos un solo byte a disposición del sistema, solo podremos representar números entre el 0 y el
255. Un byte son 8 bits, las combinaciones son 28 que es igual a 256, que son los números que podemos representar.
Como eso es muy pobre, el rango más pequeño que se utiliza es el de dos bytes, que permiten manejar números
entre –32767 y + 32768, como números enteros.
Aunque eso parece un rango muy pequeño, en programación los números enteros se usan para contar cosas, y en
un porcentaje muy elevado de casos es suficiente ese rango, siempre que se haga un uso adecuado de los recursos.
Claro la pregunta sale sola ¿ pero números hay .... ? , claro que hay más, pero esos ya se han dado en clasificar en
otro tipo de datos, los llamados números reales.
12
Los números reales se representan con otro sistema, no creeremos que se puede asignar espacio en memoria para
el número 12345678901234567890, o bien para el 0,12345678901234567890, eso no es factible.
Por lo tanto en función del tamaño del espacio usado en memoria se puede abarcar más o menos valores.
Esta tabla muestra los valores máximos y mínimos en función del número de bytes utilizados en lun lenguaje de
programación..
Pensemos que hace años un número entero utilizaba dos bytes, ahora en los lenguajes modernos utiliza 4, por lo
que se aumenta el número de valores posibles válidos.
Pág. 3.1
Unidad 3. Los datos (II)
Bytes Máximo Mínimo
Byte números 1 255 0
Booleano 2 True False
Integer rangos 2 32,767 -32,768
Long Entero largo 4 2,147,483,647 -2,147,483,648
Single precisión números 4 3.402823E+38 1.401298E-45
(positivos)
Single precisión 4 -1.401298E-45 -3.402823E+38
números(negativos)
Double precisión 8 1.797693134862315D+308 4.940656458412465D-324
números(positivos)
Double precisión números 8 -4.940656458412465D- -
(negativos) 324 1.797693134862315D+308
Pero para representar las letras sucede lo mismo, también hay que buscar una combinación de ceros y unos.
Y como además hay que representar otra serie de caracteres de control que se utilizan en otras tareas, todos y cada uno de ellos necesita
de una representación en binario de su valor en el sistema o idioma que nosotros utilizamos.
La suma de todos esos números, letras y caracteres de control aproximadamente es de unos 170 elementos.
13
2º En este caso un Integer sería suficiente, un teatro es un recinto pequeño, no llegará nunca a los 65000, o 32767
si utilizamos signo, espectadores.
3º Dado el número posible de valores que puede alcanzar el resultado sería multiplicar 24 * 60 * 1000 que daría
como resultado un tipo de dato Long.
4º En el momento que utilizamos texto, el tipo de dato es obligatoriamente alfanumérico.
Los números se pueden representar también como datos alfanuméricos, al fin y al cabo la “A” es un carácter igual que el “1”, pero
entonces no podemos operar matemáticamente con él.
La expresión es la unión de una serie de variables unidas por operadores que expresan una condición, un cálculo, una comparación.
En estas expresiones los operadores se evalúan en el siguiente orden,
Cuando hay expresiones que contienen operadores de más de una categoría, se resuelven antes las que tienen operadores aritméticos, a
continuación las que tienen operadores de comparación y por último las de operadores lógicos.
Los operadores de comparación tienen todos la misma prioridad; es decir, se evalúan de izquierda a derecha, en el orden en que
aparecen. Los operadores lógicos y aritméticos se evalúan en el siguiente orden de prioridad:
Tipos de operadores.
Aritméticos Relacionales Operadores lógicos
Exponenciación Igualdad Negación lógica
Negación Desigualdad, distinto Conjunción
Multiplicación y división Menor que Disyunción
División de enteros Mayor que Exclusión lógica
Módulo aritmético (Mod) Menor o igual que Equivalencia
Adición y substracción Mayor o igual que Implicación
En cada lenguaje de programación cada operador tiene un símbolo asignado, en la mayoría coinciden, pero hay algunos que cambian de
forma significativa, por lo que cuando se entre en cada lenguaje se expondrán los mismos.
Cuando hay multiplicación y división en la misma expresión, cada operación se evalúa a medida que aparece, de izquierda a derecha. Del
mismo modo, cuando se presentan adiciones y substracciones en una misma expresión, cada operación se evalúa tal como aparecen de
izquierda a derecha. Es posible usar paréntesis para saltar el orden de preferencia y forzar que algunas partes de una expresión se evalúen antes
que otras. Las operaciones entre paréntesis se realizan antes que las de fuera. Sin embargo, dentro de los paréntesis, la precedencia de los
operadores se mantiene.
El operador de concatenación de cadenas (&) o (+) no es realmente un operador aritmético, pero en orden de prioridad se encuentra a
continuación de todos los operadores aritméticos y antes que todos los operadores de comparación.
14
4.4. ¿Como se distinguen los tipos de variable?
La diferenciación entre un tipo y otro de variables, se realiza de dos formas básicamente,
En la creación a la hora de definirlas se les asigna un tipo, pero el nombre no lleva ningún carácter
identificativo,
En la creación a la hora de definirlas se les asigna un tipo y además el nombre lleva un carácter que la
identifica como tal tipo, si se utiliza el sistema de notación hungara.
La notación hungara, consiste en prefijos en minúsculas que se añaden a los nombres de las variables, y que
indican su tipo.
El resto del nombre indica, lo más claramente posible, la función que realiza la variable.
Pág. 4.1
Con el fin de poder realizar los ejemplos, se han utilizado los símbolos que se utilizan en Visual Basic.
1 Aritméticos.
Para indicar cálculos de tipo matemático.
Suma +
Resta -
Multiplicación *
División /, División entera, o DIV
Resto división Mod
Raíz cuadrada Sqr
Exponenciación ^
Ejemplos.
Variable = Variable + 1 Suma y además es un Contador.
Variable = Variable + OtraVariable Suma, y lo llamamos Acumulador.
Variable = Variable * 3 + OtraVariable
2 Lógicos.
And, Or, Not, Xor, Imp. Eqv
Los operadores lógicos unen dos o más condiciones para formar una única expresión.
2.1 And.
Se utiliza para efectuar una conjunción lógica de dos expresiones.
Sintaxis
resultado = expresión1 And expresión2
Parte Descripción
resultado Obligatorio; cualquier variable numérica.
Comentarios
Si y sólo si ambas expresiones se evalúan como True, el resultado es True. Si cualquiera de las expresiones es
False, el resultado es False. La siguiente tabla ilustra cómo se determina el resultado:
2.2 Or.
Se utiliza para ejecutar una disyunción lógica sobre dos expresiones.
Sintaxis
resultado = expresión1 Or expresión2
Parte Descripción
resultado Obligatorio; cualquier variable numérica.
Comentarios
Si cualquiera de las expresiones, o ambas, es True, el resultado es True. La siguiente tabla indica cómo se
determina el resultado:
La tabla de verdad es:
Expresión1 Expresión2 Resultado
True True True
True False True
False True True
False False False
El operador Or ejecuta una comparación bit a bit para identificar los bits de dos expresiones numéricas que tienen la
misma posición y establece el bit correspondiente en el resultado según la siguiente tabla de decisión lógica:
La tabla de verdad es:
Bit1 Bit2 Resultado
0 0 0
0 1 1
1 0 1
1 1 1
Pág. 4.2
Sintaxis
resultado = Not expresión
Parte Descripción
resultado Obligatorio; cualquier variable numérica.
expresión Obligatorio; cualquier expresión.
Comentarios
La siguiente tabla muestra cómo se determina el resultado:
Expresión Resultado
Trae False
False True
Además, el operador Not invierte los valores de bit de cualquier variable y establece el bit correspondiente en
resultado, de acuerdo con la siguiente tabla de decisión lógica:
La tabla de verdad es:
16
Bit1 Resultado
0 1
1 0
2.4 Xor.
Se utiliza para realizar una exclusión lógica entre dos expresiones.
Sintaxis
[resultado =] expresión1 Xor expresión2
Parte Descripción
resultado Obligatorio; cualquier variable numérica.
Comentarios
Si una y sólo una de las expresiones es True, el resultado es True. Sin embargo, si cualquiera de las expresiones es
Null, el resultado es también Null. Cuando ninguna de las expresiones es Null, el resultado se determina de acuerdo con la
siguiente tabla:
La tabla de verdad es:
Expresión1 Expresión2 Resultado
True True False
True False True
False True True
False False False
El operador Xor funciona como operador lógico y bit a bit. Ejecuta una comparación bit a bit para identificar los bits
de dos expresiones utilizando lógica de O exclusivo para obtener el resultado, según la siguiente tabla de decisión lógica:
La tabla de verdad es:
Bit1 Bit2 Resultado
0 0 0
0 1 1
1 0 1
1 1 0
Pág. 4.3
Unidad 4. Las expresiones (IV)
2.5 Imp.
Se utiliza para efectuar una implicación lógica de dos expresiones.
Sintaxis
resultado = expresión1 Imp expresión2
Parte Descripción
resultado Obligatorio; cualquier variable numérica.
Comentarios
La siguiente tabla ilustra cómo se determina el resultado:
La tabla de verdad es:
Expresión1 Expresión2 Resultado
True True True
True False False
False True True
False False True
El operador Imp ejecuta una comparación bit a bit para identificar los bits de dos expresiones numéricas que tienen
la misma posición y establece el bit correspondiente en el resultado según la siguiente tabla de decisión lógica:
La tabla de verdad es:
Bit1 Bit2 Resultado
0 0 1
0 1 1
1 0 0
1 1 1
17
2.6 Eqv.
Se utiliza para efectuar una equivalencia lógica de dos expresiones.
Sintaxis
resultado = expresión1 Eqv expresión2
Parte Descripción
resultado Obligatorio; cualquier variable numérica.
Comentarios
Si cualquiera de las expresiones es de tipo Null, el resultado es también Null. Si ninguna de las expresiones es Null,
el resultado se determina según la siguiente tabla:
La tabla de verdad es:
Expresión1 Expresión2 Resultado
True True True
True False False
False True False
False False True
El operador Eqv ejecuta una comparación bit a bit para identificar los bits de dos expresiones numéricas que tienen
la misma posición y establece el bit correspondiente en el resultado según la siguiente tabla de decisión lógica:
La tabla de verdad es:
Bit1 Bit2 Resultado
0 0 1
0 1 0
1 0 0
1 1 1
3 Cadenas, strings.
El símbolo utilizado habitualmente es el + y el &, que no representa una suma, sino la concatenación o unión de dos variables
alfanuméricas, creando una nueva con el contenido de ambas.
4 Relacionales
>, >=, <>, <, <=, =.
Son los símbolos que se usan en una comparación para indicar como hacerla, si A ha de ser mayor que B, etc.…
El ejemplo completo.
18
Valor 1 4 10 3,141592 2.718281
Variable X Y Z Pi E
Evaluar las siguientes expresiones, para los valores anteriores.
1º 2 * X + 0.5 * Y - 1/5 * Z
2º Pi * Y 2 > Y OR 2 * Pi * X < = Z
3º E (X - 1) / ( X * Z ) / ( X / Z)
4º “Don ” + “Juan”= “Don Juan” Or “A”= “a”
5º X - Y + Z + Pi - E + 2.576689
6º (-3) * X+2*Y-1 / 2*z
7º 2 * Y 2 - 6 * Y + 12
8º (2 * Y) 2 - 6 * Y + 12
9º (Y(2*X) - 6 * (Z / 10 ) ) / 2
10º X>3 AND Y = 4 or X + Y <= Z
11º X>3 AND (Y= 4 or X + Y >= Z)
12º NOT “METODO”+”LOGIA” = “LOGIA”+”METODO”
Se escribe (-3) * X + 2 * Y - 1 / 2 * Z
Se evalúa (-3) * X + 2 * Y - 1 / 2 * Z
-3 + 2 * Y - 1 / 2 * Z
-3 + 8 - 1 / 2 * Z
-3 + 8 - 0.5 * Z
-3 + 8 - 5
5-5
Resultado 0
19
Se escribe 2 * Y ^ 2 - 6 * Y + 12
Se evalúa 2 * Y ^ 2 - 6 * Y + 12
2 * 16 - 6 * Y + 12
32 - 6 * Y + 12
32 - 24 + 12
8 + 12
Resultado 20
Se escribe (2 * Y) 2 - 6 * Y + 12
Se evalúa (2 * Y )2 - 6 * Y + 12
82 - 6 * Y + 12
64 - 6 * Y + 12
64 - 24 + 12
40 + 12
Resultado 52
Se escribe (Y(2*X) - 6 * (Z / 10 ) ) / 2
Se evalúa (Y(2*X) - 6 * (Z / 10 ) ) / 2
(Y 2 - 6 * (Z / 10 ) ) / 2
(Y 2 - 6 * 1) / 2
(16 - 6 * 1) / 2
(16 - 6) / 2
10 / 2
Resultado 5
20
1 Símbolos.
En un tema anterior pusimos los símbolos más utilizados en los organigramas.
Cada uno de esos símbolos se traduce en una instrucción en un programa.
A=A+B
Realizar una entrada o salida de datos desde o hacia un dispositivo, que no se especifica de forma explicita.
Realizar una entrada o salida de datos desde o hacia un dispositivo que es de acceso direccionable, normalmente un
disco duro.
Conector dentro de página, la flecha apunta a un símbolo que está en la misma página.
Conector fuera de página, la flecha apunta a un símbolo que está fuera de la pagina actual.
2 Estructuras.
Cuando creamos un programa, creamos una estructura que se va ejecutando de forma lineal y en determinados momento necesitamos
tomar decisiones, o hacer que algo se repita.
3 Lineal, secuencial.
Si volvemos a los ejercicios que realizamos al principio, aunque aun no hayamos utilizado ningún lenguaje, podremos ver
como de forma instintiva hemos utilizado instrucciones de forma lineal con expresiones.
Cada símbolo del organigrama, o cada línea del seudo código es una instrucción.
La estructura que se ha utilizado en esos ejercicios es una estructura lineal.
La imagen que tenemos a la derecha es un ejemplo de estructura secuencial, si nos fijamos en los símbolos del organigrama,
veremos que no hay ninguna acción de repetición, no hay ninguna flecha que vuelva hacia arriba a un punto por el que ya hemos
pasado.
Tampoco hay ningún punto en el que se divida el programa entre dos posibilidades después de una pregunta.
Pág. 5.1
Las estructuras alternativas pueden tener dos salidas, cuando cumple, la derecha y cuando no cumple la
izquierda.
La parte de no se cumple, la izquierda, es optativa, es decir, no hay porque escribir una acción cuando una
condición no se cumple, a lo mejor solo nos piden que visualicemos los números primos, entonces si un número no es
primo pasaremos al siguiente y ya está, no hay por que hacer nada.
En un organigrama, cuando se usa un símbolo de decisión, es decir un “Si el número es primo”, la salida de la
derecha siempre es la que indicará la acción que se ejecutará cuando se cumpla la condición, salvo que se
indique mediante texto lo contrario.
En el ejemplo podemos observar como dentro de la pregunta de “Tiempo mayor que 180”, hay a su
vez otra condición en la que preguntamos por “Resto mayor que cero”.
5 Repetitivas.
Las estructuras repetitivas, permiten que se pueda ejecutar una parte del programa un número determinado de veces.
Cuantas veces nos han dicho, mientras no te comas la merienda, no iras con tus amigos a jugar al balón, - bueno ahora es a la
PlayStation-, o aquello de hasta que no te ordenes la habitación, no sales.
Pues hemos nombrado los dos tipos base de estructura repetitiva que existen, mientras y hasta.
Una estructura repetitiva esta formada por una serie de instrucciones que están escritas en el interior de otra
instrucción que permite que esas instrucciones se ejecuten un número determinado de veces, mientras se
cumple una condición, o hasta que se cumpla una condición.
Si observamos las imágenes veremos que en una la condición que controla cuando se ejecuta el
bucle, está al principio y en la otra está al final.
La diferencia permite que en un caso, mientras, While, solo se ejecuta las instrucciones del interior
del bucle si la condición se cumple al llegar al bucle.
En el caso del hasta, Repeat, las instrucciones del interior del bucle se ejecutarán siempre al
menos una vez, ya que la condición se analiza al final.
Los bucles mientras y repite, pueden usarse indistintamente, pero evidentemente el motivo de su
existencia es porque no siempre se pueden sustituir uno por el otro.
En los bucles, se realiza aquellas acciones que nos sean necesarias en el programa, pero una de las situaciones habituales es la de
realizar operaciones donde se cuentan, o se incrementan valores.
En los dos ejemplos que vemos a continuación, podemos observar como en los dos casos se realiza la misma acción, que es la de
visualizar unos valores que van de diez a veinte.
Sin embargo, si observamos los dos ejemplos, veremos como hay diferencias en el de la izquierda, el
número uno, la acción de incremento del contador, se realiza después de la acción de visualizar la variable X,
mientras que en la de la derecha, el número dos, es al revés.
SI seguimos observando los ejemplos, podemos ver como en un caso el valor inicial de X es diez, y en
el otro nueve.
Si seguimos observando, veremos que las condiciones de salida del bucle cambian, en un caso por
igual a veinte y en otro por ser mayor que veinte.
En el primer caso cuando X vale veinte en la condición de salida, ese número todavía no ha sido
visualizado.
En el segundo caso, cuando X vale veinte en la condición de salida, ese número ya ha sido
visualizado, esos son los matices.
La programación está llena de matices y “tonterías de éste tipo”, pero es esa la diferencia entre que funcione correctamente o no.
Un programa no puede ir bien para el noventa por ciento de los valores, si no para el cien por cien de los mismos.
Traducción, en un bucle lo importante es siempre:
22
Con que valores o condiciones empiezas,
En que momento realizas la progresión,
Cuando realizas la acción que te interesa en el bucle
En que momento abandonas el bucle, condición de salida.
Si estas condiciones las tenemos presentes, el uso de los bucles carece de problemas.
Lo siguiente es tener presente en que momento hay que utilizar de forma obligatoria un bucle While o un bucle Repeat.
Con el tiempo veremos que el más utilizado acaba siendo el mientras, pues casi siempre nos interesa tener controlado que se cumpla
determinada condición antes de entrar en el bucle.
Otro matiz, si en un bucle Repite la condición es hasta que “sea de color verde” en un bucle mientras la condición se invierte y será
mientras “sea de color verde”.
Aunque nadie se lo creerá, con lo que hemos visto, a nivel de creación de la estructura de un programa, no hay nada más que explicar,
eso les da una idea, por un lado de lo sencillo que es hacer un programa, y de lo importante que es tener hasta aquí claro todo lo que se ha visto.
Evidentemente que la programación no es solo lo que se ha visto, todavía quedan temas por ver, muchos temas, pero en realidad, para
crear un programa, no hace falta nada más de lo que se ha visto.
El resto de temas pendientes de ver se apoya en lo visto, de ahí la importancia de tener claro todo lo visto.
Pág. 5.2
Ejercicios unidad 5: Las instrucciones
1. - Introducir dos números A y B, e indicar cual es el mayor de ambos.
2. - Introducir dos números A y B, e indicar cual es el menor.
3. - Introducir dos números A y B, e indicar si son distintos.
4. - Introducir dos números A y B, e indicar si no son iguales.
5. - Introducir dos números A y B, e indicar si son iguales.
6. - Introducir dos números A y B, e indicar cual no es el mayor.
7. - Introducir dos números A y B, e indicar cual no es el menor.
8. - Introducir dos números A y B.
Si A es mayor que B calcular y visualizar A + B y A / B.
Si A no es mayor que B calcular y visualizar A * B y B - A.
9. - Introducir dos números A y B.
Si A es menor que B calcular y visualizar A * B y B - A.
Si A no es menor que B calcular y visualizar A + B y A / B.
10. - Introducir dos números A y B y visualizarlos en orden creciente.
11. - Introducir dos números A y B y visualizarlos en orden decreciente.
12. - Introducir dos números A y B y visualizar el resultado de:
Si A es mayor que B calcular A / B.
Si A es menor que B calcular A * B.
Si A es igual que B calcular A + B.
13. - Introducir dos números A y B.
Si A es distinto que B calcular y visualizar A + B y A / B.
Si A es igual que B calcular y visualizar A * B y B - A.
14. - Visualizar los números entre 10 y 20
15. - Visualizar los números entre 20 y 10.
16. - Visualizar los números entre 10 y 20 y sumarlos.
17. - Visualizar los números entre 20 y 10 que sean pares.
23
Los ejercicios del 1 al 7 son iguales en su estructura, distintos en la condición.
Podemos comprobar que la estructura es la misma pero cambia el contenido de las acciones.
Inicio Ejercicio Ocho.
Declarar A y B como enteras.
Escribir “Introducir dos valores numéricos”
Leer “Introduzca A”, A
Leer “introduzca B”, B
Si A > B Entonces
Escribir A + B
Escribir A / B
Si no
Escribir A * B
24
Escribir B - A
Fin de condición.
Final
En éste ejercicio aparece un nuevo símbolo, A comparado con B, por eso la condición puede tener tres salidas, pero han de estar
documentadas, como se puede observar en el mismo.
Inicio Ejercicio Doce.
Declarar Resultado, A y B como enteras.
Escribir “Introducir dos valores numéricos”
Leer “Introduzca A”, A
Leer “introduzca B”, B
Si A > B Entonces
Resultado = A / B
Si no
Si A < B Entonces
Resultado = A * B
Si no
Resultado = A + B
Fin de condición
Fin de condición.
Escribir “El resultado es “, Resultado
Final
Introducir dos números A y B.
25
Si A es distinto que B calcular y visualizar A + B y A / B.
Si A es igual que B calcular y visualizar A * B y B - A.
Los siguientes ejercicios, son bucles, y las soluciones están hechas en la mayoría de los casos con bucles del tipo Repeat.
Sería conveniente que los hicieran también con el bucle While.
26
Inicio Ejercicio Dieciseis.
Declarar X y Suma como Entera.
Escribir “Visualizamos los números entre diez y veinte”
X = 10
Inicio de repite
Escribir X
Suma = Suma + X
X = X + 1
Hasta que X > 20
Escribir “El Valor de la suma es “, Suma
Final
Visualizar los números entre 20 y 10 que sean pares.
La condición X Mod 2 significa si el resto de la división de X por 2 es cero, o sea que es par.
27
La programación ha avanzado mucho desde sus inicios, actualmente la programación no se entiende sin el uso de clases y sus
correspondientes objetos que derivan de las mismas.
6.3. Declaraciones.
La parte de declaraciones puede ser muy amplia, dependerá del lenguaje de programación, de sus requerimientos.
Como mínimo se tendrá que declarar las variables que intervengan en el programa, de tal forma que queden disponibles para su
utilización en el programa.
Después tenemos los procedimientos y las funciones, que en función del lenguaje o de los criterios que deseemos aplicar, podríamos
decir que pertenecen a éste apartado, ya que tanto un procedimiento, función o clase, antes de su utilización deben existir en el programa, por lo
tanto según deseemos aplicar los criterios podríamos incluirlos aquí o no.
Hay que tener presente que las sintaxis y las estructuras de cada lenguaje de programación son muy importantes a la hora de hablar de la
estructura de un programa, ya que ésta viene marcada por el mismo.
En fin para resumir, en la fase de declaraciones debemos ubicar todo aquello que después deseemos utilizar.
6.4. Clases.
El estilo de programación actual está basado en las clases.
Las clases no es nada más que una forma distinta de ver la forma de escribir un programa, pero le añade una serie de ventajas que ante
no estaban disponibles de una forma tan cómoda como se consigue con las clases.
Nos permiten escribir el código de forma que queda protegido, encapsulado y no es posible su modificación.
Además por el concepto de clase, esa forma de enfocar el programa, nos va a permitir que de un mismo enfoque de clase, podamos
obtener distintos resultados.
Como ejemplo pensemos en los planos de una casa que sean interactivos y en los que antes de poder ver los planos de la casa, “los
planos nos pregunten”:
Pero imagínese que en la clase casa, se nos olvido escribir la pregunta “Desea garaje”, la casa se quedaría sin preguntar si quiere o no
garaje, pero con escribir un método que sea capaz de añadir un garaje, la Clase quedaría actualizada, y sin necesidad de modificar lo que ya
tenemos escrito.
Carga.
Visualización.
Proceso.
Visualización.
Sin embargo podemos dividir ese programa en bloques, cada bloque es un procedimiento.
28
Y el programa principal quedaría como sigue:
Como podemos observar, el procedimiento Visualizar se ejecuta dos veces, pero esta escrito solo una vez, lo que hacemos es llamarlo en
dos ocasiones.
Además es mucho más sencillo seguir el programa así, que con todo el código a la vista, ya que solo tenemos que acudir a leer aquellos
procedimientos que nos interesen.
Un procedimiento participa de la resolución de la estructura de un programa, forma parte de la misma, y con una correcta utilización de los
mismos conseguiremos un programa ordenado y fácil de modificar, a la vez que fácil de entender por terceros y de modificar en un futuro.
El uso de procedimientos debe ir acompañado de un uso razonable de las variables.
Pág. 6.1
Cuando se ejecuta la función, ésta devolverá un valor, en el ejemplo supongamos que devuelve cierto o falso en función de los valores.
En el programa nosotros podremos utilizar la función dentro de nuestras expresiones, con lo que se facilita la escritura del mismo y se
simplifica.
En el ejemplo podemos ver como la función esta dentro de la instrucción condicional, y el resultado de su ejecución hará que se ejecute
una u otra de las ramas del programa.
En el ejemplo con seudocódigo podemos observar como la función se integra como una expresión en el interior de la condición, y su
resultado será el que provoque la acción en el entonces o en el si no.
Si Función(A,B) entonces
Acción
Si no
Acción
Fin de condición.
En éste ejemplo vemos un ejemplo más, en éste caso la función recibiría un valor numérico, y devolvería
cierto si el número es primo, y falso si no lo es.
En caso de cumplirse se ejecutaría la acción de escribir que el número sí es primo, en caso contrario se escribiría en pantalla, que el
número no es primo.
Si NumeroPrimo(Numero) entonces
Escribir “El número es primo ”,Numero
Si no
Escribir “Este número no es primo”, Numero
Fin de condición.
Por lo tanto nosotros podemos crear las funciones que necesitamos, y estas se integran como parte de la instrucción que escribimos, lo
que proporciona claridad y legibilidad al programa.
29
Al fin y al cabo un programa bien escrito se convierte en un libro, y debe de ser fácil poderlo leer.
6.7. Conclusiones.
Hemos visto los datos y las expresiones.
Se ha explicado las estructuras de programación,
Secuencial
Alternativa
Repetitiva
En éste tema se ha visto, muy por encima, sin entrar a fondo, clases, lo que son los procedimientos y las funciones, los hemos nombrado
y dejado caer su existencia.
Si lo visto hasta ahora lo tienen asimilado, hemos dado un gran paso.
Final
30
El ejercicio dos es igual, cambiando el valor de la pregunta en la función por menor, A < B
Esta es una solución, pero también se puede hacer esto otro, todo es cuestión de gustos.
Observar que la entrada de datos se realiza en el procedimiento.
El ejercicio no se debe resolver con una función pues se devuelven dos datos, y su solución debe pasar por un procedimiento.
También observar que el procedimiento se llama como si fuera una instrucción más del programa, no forma parte de una instrucción.
Procedimiento Proceso(A,B)
Si A > B Entonces
Escribir A + B
Escribir A / B
Si no
Escribir A * B
Escribir B - A
Fin de condición.
Fin de procedimiento
Procedimiento Proceso()
Declarar A y B como enteras.
Leer “Introduzca A”, A
Leer “introduzca B”, B
Si A > B Entonces
Escribir A + B
Escribir A / B
31
Si no
Escribir A * B
Escribir B - A
Fin de condición.
Fin de procedimiento
En éste ejercicio aparece de nuevo el símbolo, A comparado con B, por eso la condición puede tener tres salidas, pero han de estar
documentadas, como se puede observar en el mismo.
Procedimiento Proceso()
Declarar Resultado, A y B como enteras.
Los siguientes ejercicios, son bucles, y las soluciones están hechas en la mayoría de los casos con bucles del tipo Repeat.
Sería conveniente que los hicieran también con el bucle While.
Procedimiento Proceso()
Declarar X como Entera.
Escribir “Visualizamos los números entre diez y veinte”
X = 10
Inicio de repite
Escribir X
X = X + 1
Hasta que X > 20
Fin de procedimiento
Procedimiento Proceso()
Declarar X como Entera.
Escribir “Visualizamos los números entre diez y veinte”
X = 9
Inicio de repite
X = X + 1
Escribir X
Hasta que X = 20
Final de procedimiento
33
Inicio Ejercicio Siete.
Proceso
Final
Visualizar los números entre 10 y 20 y sumarlos.
Procedimiento Proceso()
Declarar X y Suma como Entera.
Escribir “Visualizamos los números entre diez y veinte y su suma”
X = 10
Inicio de repite
Escribir X
Suma = Suma + X
X = X + 1
Hasta que X > 20
Escribir “El Valor de la suma es “, Suma
Final de procedimiento
Funcion Calcula()
Declarar X y Suma como Entera.
X = 10
Inicio de repite
Escribir X
Suma = Suma + X
X = X + 1
Hasta que X > 20
Final de funcion
Dato
Variable
Expresión
Instrucción
Estructuras
Procedimientos y funciones.
34
Nos queda ver el o un elemento que contiene a todos estos, que es la clase.
La clase es el elemento estructural que aglutina todos los anteriores y permite que expresemos nuestros programas.
La clase está a su vez utilizada dentro del programa.
7.2. Introducción.
Si nuestro estilo de programación no contempla, comparte, o lo que cada uno desee, el uso de clases y objetos, el escalafón acaba con
los procedimientos y funciones, y estos se utilizan directamente dentro del programa.
Ni uno es malo, ni el otro es perfecto, son sistemas, estilos y filosofías distintas, pero no se puede negar que el uso de clases es positivo
dentro de la programación.
En la actualidad el tipo de programación que se realiza es lo que denominamos, P. O. O., programación orientada a objetos.
Dicho de otra forma, la materia explicada en temas anteriores, se colocan en el interior de lo que denominamos clases, con las que
crearemos los objetos.
Un objeto es un elemento derivado de una clase.
La clase es un elemento estructural en un programa que dispone de
Como lo que no se hace en informática es crear varias veces lo mismo, las clases las escribimos una sola vez, y lo que se hace es crear
algo así como un molde con el que luego vamos haciendo copias.
Para profesionalizar la parrafada de antes, al molde se le llama clase, y a esa clase le dotamos de una fisonomía, característica, a los
elementos que describen esa fisonomía, lo llamamos propiedades.
Las tareas que queramos que sea capaz de realizar las denominamos métodos.
Y a la capacidad de reaccionar a los estímulos exteriores lo llamamos eventos.
7.4. Propiedades.
Un ejemplo muy cercano, el ser humano, si deseamos crear una clase que imite al ser humano le podríamos crear una serie de
características, propiedades, como
Sexo
Altura
Color del pelo
Color de los ojos
Caminar.
Hablar
Leer
Escribir
Correr
De ésta forma, escribiendo los métodos, es decir el lugar donde se escribe el código de nuestro programa, se le dota de capacidades
ejecutivas a la clase, las capacidades que dispondrá el objeto que de ella se derive.
7.6. Eventos.
Y para que sea capaz de reaccionar ante lo que tiene a su alrededor, le dotaremos de sentidos, que sería la forma de poder reaccionar a
lo que hay a su alrededor.
Vista
Oído
Olfato
Gusto
Tacto
Con eso conseguimos que un objeto sea capaz de reaccionar a los actos que se producen a su alrededor, y nosotros generaremos los
eventos en los cuales tengamos interés.
Si no necesitamos saber si llueve o no, habrá evento EstaLloviendo, etc..
Y podríamos seguir enseñándole cosas, podríamos seguir escribiendo métodos y creando propiedades que definan a una persona, en la
misma clase, o creando una nueva que herede las capacidades de la que ya existe.
De esa forma, si nos fijamos cambiando el color de los ojos o del pelo, o del sexo, a partir de un mismo punto de partida, podemos crear
distintos tipos de personas.
7.8. Herencia.
Lo que no vamos a hacer nunca tampoco es escribir una parte de un programa de nuevo, cuando ya lo hemos escrito anteriormente, por
lo que lo que se va haciendo es crear clases, moldes base que luego vamos enriqueciendo a partir de las ya existentes, a este concepto de
aprovechamiento de lo ya existente lo denominamos herencia.
De esa forma podemos crear una clase base denominada persona con las características estándar, o un bebe, si queremos llamarlo así,
al que hemos de ir enseñando a hacer cosas.
Sexo
Altura
Color pelo
Color ojos
Color de la piel
Le enseñaremos solo a
Hablar
Leer
Escribir
Andar
Correr
Calor
Frío
Seco
Mojado
Y después crearíamos una nueva clase que heredara esas capacidades y le añadiríamos otras nuevas.
Podríamos crear una clase que fuera un matemático, al cual le potenciaríamos sus capacidades mentales para el cálculo y la lógica.
7.9. Ocultación.
Pero en el manejo de estas posibilidades nunca permitiríamos que el diseñador de la clase cocinero o matemático pudiera cambiar el
color del pelo, o de los ojos.
Esta característica que permite proteger las características del bebe se denomina ocultación.
Pág. 7.2
Unidad 7. Las clases (III)
7.10. Aplicación.
Con lo que hemos comentado, si es capaz de asumir, madurar, y comprender lo que ha leído, el pasar de la fase de abstracción a la real
le supondrá muy poco esfuerzo, ya que los conceptos base de la P. O. O., son los comentados, solo queda la aplicación.
Clase Humano
Propiedad Sexo
Propiedad Altura
Propiedad Raza
Propiedad ColorOjos
Propiedad ColorPelo
Metodo Caminar
36
Fin de metodo
Metodo Hablar
Fin de metodo
Metodo Leer
Fin de metodo
Metodo Escribir
Fin de metodo
Fin de Clase
Cada uno de esos métodos, contendrá el código adecuado para que se realice la acción que tiene como misión.
Por ejemplo el método Leer, podría ser
Metodo Leer(NombreLibro)
Fin de metodo
Y recibiría como parámetro el nombre de un libro, el cual habría que leer.
En el interior del método podríamos tener escrito algo como
Metodo Leer(NombreLibro)
AbrirLibro(NombreLibro)
CerrarLibro
Fin de metodo
Pero podríamos añadir un parámetro que fuera leer en voz alta, o podríamos añadir una condición que fuera leer si no estas cansado.
Por lo tanto podría quedar
37
NoEstoyCansado sería una función que podría analizar el estado anímico del objeto Mujer y devolver Cierto o Falso, de tal forma, que si
es cierto se sigue leyendo y si no, se abandona la lectura.
Así que podríamos llegar a algo parecido a lo siguiente.
Metodo Leer(NombreLibro)
AbrirLibro(NombreLibro)
CerrarLibro
Fin de metodo
Pág. 7.3
Unidad 7. Las clases (IV)
Una vez que disponemos de la clase ya escrita, el siguiente paso es poderla utilizar.
El primer paso sería declarar un objeto del tipo de la Clase, recordemos que cuando declaramos una variable, es porque va a almacenar
un dato, ese dato tendrá un tipo, y la variable ha de concordar con ese tipo de dato.
Con los objetos ocurre lo mismo, si declaramos un objeto, es porque deseamos que ese objeto realice una serie de acciones, el objeto es
capaz de realizar esas acciones porque la clase de la que se deriva, posee esas capacidades.
Por lo tanto hay que crear el objeto de la clase que nosotros sabemos que posee esas características.
Un ejemplo, desde un programa se pueden utilizar las librerías de Office, y se puede declarar un objeto que llamemos Hoja y que se crea
con las mismas características y habilidades que puede tener Excel, o se podría hacer también con Word, declaramos un objeto que llamamos
Documento del tipo Word, y podríamos escribir un documento de Word a partir del contenido de una base de datos, sin pulsar una sola tecla, y lo
más divertido, podríamos ver como el documento se escribe solo en pantalla.
Anécdotas a parte, un objeto es eso, un elemento en nuestro programa con las capacidades de realizar las cosas de la clase de la cual
deriva.
En el programa el primer paso sería asignar al objeto los valores de las propiedades que definirán al objeto.
Mujer.Sexo = “M”
Mujer.Altura = 180
Mujer.Raza = “Blanca”
Mujer.ColorOjos = “Verde”
Mujer.ColorPelo = “Negro”
La siguiente fase ya sería su utilización.
Mujer.Leer
O
Mujer.Escribir
Por lo que el programa podría quedar
Inicio Programa
Declarar Mujer del tipo Humano
Mujer.Sexo = “M”
Mujer.Altura = 180
Mujer.Raza = “B”
Mujer.ColorOjos = “Verde”
Mujer.ColorPelo = “Negro”
Mujer.Leer
Fin de programa
38
Claro está que esto es la mínima expresión de lo que podría ser, pero solo pretende ser eso, un ejemplo.
7.11. Conclusiones.
Evidentemente la aplicación es más compleja, pero lo es, por los tecnicismos necesarios en la escritura de los programas, no porque
cambie lo expuesto anteriormente.
Si los conceptos están claros, la comprensión de la tarea de programar se facilita en gran medida.
Programar es dominar una técnica, la técnica no cambia, lo que cambian son los lenguajes.
Para llegar a la técnica y tener agilidad en el planteamiento y comprensión de los planteamientos de un programa, es necesaria la
experiencia, y la experiencia solo se logra con la práctica y el trabajo del día a día.
Metodo CrearHabitacion
Declarar X
X = 0
Mientras X < Habitaciones
DibujarHabitacion M2Habitacion
X = X + 1
Fin de mientras
Fin de metodo
Metodo CrearBaño
DibujarBaño M2Baños
Fin de metodo
Metodo CrearSalon
DibujarSalon M2Salon
Fin de metodo
Metodo CrearCocina
DibujarCocina M2Cocina
Fin de metodo
Fin de Clase
Inicio Programa
Declarar Piso del Tipo Casa
Piso.M2Salon = 20
Piso.M2Baño = 8
Piso.M2Habitacion = 12
Piso.CrearSalon
Piso.CrearBaño
.. / ..
Fin de programa
Esta solución es eso, solo una versión, y que cada cual puede mejorar y reinterpretar.
39
Unidad 8. VB Studio Net 2005 (I)
8.1. Objetivos del tema.
Con el fin de empezar con un lenguaje de programación vamos a ver en este tema una introducción a Visual Basic.
En cuanto al tema de la historia de Vb, Qbasic, Basic etc, en Internet hay información suficiente.
8.2. Introducción.
Es un lenguaje de programación que actualmente respeta prácticamente todas las características de la P. O. O..
Anteriormente la generación de un programa ejecutable con Basic generaba un ejecutable, actualmente genera un archivo intermedio que
se ejecuta posteriormente por la máquina virtual de Studio Net.
Esta característica, que hoy incorporan otros lenguajes de programación, convierte a VB en un lenguaje portable en el momento que
exista una máquina virtual para otros sistema operativos distintos de Windows.
8.3. Características.
Es fácil de utilizar, igualmente para personas que están iniciándose como para expertos en la materia.
El entorno de diseño para un entorno gráfico es muy cómodo y fácil de utilizar.
Es un lenguaje orientado a objetos.
Existe un amplio espectro de objetos en el mercado para poderse integrar en el lenguaje.
No dispone de punteros.
8.4. Advertencias.
El problema de las mayúsculas de otros lenguajes aquí no se da, e incluso el editor de texto de VB unifica el nombre de las variables
cuando las escribes de otra forma.
http://www.microsoft.com/spanish/msdn/vstudio/express/default.mspx
Depuración.
Organización.
Ayudas
Corrector sintáctico
Compilación.
El entorno en si es muy amplio y explicarlo en su totalidad no es el motivo de ésta documentación, vamos a abordar solamente la parte
que nos interesa para ésta fase de iniciación a la programación con éste lenguaje.
8.7. Descarga.
Seguir los pasos que se indican en la página de Microsoft.
Pág. 8.1
En el escritorio de Windows dispondremos de un icono, con el texto que hayamos deseado asignarle y con el que accederemos a
la aplicación.
En función de cómo hayamos configurado en la instalación nos aparecerá un tipo de inicio u otro, el que sigue puede ser uno de ellos,
pero también puede aparecer una ventana con un enlace a las últimas noticias sobre Studio net y con los últimos proyectos abiertos a la
izquierda.
40
En esta opción si nos fijamos podemos ver las pestañas de una serie de ventanas que posteriormente serán útiles en el desarrollo de
nuestros programas.
Empezando de izquierda a derecha, la pestaña de Cuadro de herramientas que nos visualizará los objetos disponibles para el diseño de
los formularios de nuestros programas.
La ventana de explorador de soluciones es la que permite ver todos los elementos que componen el proyecto actual,
dispone de varios estilos de visualización.
La ventana de propiedades nos permite acceder a todas las propiedades de los objetos del formulario que tengamos
seleccionado en ese momento
Al seleccionar una propiedad en la parte inferior de la ventana aparece una pequeña leyenda de las características
de dicha propiedad.
Pág. 8.2
Para iniciar un proyecto nuevo seleccionaremos la opción Archivo à Nuevo proyecto., de la barra de herramientas.
En ese momento se pone en marcha un asistente, como no, y nos pedirá el tipo de proyecto que deseamos crear.
Para los ejemplos que vamos a ir viendo seleccionaremos la opción que vemos en la imagen, Windows à Aplicación de Consola.
Son ejercicios sencillos que no necesitan de la complejidad de un formulario, y así no nos distraemos de lo importante.
41
El nombre del proyecto, podemos cambiarlo por el nombre que deseemos, y su ubicación será la que él tiene por defecto, podemos
dejarla o bien crear la nuestra propia.
Hay que tener presente que cada proyecto se ubica en un directorio, donde estarán todos los archivos que se
creen para dicho proyecto.
Al pulsar Aceptar, nos crea la estructura básica del proyecto que hemos seleccionado, y ya podemos empezar a
escribir nuestro primer programa.
dato1 = 20
dato2 = 10
Module Module1
Sub Main()
Dim dato1, dato2, resultado As Integer
dato1 = 20
dato2 = 10
End Module
Ya tenemos un pequeño ejemplo.
Aunque quedaría mejor así:
Module Module1
Sub Main()
Dim dato1 As Integer
Dim dato2 As Integer
42
Dim resultado As Integer
dato1 = 20
dato2 = 10
End Module
Pero solo es cuestión de estilo.
Pág. 8.3
En VB en modo consola, y si se desea en modo gráfico también, la fase de inicio es el denominado Main del programa, desde donde
empieza la ejecución del mismo, siguiendo las instrucciones que en él hayamos escrito, como podemos ver en el ejemplo anterior.
Module Module1
Es el nombre del módulo que en éste caso contiene el Main, y que si deseamos podemos cambiar de nombre, y al final disponemos de un
End Module..
Sub Main()
Es el punto de inicio de nuestro programa, y podemos observar como al final disponemos de un End Sub.
dato1 = 20
dato2 = 10
resultado = dato1 + dato2
Asignamos unos datos y realizamos la operación de suma.
Técnicamente es incorrecto, pues para ello ambos datos deberían ser del tipo alfanumérico, pero bueno así es la sintaxis en el algunos
casos con Microsoft.
System.Console.ReadKey()
Así paramos la ejecución del programa y podemos ver los valores en la ventana.
End Sub
End Module
Los finales de la estructura, del main y del módulo principal.
43
En la imagen vemos el resultado de la ejecución.
Pág. 8.4
End Class
Resolvemos el ejemplo de antes.
Pág. 8.5
44
En el peor de los casos, todo lo que se puede escribir en un procedimiento se puede resolver también con una función, o al revés,
¡técnicamente!, en la realidad no debe abordarse así.
El procedimiento nos va a permitir resolver la estructura de un programa, cuando nos dan los resultados del análisis de un problema, nos
dan una estructura, y esa estructura se resuelve mediante el uso de procedimientos.
9.4. Procedimientos.
Siempre hemos de procurar crear procedimientos que sean cortos.
Se ha de intentar seguir la pauta de que un procedimiento no supere en
mucho la capacidad de líneas de una pantalla o de una hoja de papel, no por ningún
requisito técnico, si no por comodidad nuestra, lo cual no impide en absoluto que
cuando nos interese lo superemos.
Un procedimiento debe de ser un espacio estanco, su forma de comunicación con los datos que hay en el exterior debe ser los que
figuran en la línea de parámetros.
Cualquier otra forma de utilización, técnicamente puede ser correcta, y de hecho
habrá alguna vez que habrá que saltarse esa norma, consejo, pero a la larga se convierte en
problemas.
El procedimiento A y B son conocidos por el programa principal, A conoce a B y B conoce a A, pero A no conoce a B1, ni B1 conoce a A.
Las variables de nivel de programa, pueden ser utilizadas por los procedimientos en su interior, no es aconsejable.
Es conveniente utilizar el paso de variables, más que el uso de las globales, ya que eso le da independencia al procedimiento.
45
9.7. Paso de variables a los procedimientos.
El paso de variables a los procedimientos es el camino adecuado para su correcta utilización.
Para ellos hay que seguir unas normas, que son de lo más sencillas y absolutamente lógicas.
El siguiente ejemplo vemos que no coinciden ni color, tipo, ni tamaño dato, ni el número de parámetros que se envían y reciben.
El nombre no tiene porque coincidir, pensemos que el mismo procedimiento puede utilizarse en varios programas, no tienen porque
coincidir los nombres de las variables por eso, si no sería un problema bastante serio.
Actualmente hay lenguajes que permiten que haya variables de uso opcional en la línea de parámetros.
Aquí podemos ver como en el programa principal se envía dos variables a CALCULA, en este
procedimiento se reciben en el mismo orden y con el mismo tipo.
A su vez luego desde CALCULA se llama a REPRESENTA y se le envía tres variables que se
recogen igual.
Pág. 9.2
46
El paso de datos por referencia, es lo que nos permite que un procedimiento sea independiente del programa que lo llama.
De esa forma podemos conseguir que un procedimiento trabaje con los datos de otro procedimiento o programa sin necesidad de que las
variables se llamen igual.
El paso de datos por referencia a un procedimiento, nos da la posibilidad de poder modificar el valor de una variable pasada en el
procedimiento, y que éste sea devuelto al programa principal o al procedimiento que lo ha llamado.
Cuando se pasa un dato por valor el dato es recibido por el procedimiento pero éste dato si se modifica en su interior no se recibe
modificado en el lugar en el que se llama al procedimiento.
El paso de datos por valor a un procedimiento, nos da la posibilidad de poder enviar el dato de una variable a un procedimiento, y que la
variable no pueda ser modificada en su contenido al finalizar la ejecución del procedimiento y devolverse el control al programa principal o al
procedimiento que lo ha llamado.
Pág. 9.3
El nombre del proyecto, podemos cambiarlo por el nombre que deseemos, y su ubicación será la que él tiene por defecto, podemos
dejarla o bien crear la nuestra propia.
Module Module1
47
Sub Main()
Dim dato1 As Integer
Dim dato2 As Integer
Dim resultado As Integer
dato1 = 20
dato2 = 10
Esta es una solución, pero así no se puede hacer un programa, un programa es una estructura muy
compleja, o puede llegar a serlo, y para eso hace falta una estructura que sea resistente y eficiente.
Empecemos por pasar parámetros al procedimiento, por lo que en la línea de parámetros tendrá que aparecer las dos variables.
Las variables tendrán que ir declaradas con el tipo que les corresponde.
resultado = D1 + D2
Procedimiento(dato1,dato2)
En el programa principal, dichas variables deberán estar declaradas para poderse utilizar.
Module Module1
Private Sub Procedimiento(ByVal D1 As Integer, ByVal D2 As Integer)
Dim resultado As Integer
resultado = D1 + D2
Sub Main()
Dim dato1 As Integer
Dim dato2 As Integer
48
dato1 = 20
dato2 = 10
Procedimiento(dato1, dato2)
End Sub
End Module
Comprobemos que las variables que se pasan lo son en el mismo orden, del mismo tipo y con el mismo dato, d1 desde dato1 y d2 desde
dato2.
Pág. 10.2
Donde expresión será cualquier expresión cuyo resultado de evaluación final siempre es del tipo cierto o falso.
Pueden ir o no acompañadas de un else, en función de que sea necesario para nuestro programa.
Hay otra instrucción alternativa que es Select Case, que mucho más estructurada y más potente en cuanto a sencillez de posibilidades de
creación de estructuras.
Aquí tenemos un ejemplo con los posibles valores que nos interese de X, pero hay un sin fin de posibilidades en cuanto a posibles
expresiones para evaluar.
Select case X
case 1
Instrucción;
Instrucción;
case 2
Instrucción;
Instrucción;
Case else
Console.writeline("error" )
End Select
Otro ejemplo de un Select Case
49
End Select
En el ejemplo podemos observar varias formas de escribir la instrucción.
En caso de que en la estructura deseemos dar una salida para la situación en la que no se cumpla ninguna de las situaciones previstas,
podemos utilizar la opción de Case else
Case Else
NombreMes = "Incorreccto"
End Select
Dicho de otra forma es el equivalente del else en la instrucción If, vista anteriormente.
En el ejemplo tenemos una variable con un valor previsto de -1 y desconocemos cuales son las otras posibilidades, por lo tanto utilizamos
case else para el resto.
if (x > 0) then
y = 15
if (x > 10) then
x = 2
else
x = 25
end if
else
x = 25
end if
Pág. 10.3
La flecha indica al punto del programa en el cual se inicia la estructura o en el que está la primera instrucción del bucle.
Si observamos las flechas podemos observar como la última instrucción del bucle es la encargada de analizar la situación en ese
momento, para volver a iniciar una vez más el ciclo o seguir hacia la siguiente instrucción, ya fuera del bucle.
Su sintaxis es la siguiente.
do
instrucción
... / ...
instrucción
Loop Until (expresión de condición)
Sin embargo si observamos la imagen del bucle mientras, podemos observar como a diferencia del bucle repite, la
instrucción de control está situada al inicio del mismo.
Esto implica que si al llegar al inicio del bucle, la condición que expresamos en ese momento no se cumple, el bucle no se
ejecutará, no entraremos en el mismo, o si lo queremos ver así, el bucle está protegido en su ejecución.
Si observamos las flechas podemos observar como al acabar la última instrucción del bucle se retorna al inicio del mismo,
donde está la instrucción de control, en ese momento se analiza la situación y se vuelve a ejecutar una vez más el ciclo, o se
abandona el mismo, siguiendo a la siguiente instrucción.
50
Su sintaxis es la siguiente.
instrucción
... / ...
instrucción
End While
Hay una tercera opción de bucle que es el For.
Este bucle se ejecuta para un valor inicial, hasta un valor final, con un incremento determinado, no deja de ser una variación de un bucle
mientras.
For X = 0 to 20
instrucción
... / ...
instrucción
Next
Lo que con un bucle mientras, equivale a:
inicialización;
While X <>20
instrucción
... / ...
instrucción
incremento
End While
Existe la instrucción exit for, exit do, dentro de los bucles, pero quizás sea poco didáctico y no sea muy adecuado su utilización en una
primera fase del lenguaje, al igual que el uso del for, hasta que no se haya avanzado más en el dominio del mismo.
En los bucles, sean del tipo que sean, y se utilicen para lo que sea, siempre hay que tener presente el valor de partida, el valor final, y el
momento en el que se realiza el incremento del contador, si es que se usa, o de la instrucción que provoque la progresión en el mismo.
Por ejemplo en la visualización de los números del 0 al 9, utilizaremos una variable del tipo entero.
Le daremos un valor inicial de cero, en el bucle la primera instrucción será visualizar, y la condición del bucle será mientras que x sea
menor que diez.
El resultado será correcto.
Module Module1
Sub Main
Dim x as Integer = 0
while x < 10
Console.Writeline(x)
x = x + 1
End While
End Sub
End Module
Pero si alteramos el orden de las instrucciones, el valor cero inicial, ya no será válido, pues el primer valor que se visualizará será uno, y
perdemos la visualización del cero. Además la condición final tampoco será válida, pues acabaremos en diez, no en nueve, que es de lo que se
trata.
Pruébelo.
Por lo tanto hay que tener siempre presente, el punto de partida, los valores intermedios, el valor de la progresión, en que momento, y
cual es el último valor que debe procesarse en el bucle.
Teniendo eso presente no debe haber nunca problemas en el manejo de los bucles.
Pág. 10.4
instrucción
instrucción
instrucción
51
Como ejemplo podríamos poner:
Hemos de tener presente que en lo que podemos denominar programa principal, que en muchas ocasiones es algo ficticio, o no muy
próximo a la realidad, no se escribe casi código, si no llamadas a procedimientos, o declaración y ejecución de los objetos que se han declarado, y
donde realmente se escriben los programas es en los procedimientos, y funciones que se convierten en métodos en las clases.
1º Introducir dos números y calcular la suma de los mismos, visualizando el resultado final. Repetir para la resta y la
multiplicación.
Module Module1
Private Sub Uno(ByVal D1 As Integer, ByVal D2 As Integer)
Dim resultado As Integer
resultado = D1 + D2
Sub Main()
Dim dato1 As Integer
Dim dato2 As Integer
dato1 = Console.ReadLine()
dato2 = Console.ReadLine()
Uno(dato1, dato2)
End Sub
End Module
Si en la solución del ejercicio se tienen problemas del tipo Option Strict On no permite la conversión de String en Integer,
la solución pasa por:
dato1 = CInt(Console.ReadLine())
dato2 = CInt(Console.ReadLine())
Que es la solución correcta.
52
Private Sub Dos(Rad as Double)
Dim Longitud As Double
Dim Area As Double
Area = PI * Rad ^ 2
Longitud = 2 * PI * Rad
Console.WriteLine()
Console.WriteLine("El área de la circunferencia es {0} ", Area)
Console.WriteLine()
Console.WriteLine("La longitud de la circunferencia es {0} ", Longitud)
Console.WriteLine()
Console.Write("Pulse cualquier tecla para finalizar ... ")
Console.Read()
End Sub
Y en el Main:
Const PI As Double = 3.1416
Sub Main()
Dim Radio As Double
Console.WriteLine("Hallar el área y la longitud de la circunferencia")
Console.WriteLine()
Dos (Radio)
End Sub
3º Introducir dos números A y B y visualizar el resultado de:
Si A es mayor que B calcular A / B.
Si A es menor que B calcular A * B.
Si A es igual que B calcular A + B.
Sub Main
Dim A As Long
Dim B As Long
Tres(A,B)
53
End Sub
4º Visualizar los números entre 10 y 20
Private Sub Cuatro()
Dim X As Integer
Suma = 0
X = 10
Do
Console.WriteLine(X)
X = X + 1
Loop Until X > 20
Console.WriteLine()
Console.Write("Pulse cualquier tecla para continuar ... ")
Console.Read()
End Sub
Y en el Main
Sub Main
Cuatro()
End Sub
En éste ejercicio se ha optado por agrupar todo el código en el procedimiento.
5º Visualizar los números entre 10 y 20 y sumarlos.
Private Sub Cinco()
Dim Suma As Long
Dim X As Integer
Altura = 5
Base = 10
AreaTriangulo(Base,Altura,Area)
En el caso de una función no nos sirve el criterio de que un procedimiento crezca en demasía, para crear una función, hay una diferencia
de base entre un procedimiento y una función, y es que un procedimiento puede formar, o forma parte, de la resolución lógica de un programa,
parte de su estructura, pero una función es una parte de nuestro programa que está especializado en algo muy concreto y que solo sabe resolver
ese tema, y no formará parte de la estructura del programa, colabora en su solución.
Evidentemente que sí convierte en más legible un programa, el uso de una función, pero no es la forma de resolver un programa, por
supuesto que su uso es necesario en programación, pero hay que ver ese matiz entre ambas herramientas de programación.
Un procedimiento, un método, cuando crece se puede dividir en varios procedimientos, pero no en varias funciones.
En el diseño de una función, hay que mantener el criterio, de que solo se utilice las variables que se definan en la misma, y las que se
reciban en la línea de entrada, pero de forma todavía mucho más taxativa, una función, por naturaleza, es una parte de código mucho más
reutilizable, normalmente, que un procedimiento, por lo tanto debe ser todavía mucho más aislado, autónomo.
55
De todos modos, será la experiencia la que nos ira marcando cuando usar el procedimiento y cuando la función.
11.4. ¿Funciones o Procedimientos.?
En el peor de los casos, todo lo que se puede escribir en un procedimiento se puede resolver también con una función, o al revés,
¡técnicamente!, en la realidad no debe abordarse así, porque en algunas ocasiones para hacerlo, hay que cometer alguna incorrección.
Una función devuelve siempre un único dato, un procedimiento puede devolver uno o varios, o ninguno, pero es que si se usan
adecuadamente las funciones, con un único dato es suficiente.
11.5. Tipos de la función.
Hemos dicho que una función devuelve un dato, por lo tanto si devuelve un dato, ese dato debe de
ser de un tipo, de ahí que la función cuando se crea hay que declarar de que tipo es, y ese tipo es el del dato
devuelto.
Otra forma de clasificar las funciones es dividirlas por las propias del lenguaje y las que diseñemos
nosotros, todos los lenguajes de programación disponen de funciones preescritas en el mismo.
En el ejemplo vemos una función escrita por nosotros, y vemos como en su interior utilizamos
funciones del lenguaje en el que se escribe esa función.
La función del ejemplo es del tipo alfanumérico porque lo que devuelve es un dato alfanumérico.
Por lo tanto tendremos tantos tipos de funciones como tipos de datos disponga el lenguaje que
estamos utilizando.
Pág. 11.1
Pueden ser públicas o privadas, y pueden declararse en el programa actual o en un módulo disponible para toda la aplicación, proyecto.
11.7. Paso de variables a las funciones.
El paso de variables a las funciones cumple los mismos requisitos que el de los procedimientos.
Para ellos hay que seguir unas normas, que son de lo más sencillas y absolutamente lógicas.
El nombre no tiene porque coincidir, pensemos que el mismo procedimiento puede utilizarse en varios programas, no tienen porque
coincidir los nombres de las variables por eso, si no sería un problema bastante serio.
Actualmente hay lenguajes que permiten que haya variables de uso opcional en la línea de parámetros.
56
El paso de datos por referencia, es lo que nos permite que un procedimiento sea independiente del programa que lo llama.
De esa forma podemos conseguir que un procedimiento o una función, trabaje con los datos de otro procedimiento o programa sin
necesidad de que las variables se llamen igual.
El paso de datos por referencia a una función, nos da la posibilidad de poder modificar el valor de
una variable pasada en la función, y que éste sea devuelto al programa principal o al procedimiento que lo
ha llamado.
Otro apartado, es que por la definición intrínseca de lo que debe ser una función, no sea correcto
realizar ese tipo de actuaciones, paso por referencia en una función, ya que eso en realidad me permitiría
devolver no un dato, si no varios en la misma, uno en la función y otros en la línea de parámetros en las
variables recibidas, lo que contradice la filosofía de lo que debe ser una función.
Pero hemos de saberlo y comprobar que el lenguaje lo permite o no, y de esa forma si llega el
momento “utilizarlo”.
Cuando se pasa un dato por valor el dato es recibido por el procedimiento o función, pero éste
dato si se modifica en su interior no se recibe modificado en el lugar en el que se realiza la llamada a la
función.
El paso de datos por valor a un procedimiento o función, nos da la posibilidad de poder enviar el
dato de una variable y que la variable no pueda ser modificada en su contenido al finalizar la ejecución del
procedimiento o función, y devolverse el control al programa principal o al procedimiento que lo ha llamado.
Pág. 11.2
Así que lo más sencillo es declarar una variable temporal a la que le asignamos un valor por defecto
y que después cuando finalice la ejecución de la función asignaremos al nombre de la misma.
Hay que pensar que tanto una función como un procedimiento son mini programas, pero en el caso de una
función aún más.
Esta es una forma de plantear una función, pero el momento y el estilo de cada uno es personal e
intransferible, por lo que a partir de ahí cada cual puede ir creando su estilo.
Pág. 11.3
Los procedimientos y las funciones, dependiendo de la estructura del lenguaje utilizado, y del estilo de programación individual de cada
uno, están bien en módulos independientes, de forma que son públicos para toda la aplicación, o de forma privada en el interior de un programa, o
una clase.
En VB, las funciones son funciones y podrán o no pertenecer a una clase y ser un método, se albergará en el interior de una clase,
haciendo referencia al mismo mediante el nombre de la clase y a continuación el de la función, método, o si está en el mismo nivel, con utilizar la
función es suficiente, como vemos en el ejemplo.
57
Con las funciones sucede lo mismo, al fin y al cabo, no son nada más que otra de las herramientas de programación.
Cadena = InvierteCadena(Cadena)
Pág. 12.1
58
While x <> Len(Cadena)
x = x + 1
Result = Mid(Cadena, x, 1) & Result
End While
Finalizada la ejecución de la función se asigna su resultado a la misma.
InvierteCadena = Result
Y la función que finalizará con la línea
End Function
La devolución del resultado de la ejecución de la función se obtiene con la línea
InvierteCadena = Result
O bien como sigue:
FuncionFactorial = n * FuncionFactorial(n - 1)
En este ejemplo lo que se muestra es una utilización recursiva de la misma.
El nombre de la función es la encargada de recibir el valor que se va a devolver al punto de llamada de la misma, y el dato que se le
asigna debe ser del mismo tipo que se declara en la función.
Por valor
Por referencia
En el primero de los casos la variable que recibe el procedimiento, puede ser utilizada en el interior del mismo, pero los cambios que
sufra, no podrán ser devueltos al programa que lo ha llamado, el procedimiento recibe el valor de la variable, pero no la variable.
Por referencia, sin embargo la variable recibida podrá ser utilizada y si ha sufrido cambio en su valor, éste podrá ser devuelto al programa
que lo ha llamado, el procedimiento recibe una referencia a la variable, por lo tanto los cambios que se realicen a la misma, perduran a la
finalización del procedimiento, o función.
En VB se puede recibir datos por valor, ByVal, y por referencia, ByRef, tanto en un procedimiento, SUB, o una función, Function.
Dicho de otra forma, podríamos enviar datos por referencia a una función y recibir datos devueltos en el nombre de la función y en la
variable que nosotros consideremos adecuado.
Un ejemplo:
, ByRef R As String)
Que podemos observar que es por referencia, ByRef, y después para probar que se puede utilizar:
R = Result
Al final de la función, y el resultado de ejecutar
59
Sub Main()
Dim C As String = “ARROZ”
Dim R As String
Console.WriteLine("Valor por referencia en una función")
Console.WriteLine("Cadena invertida {0} es {1} ", C, InvierteCadena("ARROZ", R))
Module Module1
Sub Main()
Dim Radio As Double
Module Module1
Private Function AreaTriangulo(ByVal Base As Double, ByVal Altura As
Double) As Double
AreaTriangulo = Base * Altura / 2
End Function
Sub Main()
Dim Base As Double
Dim Altura As Double
Console.ReadKey()
End Sub
End Module
3.- Introducir un número A y visualizar si es o no primo.
Module Module1
Public Function Primos(ByVal Numero As Long) As Boolean
Dim X As Integer = 3
Dim Final As Long
Dim Result As Boolean = True
Sub Main()
61
Dim Numero As Integer
Console.WriteLine("Números primos")
Console.WriteLine("Introducir número")
Numero = Console.ReadLine
Select Case Objeto.Primos(Numero)
Case True
Console.WriteLine("El número {0} es primo ", Numero)
Case Else
Console.WriteLine("El número {0} no es primo ", Numero)
End Select
Console.ReadKey()
End Sub
End Module
4.- Introducir una calificación (entre cero y diez), e imprimir su equivalente alfabético, según la siguiente tabla.
De 3 -------> M.D.
Desde 3 y menor que 5 -------> INS.
Desde 5 y menor que 6 -------> SUF
Desde 6 y menor que 7 -------> BIEN
Desde 7 y menor que 9 -------> NOT.
Desde 9 hasta 10 -------> SOB.
Module Module1
Private Function Calificacion(ByVal Nota As Single) As String
Dim Texto As String = ""
Select Case Nota
Case 0 To 2.99
Texto = "M.D."
Case 3 To 4.99
Texto = "Ins"
Case 5 To 5.99
Texto = "Suf"
Case 6 To 6.99
Texto = "Bien"
Case 7 To 8.99
Texto = "Not"
Case 9 To 10.0
Texto = "Sob"
Case Else
Texto = "Calificación erronea"
End Select
Calificacion = Texto
End Function
Sub Main()
Dim Nota As Single
Console.WriteLine("Introducir nota ")
Nota = Console.ReadLine
Console.WriteLine(Calificacion(Nota))
Console.ReadKey()
End Sub
End Module
5.- Introducir un valor en metros y visualizar su valor en millas terrestres, marinas , yardas y leguas.
Milla terrestre = 1.609,34 m.
Milla marina = 1.852,00 m.
Yarda = 4.190 m.
Legua = 0,9144 m.
Module Module1
Private Function Conversion(ByVal M As Single, _
ByVal T As String) As Single
Dim C As Single
Select Case T
Case "T"
C = CSng(M / 1609.34)
62
Case "M"
C = CSng(M / 1852)
Case "L"
C = CSng(M / 4190)
Case "Y"
C = CSng(M / 0.9144)
End Select
Conversion = C
End Function
Sub Main()
Dim Metros As Single
Dim Tipo as String
Console.WriteLine("Convertir distancia en metros ")
Console.WriteLine("Introducir distancia en metros")
Metros = Console.ReadLine
Console.WriteLine("Introducir M/T/L/Y ")
Tipo = Console.ReadLine
Console.WriteLine(Conversion(Metros, Tipo))
Console.ReadKey()
End Sub
End Module
6.- Introducir una fecha en pantalla con el formato día, mes y año en tres variables numéricas, validar la fecha y emitir
el mensaje de fecha incorrecta o correcta.
Module Module1
Function Fecha(ByVal D As Integer, _
ByVal M As Integer, _
ByVal A As Integer) _
As Boolean
Select Case M
Case 1, 3, 5, 7, 8, 10, 12
Fec = D > 0 And D < 32
Case 4, 6, 9, 11
Fec = D > 0 And D < 31
Case 2
Select Case A Mod 100 = 0
Case True
Fec = (D > 0 And D < 29) Or (D = 29 And A Mod 400 = 0)
Case Else
Fec = (D > 0 And D < 29) Or (D = 29 And A Mod 4 = 0)
End Select
End Select
Fecha = Fec
End Function
Sub Main()
Dim Dia As Integer
Dim Mes As Integer
Dim Year As Integer
Console.WriteLine("Comprobar fecha ")
Console.WriteLine("Introducir dia")
Dia = Console.ReadLine
Console.WriteLine("Introducir mes")
Mes = Console.ReadLine
Console.WriteLine("Introducir año")
Year = Console.ReadLine
Select Case Fecha(Dia, Mes, Year)
Case True
Console.WriteLine("La fecha es correcta")
63
Case Else
Console.WriteLine("La fecha no es correcta")
End Select
Console.ReadKey()
End Sub
End Module
7.- A partir de los siguientes valores de moneda extranjera, crear una función que a partir de un importe en pesetas
devuelva su equivalente en la moneda que se indique.
Module Module1
Function ConversionMoneda(ByVal Pesetas As Single, _
ByVal Moneda As String) As Single
Dim Result As Single
Select Case Moneda
Case "F"
Result = CSng(Pesetas / 25.24)
Case "L"
Result = CSng(Pesetas / 0.0859)
Case "I"
Result = CSng(Pesetas / 245.556)
Case "D"
Result = CSng(Pesetas / 150.228)
Case "M"
Result = CSng(Pesetas / 84.648)
Case "S"
Result = CSng(Pesetas / 101.755)
Case "H"
Result = CSng(Pesetas / 5.117)
Case "P"
Result = CSng(Pesetas / 0.826)
End Select
ConversionMoneda = Result
End function
Sub Main()
Dim Pesetas As Integer
Dim Moneda As Char
En estos ejercicios en algunos casos sería necesario añadir instrucciones del tipo
T = Ucase(T)
Siendo T una variable de tipo char, que puede venir indistintamente en minúsculas o mayúsculas, de esa forma nos aseguramos su
completo funcionamiento, convirtiéndola a mayúsculas.
También se ha optado por utilizar una variable auxiliar, y luego que la función reciba su valor, no siendo eso imprescindible, pero sin
embargo si válido en cualquier lenguaje.
64
Pueden funcionar también con esta sintaxis.
Ello viene obligado por la definición del parámetro Option Strict, para acceder al mismo
Si está en off, no exige la conversión obligada de tipos, es fuente de posibles errores, si está en On, sí.
Su valor adecuado debería ser On, aunque obligue a la conversión de los datos.
A pesar de que sea un tema que se lo podría saltar, pues el sistema de programación con procedimientos y
funciones es válido, la realidad es otra, aunque poco a poco, cada día el sistema de clases se va imponiendo más
en los programas de las empresas que se dedican al desarrollo de software, no nos referimos a las grandes empresas, si no a las de menos
volumen.
Si está usted empezando, le aconsejo que se meta de lleno en ello, a lo mejor le cuesta un poco más, pero no tiene sentido empezar de
cero y quedarse con un sistema de programación más o menos obsoleto, o al menos no adquirir de forma clara el concepto de clase.
En este tema vamos a abordar el apartado de datos en las clases.
13.2. Introducción.
En las clases hay que solventar la gestión de los datos que necesita la clase, las acciones que tiene que
ser capaz de resolver, y los estímulos exteriores a los que tiene que reaccionar.
La clase podrá o no de disponer de la capacidad de reaccionar ante estímulos externos, eventos, pero
siempre datos siempre necesitará y acciones también.
La excepción, es que podemos crear una clase que solo contenga una estructura de información, y no sea
ejecutiva, no tenga métodos.
Esos son los tres apartados básicos a nivel de programación, propiedades, métodos y eventos.
Después mejoran las características de un programa por sus características de encapsulamiento, ocultación, polimorfismo y sobre todo de
herencia.
Lo más importante es empezar entendiendo bien como desarrollar una clase, y tener claro que de la clase después derivaremos objetos,
que serán en realidad donde se demuestre la capacidad de la clase.
Una clase es un elemento independiente del programa que la contiene, por lo tanto hemos de crear una estructura estanca y robusta.
Estanca porque no tiene dependencia de código ajeno, y cuando lo tiene es a través de la herencia de una clase anterior.
Pero no olvidemos que al fin y al cabo, al final, lo que hay es código, y el código son las estructuras de programación ya conocidas, más
los datos.
13.3. Datos.
Una clase necesita de datos para su funcionamiento.
Disponemos de dos niveles en su utilización.
Internos.
Extermos, propiedades.
Los datos que son simplemente variables para el funcionamiento de la clase y que en ningún caso podrán ser utilizados ni visualizados
por el usuario del objeto que de ella se deriva, y los datos que son necesarios que se proporcionen para el uso de la misma.
Pág. 13.1
Clase Ejemplo
Crear X Entera = 0
Crear Y Entera = 0
Crear Z Entera = 0
...
65
Esos datos internos, puede ser que necesiten un valor inicial cuando se crea un objeto de la clase, en ese caso esas variables pueden ser
cargadas en el momento de declarar una nueva instancia de la clase.
Con una u otra sintaxis, los lenguajes de programación disponen de una instrucción mediante la cual se crea una instancia de una clase,
se crea un objeto, en esa instrucción se puede reclamar desde la clase que se indique el valor de determinados parámetros.
Clase Ejemplo
Crear X Entera
Crear Y Entera
Crear Z Entera
Inicio de Programa
Crear Objeto como Ejemplo
Objeto = Nueva instancia de Ejemplo(1,20)
Fin de Programa
Cuando ejecutamos …
Pero también se puede crear el objeto sin valores iniciales y después en el momento de utilizar el método solicitar los valores necesarios
para el uso de ese método.
Metodo Nuevo()
Fin Metodo
Podemos observar como el método Nuevo, carece de código, e incluso, si el lenguaje de programación no lo exije, podría no existir.
Clase Ejemplo
Crear X Entera = 0
Crear Y Entera = 0
Crear Z Entera = 0
Objeto.Cuenta(1,20)
66
Y el programa quedaría como sigue.
Inicio de Programa
Crear Objeto como Ejemplo
Objeto = Nueva instancia de Ejemplo
Objeto.Cuenta(1,20)
Fin de Programa
Recalcar que en el ejemplo anterior, los datos son internos en la clase y que tanto X, Y, Z no son visibles desde el exterior de la clase.
Pág. 13.2
Clase Ejemplo
Crear X Entera
Crear Y Entera
Crear Z Entera
Propiedad Final
Lectura
Z = Final
Escritura
Final = Z
Fin propiedad
Metodo Cuenta
X=Y
Mientras X <> Z
...
...
X = X + 1
Fin Mientras
Fin Metodo
Fin Clase
Inicio de Programa
Crear Objeto como Ejemplo
Objeto = Nuevo instancia de Ejemplo
Objeto.Inicio = 1
Objeto.Final = 20
Objeto.Cuenta
Fin de Programa
Esto podría ser una clase, en ella “X” es una variable interna, en ningún caso se puede ver desde el exterior, mientras que “Y” y “Z” son
dos variables que son en realidad una propiedad, puesto que sus valores son visibles desde el exterior, pero se ven a través del nombre que las
representa que es “Inicio” y “Final”.
67
Propiedad Inicio Entera
Propiedad Final Entera
Para posteriormente en el programa, después de crear una instancia de la clase Ejemplo utilizar las propiedades.
Inicio Programa
Crear Objeto como Ejemplo
Objeto = Nueva instancia de Ejemplo
Objeto.Inicio = 10
Objeto.Final = 20
Objeto.Cuenta
Fin programa
Inicio Programa
Crear Objeto como Ejemplo
Objeto = Nueva instancia de Ejemplo
Objeto.Y = 10
Objeto.Z = 20
Objeto.Cuenta
Fin programa
La ventaja de declararlas a través de propiedades, radica en la posibilidad de crear código de
control en el interior de la propiedad, mientras que como variable pública eso no será posible
normalmente.
Todo dependerá de la necesidad de control de los datos.
Pág. 13.3
Conviene tener la precaución de utilizar nombres de variables que no entren en conflicto por el nombre con otras declaradas a nivel de la
clase, es el mejor sistema para evitar problemas, a pesar de que se pueden utilizar sintaxis que no dejan lugar a duda de si se hace referencia a
una u otra variable, -del método o de la clase-, en el caso de coincidir, pero es mejor evitar la ocasión y así esquivar el problema.
Es importante tener presente el ámbito de influencia de las mismas, siempre es aconsejable que las variables sean lo más próximas
posibles a su punto de utilización, para que de esa forma finalizada su utilidad se liberen.
13.7. Conclusiones.
En la imagen podemos ver como el programa es la zona amarilla, que lo abarca todo.
El objeto, es la zona azul, lo que hay en el interior de la zona azul son variables, los procedimientos y funciones no se han incluido, que se
derivan de la clase ejemplo.
Lo que está unido al objeto con la flecha es lo que consideramos las propiedades, faltan los métodos, que es la parte que se ofrece al
programa, al programador.
Se ha visto varias formas de iniciar los datos de una clase, pero son solamente distintas formas de abordar los datos de una clase, no es
que unas sean mejores que otras, si no que según el diseño de la clase, eso nos llevará a utilizar uno u otro sistema.
Se crean del tipo adecuado y si es necesario se inicializan a un valor adecuado, para ser utilizadas.
Internas, variables Se crean del tipo adecuado y si es necesario se inicializan a un valor adecuado, para ser utilizadas.
68
Externas, propiedades Se crean del tipo adecuado y sí, que es imprescindible que se inicialicen a un valor adecuado, para que de forma
predeterminada, si no se asignan valores externos, pueda usarse el objeto con unos valores iniciales
previos y válidos, que no generen un error.
Pág. 13.4
Unidad 14. Clases en VB (I)
14.1. Objetivos del tema.
Se han explicado los conceptos imprescindibles de una clase, métodos y propiedades, ahora tenemos que aplicarlos en este caso en VB.
14.2. Introducción.
Las clases son el molde a partir del cual obtenemos el objeto en nuestro programa, y el objeto es en realidad el que tiene el protagonismo
de la acción, la clase es solo el molde.
Vamos a ver como aplicar los conceptos vistos con anterioridad en VB.
14.3. Crear la clase.
Lo ideal es tener un módulo con las o la clase en nuestro proyecto, de forma que estén
agrupadas de forma práctica para nosotros.
14.4. El objeto.
Primero creemos el objeto.
Nuestra clase ahora es así.
End Class
Ahora creamos un objeto de esa clase.
Objeto.
Si vemos la imagen, ese es el resultado, son los métodos estándar de cualquier objeto.
Internos.
Externos.
Veamos como definir los datos internos en la clase, es decir los que no se ven en el exterior.
69
Exactamente lo mismo que antes, como los datos son internos no se ven fuera de la clase.
Ahora externos, o sea, propiedades.
Pág. 14.1
La declaración del constructor como public sin argumentos permite la creación de objetos sin la utilización de datos, esto no siempre
puede ser práctico o cómodo.
Si en lugar de declarar el constructor como public lo declaramos como private, se impide que se generen instancias de un objeto sin que
estos tengan los valores que se reclamen como adecuados en el método.
Sub Main()
Dim Objeto As Ejemplo
Objeto.DatoExterno = "Contenido de la propiedad"
Console.WriteLine(Objeto.DatoExterno)
Console.ReadKey()
70
End Sub
No hemos podido utilizarlo, falta un pequeño matiz, hemos definido que el objeto es del tipo Ejemplo, pero no se ha creado una instancia
del mismo, cambiemos la forma de definir el objeto por la que sigue.
Contenido de la propiedad
para evitar el error de sintaxis que podemos observar en la imagen, ya que no se ha introducido el valor que solicitamos en el método
new.
Sub Main()
Dim Objeto As New Ejemplo("Contenido de la propiedad.")
Console.WriteLine(Objeto.DatoExterno)
Console.ReadKey()
End Sub
Ahora si que funciona, y este sería el resultado.
Contenido de la propiedad.
Fijémonos en que a la propiedad DatoExterno le hemos asignado el valor obtenido en el método New.
Además no se ha realizado ningún control sobre ese dato.
Al método new se le denomina constructor de la clase.
Pág. 14.2
Unidad 14. Clases en VB (III)
2 Asignar controladamente los datos.
Se trata de utilizar la sintaxis de propiedad en lugar de la de variable pública.
Al utilizar esta opción, podemos recoger los datos realizando una validación de los mismos antes de asignar el dato a la variable interna
nuestra dentro de la clase.
71
La variable interna de la clase, que está oculta.
Console.WriteLine(Objeto.Propiedad)
El resultado sería:
Cambio de contenido
Un ejemplo de su utilización sería:
Sub Main()
' Dim Objeto As New Ejemplo("Contenido de la propiedad")
Dim Objeto As New Ejemplo("") ‘ se rechaza la inicialización
Console.WriteLine(Objeto.Propiedad)
Console.ReadKey()
End Sub
Podemos seleccionar una de las dos opciones en la inicialización del objeto:
Sub Main()
Dim Objeto As New Ejemplo("Contenido de la propiedad")
Console.WriteLine(Objeto.DatoExterno)
Objeto.DatoExterno = ""
Console.WriteLine(Objeto.DatoExterno)
73
Console.ReadKey()
End Sub
La ejecución quedaría como sigue:
Nuevo valor
La línea en blanco es la que provoca ésta instrucción
Objeto.DatoExterno = ""
Console.WriteLine(Objeto.DatoExterno)
La clase completa de éste ejemplo quedaría:
3º Añadir a la clase anterior el método new, de forma que se pueda cargar los valores iniciales de las propiedades
en el mismo.
75
Dim Propie As String = "Valor por defecto"
Dim PropieLectura As Integer = 3
Dim PropieAsignac As String = "Valor por defecto"
Module Module1
Sub Main()
Dim Objeto As New Ejercicio ' ("Nuevo")
76
Get
Return Propie ' Lectura
End Get
Set(ByVal value As String)
If value <> "" Then Propie = value ' Asignación
End Set
End Property
End Sub
End Class
Module Module1
Sub Main()
Dim Objeto As New Ejercicio("Valor prop en new", 23, "Valor PropAsig en
New")
77
15.1. Objetivos del tema.
Hemos visto los datos en el tema anterior, veamos ahora los métodos.
Los métodos son los que nos van a permitir que una clase tenga la capacidad de realizar, resolver problemas, capacidad ejecutiva en
pocas palabras.
15.2. Introducción.
En una clase tenemos que escribir código con el fin de alcanzar los objetivos para la cual se diseña la misma.
Si no existiera código en la misma, la clase puede seguir existiendo, pero lo único que podríamos hacer con ella es crear una estructura
de datos, más o menos compleja.
Las variables, propiedades, los datos, almacenan la información que se utiliza en la clase para poder
realizar las acciones para las cuales se escriben los métodos de la misma.
Con el código sucede lo mismo, una clase se diseña para resolver un problema.
Ese problema, para resolverlo se descompone en una serie de acciones de menor entidad, y en su solución
se podrán utilizar acciones de dos tipos:
Externas.
Internas.
Las acciones externas serán las que ofreceremos al usuario para que pueda interactuar con el objeto que
se deriva de la clase.
Las acciones internas son las que creamos nosotros de forma interna en nuestra clase para crear el código que resuelva el problema para
el cual se diseña la clase.
Sea cual sea el caso, el código lo escribiremos dentro de un procedimiento o de una función, y cuando sean internas las denominaremos
exclusivamente funciones o procedimientos, según corresponda, pero cuando sean externas se convertirán en métodos.
Explicado en sentido inverso, los métodos son la parte de código que se ve en una clase.
Los métodos se escriben utilizando procedimientos o funciones, en función de nuestras necesidades.
En la clase existen otros procedimientos y funciones, pero no son públicos, o no son métodos, y no se pueden utilizar por el usuario de la
clase, del objeto que se deriva de ella.
En cualquier caso, en los procedimientos y funciones, sean internos o externos, lo que tenemos es código con las estructuras de
programación ya conocidas, lineales, alternativas o repetitivas.
Una clase al fin y al cabo es un programa más, no hay diferencias en cuanto a la solución de los problemas, pero el matiz es que un
programa se inicia a instancia del usuario, y una clase se inicia a solicitud de una instrucción desde el interior de un programa.
Clase Ejemplo
78
Funcion EsPar(Numero como Entera) Como Booleana
EsPar = Numero Modulo 2 = 0
Fin de Funcion
Inicio Programa
Crear Objeto como Ejemplo
Objeto.NumerosPares(10,50)
Fin programa
Pág. 15.1
Clase Ejemplo
Crear X Entera = 0
Crear Y Entera = 0
Crear Z Entera = 0
Inicio Programa
Crear Objeto como Ejemplo
Objeto.Inicio = 10
Objeto.Final = 20
Objeto.Cuenta
79
Fin programa
Si miramos el ejemplo del método, podremos observar que ese método no devuelve ningún dato, y que lo que realiza es una acción, nos
suena de algo, ¿procedimiento?.
Metodo Cuenta
X=Y
Mientras X <> Z
...
...
X = X + 1
Fin Mientras
Fin Metodo
Sí, es un procedimiento.
Inicio Programa
Crear Objeto como Ejemplo
Crear Par como Booleano
Objeto.NumeroPar(10,Par)
Si Par = Cierto Entonces
Escribir (“El número es par”)
Si no
Escribir (“El número es par”)
Fin de condicion
Fin programa
Pero cuando vimos las funciones vimos que su uso es más estético, y nuestro programa es más legible, pues escribamos una función en
lugar de un procedimiento, pero como método.
Inicio Programa
Crear Objeto como Ejemplo
Que la clase se compone de procedimientos y funciones, y que cuando estos son públicos, se convierten en métodos.
Que el punto de partida son los métodos que componen la clase.
Y como una clase tiene muchos métodos, en realidad hay muchos puntos de partida.
80
Pero en realidad, tendríamos que decir que el punto de partida es el método que hemos llamado Nuevo en los ejemplos y que se ejecuta
cada vez que se crea una instancia de la clase, ya que después podríamos decir que la clase, el objeto, queda a la espera de los métodos que
sean ejecutados.
Añadamos también que en el interior de los métodos, procedimientos, funciones, lo que tenemos escrito son las estructuras de
programación que vimos al inicio de curso.
Estructuras lineales.
Estructuras alternativas, condicionales
Estructuras repetitivas.
Pág. 15.2
En el ejemplo de clase que sigue, se ha creado un método que visualiza los números primos entre dos valores determinados.
Final = CLng(Numero / 2) + 1
Select Case Numero Mod 2 <> 0
Case True
While X < Final And Result
Result = Numero Mod X <> 0
X = X + 1
81
End While
Case Else
If Numero > 2 Then Result = False
End Select
Primos = Result
End Function
End Class
En la clase vemos como disponemos de un procedimiento que es public, es un método, y de una función que es private, es una función,
no es un método.
Podemos comprobarlo porque si escribimos en el entorno de programación, “Objeto.”
lo único que podemos ver es NumerosPrimos.
En ella vemos como en el método se llama a la función que devolverá cierto o falso
en función de que el número sea primo o no.
x = x + 1
Después su utilización en el programa principal será como vemos en el ejemplo.
Module Module1
Sub Main()
Dim Objeto As Ejemplo = New Ejemplo
Objeto.NumerosPrimos(10, 50)
End Sub
End Module
Y su aclaración …
Objeto.NumerosPrimos(10, 50)
Y ejecutamos el método con el rango que deseamos visualizar.
Nada que nos pueda parecer extraño.
El único cambio está en el exterior.
82
Y después en el programa principal.
Sub Main()
Dim Objeto As Ejemplo = New Ejemplo
Objeto.NumerosPrimos(10, 50)
End Sub
Pág. 16.1
Por lo tanto lo que necesitamos es una función que es la estructura con la que se obtiene un dato a partir de la ejecución de la misma, así
que podemos convertir la función de antes en un método, basta con cambiarla de private a public:
Final = CLng(Numero / 2) + 1
Select Case Numero Mod 2 <> 0
Case True
While X < Final And Result
Result = Numero Mod X <> 0
X = X + 1
End While
Case Else
If Numero > 2 Then Result = False
End Select
Primos = Result
End Function
Y así en nuestro programa podremos escribir:
Sub Main()
Dim Objeto As Ejemplo = New Ejemplo
Dim Numero As Integer
Numero = CInt(Console.ReadLine)
83
End Sub
Primos nos devolverá un valor cierto o falso.
Por lo que podemos comprobar que un método puede ser escrito como función o como procedimiento.
Solo hay que utilizar la sintaxis adecuada en cada momento.
16.7. Conclusiones.
Se ha visto en el tema donde se escribe el código dentro de una clase.
Que la clase se compone de procedimientos y funciones, y que cuando estos son públicos, se convierten en métodos.
Que el punto de partida son los métodos que componen la clase.
Y como una clase tiene muchos métodos, en realidad hay muchos puntos de partida.
Pero en realidad, tendríamos que decir que el punto de partida es New y que se ejecuta cada vez que se crea una instancia de la clase,
ya que después podríamos decir que la clase, el objeto, queda a la espera de los métodos que sean ejecutados.
Añadamos también que en el interior de los métodos, procedimientos, funciones, lo que tenemos escrito son las estructuras de
programación que vimos al inicio de curso.
Estructuras lineales.
Estructuras alternativas, condicionales
Estructuras repetitivas.
1. Hallar el área y la longitud de una circunferencia, solicitando el radio de la misma R . Area = PI * R al cuadrado,
Longitud = 2 * PI * R .
2. Hallar el área de un triángulo. Area = Base por Altura / 2.
3. Introducir un número A y visualizar si es o no primo.
4. Introducir una calificación (entre cero y diez), e imprimir su equivalente alfabético, según la siguiente tabla.
De 3 -------> M.D.
Desde 3 y menor que 5 -------> INS.
Desde 5 y menor que 6 -------> SUF
Desde 6 y menor que 7 -------> BIEN
Desde 7 y menor que 9 -------> NOT.
Desde 9 hasta 10 -------> SOB.
5. Introducir un valor en metros y visualizar su valor en millas terrestres, marinas , yardas y leguas.
Milla terrestre = 1.609,34 m.
Milla marina = 1.852,00 m.
Yarda = 4.190 m.
Legua = 0,9144 m.
6. Introducir una fecha en pantalla con el formato día, mes y año en tres variables numéricas, validar la fecha y emitir
el mensaje de fecha incorrecta o correcta.
7. A partir de los siguientes valores de moneda extranjera, crear una función que a partir de un importe en pesetas
devuelva su equivalente en la moneda que se indique.
1 Franco francés 25,2400 25,3920
1 Lira 0,0859 0,0864
1 Libra esterlina 245,5560 247,0340
1 Dólar americano 150,2280 151,1320
1 Marco alemán 84,6480 85,1570
1 Franco suizo 101,7550 102,3670
1 Florín holandés 5,1170 75,5690
1 Escudo portugués 0,8262 0,8312
8. Visualizar los números primos entre 10 y 200.
84
Public Sub New()
End Sub
Module Module1
Sub Main()
Dim Objeto As New Ejercicios
Dim Radio As Double
Sub Main()
Dim Base As Double
Dim Altura As Double
Dim Objeto as New Ejercicios
Console.ReadKey()
End Sub
85
El resultado de la ejecución:
Sub Main()
Dim Numero As Integer
Dim Objeto as New Ejercicios
Console.WriteLine("Números primos")
Console.WriteLine("Introducir número")
Numero = Console.ReadLine
Select Case Objeto.Primos(Numero)
Case True
Console.WriteLine("El número {0} es primo ", Numero)
Case Else
Console.WriteLine("El número {0} no es primo ", Numero)
End Select
Console.ReadKey()
End Sub
El resultado de la ejecución:
4. Introducir una calificación (entre cero y diez), e imprimir su equivalente alfabético, según la siguiente tabla.
De 3 -------> M.D.
Desde 3 y menor que 5 -------> INS.
Desde 5 y menor que 6 -------> SUF
Desde 6 y menor que 7 -------> BIEN
Desde 7 y menor que 9 -------> NOT.
Desde 9 hasta 10 -------> SOB.
El contenido de la clase es;
86
Public Class Ejercicios
Public Sub New()
End Sub
5. Introducir un valor en metros y visualizar su valor en millas terrestres, marinas , yardas y leguas.
Milla terrestre = 1.609,34 m.
Milla marina = 1.852,00 m.
Yarda = 4.190 m.
Legua = 0,9144 m.
87
Conversion = C
End Function
End Class
El programa principal:
Sub Main()
Dim Objeto as new Ejercicios
Dim Metros As Single
Dim Tipo As String
Console.WriteLine("Convertir distancia en metros ")
Console.WriteLine("Introducir distancia en metros")
Metros = Console.ReadLine
Console.WriteLine("Introducir M/T/L/Y ")
Tipo = Console.ReadLine
Console.WriteLine(Objeto.Conversion(Metros, Tipo))
Console.ReadKey()
End Sub
El resultado de la ejecución:
6. Introducir una fecha en pantalla con el formato día, mes y año en tres variables numéricas, validar la fecha y emitir
el mensaje de fecha incorrecta o correcta.
El contenido de la clase es;
Select Case M
Case 1, 3, 5, 7, 8, 10, 12
Fec = D > 0 And D < 32
Case 4, 6, 9, 11
Fec = D > 0 And D < 31
Case 2
Select Case A Mod 100 = 0
Case True
Fec = (D > 0 And D < 29) Or (D = 29 And A Mod 400 = 0)
Case Else
Fec = (D > 0 And D < 29) Or (D = 29 And A Mod 4 = 0)
End Select
End Select
Fecha = Fec
End Function
End Class
El programa principal:
Sub Main()
Dim Objeto as New Ejercicios
Dim Dia As Integer
Dim Mes As Integer
88
Dim Year As Integer
Console.WriteLine("Comprobar fecha ")
Console.WriteLine("Introducir dia")
Dia = Console.ReadLine
Console.WriteLine("Introducir mes")
Mes = Console.ReadLine
Console.WriteLine("Introducir año")
Year = Console.ReadLine
Select Case Objeto.Fecha(Dia, Mes, Year)
Case True
Console.WriteLine("La fecha es correcta")
Case Else
Console.WriteLine("La fecha no es correcta")
End Select
Console.ReadKey()
End Sub
El resultado de la ejecución:
7. A partir de los siguientes valores de moneda extranjera, crear una función que a partir de un importe en pesetas devuelva su
equivalente en la moneda que se indique.
1 Franco francés 25,2400 25,3920
1 Lira 0,0859 0,0864
1 Libra esterlina 245,5560 247,0340
1 Dólar americano 150,2280 151,1320
1 Marco alemán 84,6480 85,1570
1 Franco suizo 101,7550 102,3670
1 Florín holandés 5,1170 75,5690
1 Escudo portugués 0,8262 0,8312
89
El programa principal:
Sub Main()
Dim Objeto as New Ejercicios
Dim Pesetas As Integer
Dim Moneda As Char
End Sub
El resultado de la ejecución:
Que son todos los métodos que hemos escrito, en el formato de función.
Si repasamos el tema 12, también podemos ver que no hay diferencia entre sus soluciones y las de éste, excepto lo de poner las
funciones como públicas en la clase, en lugar de private.
Sub Main()
Dim Objeto as New Ejercicios
Objeto.NumerosPrimos(10,200)
Console.ReadKey()
90
End Sub
En los ejercicios anteriores se había utilizado funciones para cada uno de los métodos, en éste ejercicio la solución pasa por la utilización
de un procedimiento.
Inicialización
Ejecución
Finalización.
Y esas fases conviene recordarlas a la hora de la explotación de la misma, pues habrá algunas tareas que nos interesen se desarrollen
exclusivamente en ese instante, y no posteriormente.
17.3. Iniciar la clase, crear una instancia.
Cuando se crea un objeto a partir de una clase, el primer paso es instanciar ese objeto, con una u otra sintaxis, se dispone de un
constructor, un método especializado, que se ejecuta de forma automática al crearse el objeto de la clase en cuestión.
En VB se denomina New.
Clase Ejemplo
Metodo Constructor()
Fin Metodo
Clase Ejemplo
Crear VariableInterna Entera = 1
Metodo Constructor()
Fin Metodo
Clase Ejemplo
Crear VariableInterna Entera
Metodo PrimeraInstanciaSolamente()
VariableInterna = 1
91
Fin Metodo
Metodo Constructor()
Fin Metodo
Clase Ejemplo
Crear VariableInterna Entera
Metodo PrimeraInstanciaSolamente()
VariableInterna = 1
Fin Metodo
Fin Metodo
Normalmente es muy habitual que necesitemos varios escenarios posibles en el inicio de un objeto, por lo que la solicitud de datos en el
constructor se puede volver algo complicada.
En las clases existe el concepto de sobrecarga, esto significa poder escribir varias versiones de un mismo método, - más adelante se
expondrá el tema - , ese es el camino más adecuado para poder solventar el problema de los distintos escenarios posibles en el inicio de una
clase para los objetos que se derivan de ella.
En el siguiente ejemplo, podemos observar como se han escrito varias versiones del constructor en el cual se ha declarado distintas
versiones de la misma variable, String, Integer, aunque no tiene porque cambiar el nombre de la variable.
Clase Ejemplo
Privado Metodo Constructor()
Fin Metodo
Clase Ejemplo
Privado Metodo Constructor(EscenarioUno como String)
Fin Metodo
92
Podemos observar como en este ejemplo se mantiene el nombre de la variable, pero se añade una nueva en la segunda versión del
mismo.
17.5. Ejecución de la clase.
La clase no se ejecuta, se ejecuta una instancia de la misma, en el objeto que de ella se crea.
El punto de inicio es el constructor de la misma.
La ejecución del objeto, se iniciará en una fase inicial cuando se declara y se inicializa el mismo, y en segundas fases cuando se reclama
la ejecución de cualquiera de sus métodos.
La finalización de la ejecución de cualquiera de sus métodos no implica que deje de ser utilizado el objeto y que éste deje de consumir
recursos.
La ejecución permanecerá activa hasta que se ejecute una asignación de “nothing” o “null”, al objeto que de ella se deriva, o bien hasta
que desaparezca el mismo de la memoria por finalizar el procedimiento o programa que lo reclama, o bien finalicemos la misma con el método de
finalización previsto en el lenguaje.
Tengamos presente que mientras no se ejecute una de estas acciones, el objeto estará consumiendo recursos del sistema.
17.6. Finalización de la clase.
Las clases, sus objetos, mientras están en uso, están consumiendo recursos, lo que se traduce en memoria del sistema, por lo que
conviene que cuando un objeto deje de ser útil lo liberemos, puesto que eso permitirá disponer de más recursos al sistema.
Los sistemas suelen incluir un sistema de inspección que investiga que objetos no están siendo utilizados, para liberar el espacio que
ocupan, pero eso implica que hasta que esa situación se produce, el recurso está ocupado y sin poder ser utilizado por otros programas. De ahí la
importancia de finalizar el uso del objeto cuando dejemos de utilizarlo en nuestro programa, para evitar esa ocupación inadecuada de recursos,
sin que tenga que ser la finalización del procedimiento o del programa el que acabe con él, lo que es una demora en el tiempo.
La finalización de un objeto se puede conseguir con la ejecución de un método de finalización, runFinalize, o Finalize, en cada lenguaje
tendrá un nombre.
System.Recolectar
Clase.Finalizar
Sin embargo hay que asegurarse de que ese método se ejecute, ya que podría darse la situación de que no fuera llamado por el sistema,
por lo tanto hay que comprobar en el lenguaje en uso si esa situación puede darse.
También conviene comprobar si el lenguaje utilizado dispone de métodos que obliguen a la hora de la finalización de la ejecución del
programa a la inspección de la existencia de métodos de finalización sin ejecutar todavía.
Pág. 17.2
Inicialización
Ejecución
Finalización.
18.3. Iniciar la clase, crear una instancia.
Cuando se crea un objeto a partir de una clase, el primer paso es instanciar ese objeto, con una u otra sintaxis, se dispone de un
constructor, un método especializado, que se ejecuta de forma automática al crearse el objeto de la clase en cuestión.
End Sub
93
Public Class Clase
Public UnDato As Integer
' Constructor sin captura de datos
Public Sub New()
End Sub
En muchas ocasiones es imprescindible, sobre todo cuando deseamos exigir datos en la inicialización de la misma, y no deseamos que se
inicie una copia de nuestra clase de forma accidental.
Normalmente es muy habitual que necesitemos varios escenarios posibles en el inicio de un objeto, por lo que la solicitud de datos en el
constructor se puede volver algo complicada.
En las clases existe el concepto de sobrecarga, esto significa poder escribir varias versiones de un mismo método, - más adelante se
expondrá el tema - , ese es el camino más adecuado para poder solventar el problema de los distintos escenarios posibles en el inicio de una
clase para los objetos que se derivan de ella.
94
En el siguiente ejemplo, podemos observar como se han escrito varias versiones del constructor en el cual se ha declarado distintas
versiones de la misma variable, String, Integer, aunque no tiene porque cambiar el nombre de la variable.
End Sub
End Class
Podemos observar como en este ejemplo se mantiene el nombre de la variable, pero se añade una nueva en la segunda versión del
mismo.
18.5. Ejecución de la clase.
La clase no se ejecuta, se ejecuta una instancia de la misma, en el objeto que de ella se crea.
El punto de inicio es el constructor de la misma.
La regla de oro a seguir es que no se debe poner ningún código que deba ser ejecutado en el método finalize().
Por ejemplo, si se necesita concluir la comunicación con un servidor cuando ya no se va a usar un objeto, no debe ponerse el código de
desconexión en el método finalize, porque puede que nunca sea llamado.
95
Es responsabilidad del programador escribir métodos para realizar la limpieza que no involucre a la memoria ocupada por el objeto y
ejecutarlos en el instante preciso.
Objeto = nothing
El método finalize y el recolector de memoria son útiles para liberar la memoria de la pila y debería restringirse su uso solamente a eso, y
no depender de ellos para realizar ningún otro tipo de limpieza.
En la construcción de un objeto, se desplaza uno por el árbol de jerarquía, de herencia, desde la raíz del árbol hacia las ramas, y en la
finalización, es al revés, los desplazamientos por la herencia debe ser desde las ramas hacia las superclases hasta llegar a la clase raíz.
End Sub
End Class
2. Crear una clase en la que al iniciar una instancia de la clase se tenga que introducir un valor entero, y comprobar
que su valor es mayor que cero y menor que diez.
La clase será:
Public Class Ejercicios
Public Sub New()
End Sub
Sub Main()
Dim Objeto As Ejercicios = New Ejercicios(20)
Console.ReadLine()
End Sub
End Module
El resultado será
3. Con la clase del ejercicio anterior, añadir una variable interna que se llame Dato, dicha variable será inicializada a
cinco, y que tome el valor de la inicialización del objeto en caso de ser válido.
La clase será:
Public Class Ejercicios
Dim Dato As Integer = 5
96
Public Sub New()
End Sub
Sub Main()
Dim Objeto As Ejercicios = New Ejercicios(20)
Console.ReadLine()
End Sub
End Module
El resultado será:
1. Con la clase del ejercicio anterior, añadir un método llamado finalizar, y colocar en el un texto que permita
visualizar su ejecución. En el programa principal asignar al objeto una vez utilizado una línea que le asigne
nothing.
Public Class Ejercicios
Dim Dato As Integer = 5
Module Module1
Sub Main()
Dim Objeto As Ejercicios = New Ejercicios(20)
Objeto = Nothing
Objeto.Finalizar()
Console.ReadLine()
97
End Sub
End Module
El resultado sería erróneo al tener
Objeto = Nothing
Antes de la siguiente línea.
Objeto.Finalizar()
Sería correcto si estuviera:
Module Module1
Sub Main()
Dim Objeto As Ejercicios = New Ejercicios(20)
Objeto.Finalizar()
Objeto = Nothing
Console.ReadLine()
End Sub
End Module
Como figura en el ejemplo, teniendo en cuenta que hay cierta redundancia en el mismo.
Cuando solo se admite la herencia de una clase origen, se denomina herencia simple, y si se admite más de una clase se denomina
herencia múltiple.
La herencia múltiple es más compleja, tenemos que tener presente que cuando
en una clase se heredan al mismo nivel varias clases origen, el problema surge cuando se
da la circunstancia de existir métodos con el mismo nombre, pues hay que decidir cual de
ellos es el que dispone de prioridad al ser utilizado, o bien cuando se llama a un método y
éste tiene que buscarse por varias de las ramas posibles de las distintas herencias
disponibles en la clase actual.
Si miramos la imagen de la derecha, en esa forma de rombo, si la clase siete hereda la cuatro, cinco y seis,
cuando se indica el uso de un método que no es de la propia clase siete, hay que buscarlo en todas las ramas posibles, es
decir, en la rama cuatro, dos y uno, pero también en la rama cinco, dos, uno y en la rama seis, tres y uno.
En cuanto a la herencia, hay que pensar que los métodos de la clase uno, puede ser que aparezcan, - en función
de cómo cada lenguaje gestione la herencia -, repetidos varias veces, lo que genera ambigüedades en la gestión.
Dicho de otra forma, se complica en gran medida la gestión y localización de los métodos y el sistema de
prioridades en el momento de localizar dos al mismo nivel, de ahí que lo que habitualmente contemplan los lenguajes de
98
programación mayoritariamente es la herencia simple, que es más sencilla de gestionar, y también por consecuente más eficiente.
19.6. Sobre escritura.
Una vez que se crea una clase a partir de otras de origen, puede darse la circunstancia de que los métodos que tengamos heredados no
nos interesen, en ese caso los métodos pueden ser sustituidos, sobre escritos, y entonces se ejecutarían los que se crean de nuevo en la clase
resultante, ignorándose los de la clase origen.
19.7. Limitaciones en la herencia.
Todos los campos y métodos de una clase son siempre accesibles para el código de la misma clase.
Para controlar el acceso desde otras clases, y para controlar la herencia por las clases derivadas, o subclases, los elementos (atributos y
métodos) de las clases tienen tres situaciones posibles de control de acceso:
Público, public Los miembros declarados públicos son accesibles en cualquier lugar en que sea accesible la clase, y son heredados por las
subclases.
Privado, private Los miembros declarados privados son accesibles sólo en la propia clase.
Protegido, protected Los miembros declarados protegidos son accesibles sólo para sus subclases
19.8. Conclusiones.
El uso de la herencia nos puede permitir crear la siguiente estructura.
Creamos la clase persona, en esta clase definimos la estructura de datos personales y escribimos un
método que nos visualice dichos datos en el soporte que se crea oportuno.
Después podemos escribir la clase alumno, y que esta clase herede la clase persona, por lo que ya
tenemos a nuestra disposición todo lo referente a los datos personales y su visualización, provenientes de la
clase base, Persona, y a la clase alumno le añadimos lo referente a los datos académicos y su
correspondiente visualización.
Y podemos hacer lo mismo con la clase profesor, pero en lugar de datos académicos, le definimos
datos administrativos.
Por lo tanto, ambas clases, alumno y profesor, heredan la misma clase, persona, y comparten la
gestión de los datos personales.
Si creamos el objeto
Y así sucesivamente podemos ir ampliando las características de cada una de las clases, e ir mejorando la estructura de las mismas.
Pág. 19.1
Unidad 20. La herencia en las clases en VB (I)
20.1. Objetivos del tema.
La herencia es una de las características de las clases, vamos a ver el funcionamiento y sus ventajas de cara al uso dentro de los
programas en Visual Basic.
20.2. Introducción.
La herencia es una de las posibilidades que nos ofrece el uso de las clases en general.
Visual Basic ofrece esta posibilidad utilizando la herencia simple.
Visual permite la creación de clases que pueden ser
Evidentemente cualquier clase puede ser heredada excepto las que se declaren en uno de los otros formatos.
El fin de la herencia es el crear un punto de partida con un código existente y que ya está asentado, o no, para ampliar las capacidades en
una nueva versión o modificar ciertos aspectos de la clase base.
20.3. Clase base, origen.
Veamos un ejemplo de herencia en VB,
Module Module1
Sub Main()
' definición de la clase
Dim Objeto As New Nueva
Objeto.Visualiza()
Objeto.Incrementa()
Objeto.Visualiza()
Console.ReadLine()
End Sub
End Module
Y ejecutamos dicho ejemplo podremos observar como el resultado es el adecuado.
Así de sencillo.
La clase Ejemplos es la clase base, u origen.
20.4. Clase derivada.
Por lo tanto la clase Nueva es la clase derivada.
La clase derivada es la clase resultante al heredar la clase Ejemplos, y asumirá todas las características de las clases origen.
Además en esta clase podemos añadiremos las características necesarias para que cumpla la función para la cual se diseña.
Pág. 20.1
Unidad 20. La herencia en las clases en VB (II)
20.5. Resultado de la herencia.
Como consecuencia de la herencia, debemos disponer de la posibilidad, porque es una de sus necesidades, de poder reescribir o
reemplazar métodos de la clase base, con el fin de sustituirlos.
Pero también podría ser que nos interese que un método de nuestra clase no pueda ser reescrito.
De esa forma es como se va tejiendo las características de las clases en la herencia.
Para ello se dispone en Vb de la posibilidad de reescribir mediante el uso de
Cuando se hereda una clase MustInherit automáticamente VB escribe los métodos declarados en la clase base como MustOverride.
100
Public MustOverride Sub MetodoQueDebeSerEscrito()
Public Overridable Sub MiMetodo()
La clase derivada podría ser:
Class ClaseDerivada
Inherits ClaseBase
Class ClaseBase
Public Sub Sombreado()
Console.WriteLine("Texto desde sombreado")
End Sub
El ejemplo que sigue puede dar una idea del uso de Me, y MyClass, pero como realmente se aprecia el ejemplo es ejecutándolo paso a
paso, con <F8>, y no solo una vez, para comprenderlo.
Hay que fijarse en que MiMetodo está definido en las dos clases, y en función del uso de Me o MyClass se ejecuta uno u otro.
Class ClaseDerivada
101
Inherits ClaseBase
Y el principal sería:
Module Module1
Sub Main()
Dim Objeto As New ClaseDerivada
Objeto.MiMetodo()
Objeto.Sombreado()
Objeto.UsandoMe()
Objeto.UsandoMyClass()
Console.ReadLine()
End Sub
End Module
El resultado de la ejecución.
Público, public Los miembros declarados públicos son accesibles en cualquier lugar en que sea accesible la clase, y son heredados por las
subclases.
Privado, private Los miembros declarados privados son accesibles sólo en la propia clase.
Protegido, protected Los miembros declarados protegidos son accesibles sólo para sus subclases
En VB además disponemos de Protected Friend que permite que la clase base visualice el método protegido en un objeto derivado de la
clase base.
Ejercicios propuestos de la Unidad
Pág. 20.3
Ejercicios unidad 20: La herencia en las clases en VB
1. Escribir una clase que se tenga que heredar y en la que haya un método que se deba escribir en la clase
heredada.
2. Escribir una clase que herede la clase anterior y que desarrolle el método pendiente en dicha clase, crear un
objeto de ésta clase que permita realizar la prueba de funcionamiento de dicho método.
102
Public Sub New()
End Sub
Module Module1
Sub Main()
Dim Objeto As Nueva = New Nueva
Objeto.VisualizarAbecedario()
Console.Read()
End Sub
End Module
Unidad 21. La sobrecarga en las clases (I)
21.1. Objetivos del tema.
La sobrecarga, overload, es la posibilidad de tener varias versiones de un mismo método, vamos a ver como crearlo y como funciona.
21.2. Introducción.
Una de las características de las clases es la posibilidad de poder escribir varias versiones de un mismo método, sin necesidad de
cambiar el nombre, de esa forma se puede salvar el problema que puede surgir al tener que realizar la misma acción pero con escenarios
distintos, en caso de que no existiera la sobre carga, eso nos llevaría a tener que escribir la misma cantidad de métodos pero con nombres
distintos, lo que complicaría la elección del método adecuado en alguna ocasión.
La sobrecarga se produce cuando el método coincide en nombre pero no en el número de argumentos o aunque tenga el mismo número
de argumentos el tipo de los datos de los mismos cambia.
21.3. Creación.
La sobrecarga en realidad implica la escritura de tantos métodos como versiones tengamos, eso es así porque si se da la circunstancia de
distintos escenarios en cada uno de ellos, aunque cada método en realidad realice la misma tarea, el punto de partida será distinto, por lo que
dará lugar a distintas formas de realizar la misma tarea, y distintas líneas de argumentos de entrada al método.
Tampoco es que haya que reescribir todo el método por completo, pensemos que disponemos de los procedimientos, y estos estarán
disponibles para los mencionados métodos, y posiblemente solo sea necesario reescribir parte del mismo, sobre todo si se estructura bien el
método desde su origen.
Como ejemplo veamos el siguiente método.
Clase Ejemplo
Metodo Suma(Entero A, Entero B)
Suma = A + B + C
Final Metodo
Clase Ejemplo
Metodo Suma(Entero A, Entero B, Entero C)
Suma = A + B + C
Final Metodo
103
Metodo Suma(Real A, Entero B, Largo C)
Suma = A + B + C
Final Metodo
En el ejemplo siguiente lo que tenemos no es una sobre carga y daría error, porque la firma, identificación, como deseemos llamarlo, de
los métodos es idéntica.
Clase Ejemplo
Pág. 21.1
Unidad 22. La sobrecarga en las clases en VB (I)
22.1. Objetivos del tema.
La sobrecarga, overload, es la posibilidad de tener varias versiones de un mismo método, vamos a ver como crearlo y como funciona
desde el lenguaje VB.
22.2. Introducción.
Las características de la sobrecarga permite escribir varias versiones del mismo método, en VB no es necesario indicar con ninguna
palabra previa que un método está sobrecargado basta con que existan dos procedimientos o funciones con el mismo nombre pero tengan
distintas líneas de parámetros.
22.3. Creación.
En el ejemplo que sigue disponemos de tres métodos new.
La segunda y la tercera son iguales, aunque las variables sean distintas, por lo tanto deberíamos eliminar una de las dos.
104
End Class
Para este caso la solución podría pasar por :
Podemos observar como se introduce un importe y luego solo hay que elegir una de las opciones disponibles.
De esa forma no habría que utilizar una sobrecarga para resolver el problema.
Solo quedaría escribir un método convertir para realizar la conversión adecuada en función de lo que se necesite.
Case Monedas.Libra
Case Monedas.Yen
End Select
End Function
De tal forma que en el principal quedaría.
Module Module1
Sub Main()
Dim Importe As Double = Console.ReadLine
Dim Objeto As Ejemplos = New Ejemplos(Importe, Ejemplos.Monedas.Euro)
Console.WriteLine(Objeto.Convertir(Ejemplos.Monedas.Dolar))
Console.ReadLine()
End Sub
End Module
Pág. 22.1
En el siguiente ejemplo podemos ver repetido el mismo método en tres ocasiones, serían tres sobrecargas.
En el ejemplo que sigue podemos ver como las sobrecargas de cada método llaman al mismo procedimiento y lo que se hace es ofrecer
distintas opciones al usuario, completando por programa las carencias.
Module Module1
Sub Main()
Dim Objeto As Ejemplos = New Ejemplos
Objeto.EscribirTexto()
Objeto.EscribirTexto("Hola mundo")
Objeto.EscribirTexto("Hola", ConsoleColor.Blue, ConsoleColor.DarkBlue)
Console.ReadLine()
End Sub
End Module
106
Es importante recordar que desde los métodos, podemos ejecutar código privado, funciones o procedimientos, lo cual reduce el volumen
de código que hay que escribir, y reduce la posibilidad de errores.
22.4. Conclusiones.
La sobre carga, overload, nos permite que un mismo método podamos tenerlo escrito con distintas versiones y con el mismo nombre, de
forma que podemos tener distintos puntos de partida para una misma acción.
La sobrecarga se produce cuando el método coincide en nombre pero no en el número de argumentos o aunque tenga el mismo número
de argumentos el tipo de los mismos cambia.
Ejercicios propuestos de la Unidad
Pág. 22.2
Ejercicios unidad 22: La sobrecarga en las clases en VB
1.- Crear un método en el que dispongamos la posibilidad de calcular el coste de un artículo de forma que el cálculo
se pueda realizar aplicando un descuento, sin descuento y con un recargo del diez por ciento, recibiendo siempre
el precio y las unidades vendidas.
2.- Crear un método que permita calcular la nota de un alumno como
la media a partir de dos notas recibidas
la media ponderada a partir de dos notas recibidas y el número de horas dedicadas en cada una de dichas
notas.
La formula es la que sigue, donde X sería la nota y w sería las horas adjudicadas a cada nota.
3.- Crear un método que permita visualizar un texto en modo consola con o sin colores de fondo y de primer plano,
Console.background y Console.Foreground
107
Importe = Cantidad * Precio
End Function
End Class
El programa principal es :
Module Module1
Sub Main()
Dim Objeto As Ejercicios = New Ejercicios
Dim Precio As Double = 10.2
Dim Cantidad As Integer = 20
Dim Descuento As Single = 10
Dim Recargo As Single = 5
Module Module1
Sub Main()
Dim Objeto As Ejercicios = New Ejercicios
Console.WriteLine("la nota media es {0} ", Objeto.Nota(5, 5))
Console.WriteLine("la nota media ponderada es {0} ", Objeto.Nota(4, 90,
5, 40))
Console.ReadLine()
End Sub
End Module
3.- Crear un método que permita visualizar un texto en modo consola con o sin colores de fondo y de primer plano,
Console.background y Console.Foreground
La clase podría ser:
Public Class Ejercicios
108
Private Sub Escribe(ByVal Texto As String, _
ByVal ColorTexto As ConsoleColor, _
ByVal ColorFondo As ConsoleColor)
Console.ForegroundColor = ColorTexto
Console.BackgroundColor = ColorFondo
Console.WriteLine(Texto)
End Sub
Module Module1
Sub Main()
Dim Objeto As Ejemplos = New Ejercicios
Objeto.EscribirTexto()
Objeto.EscribirTexto("Texto ")
Objeto.EscribirTexto("Texto ", ConsoleColor.Blue,
ConsoleColor.DarkBlue)
Console.ReadLine()
End Sub
End Module
¿Cuando definir una clase?, en principio eso va a ser un problema, pero desde luego en la actualidad toda la programación se basa o está
integrado por clases, otra cosa es el código que tengamos que escribir nosotros. Eso es otra historia. Pero ya lo iremos aprendiendo con el
tiempo.
En principio una clase sería práctico crearla cuando deseamos crear lo que anteriormente definíamos como una librería, para la gestión de
datos, para cualquier cosa en realidad.
También si deseamos crear una agrupación de código relacionado entre si, y que el fuente quede protegido. Hay que tener en cuenta que
las empresas de programación de esta forma pueden tener objetos desarrollados que se reutilizan de una a otra aplicación, y que son o están
depurados.
Una de las ventajas de las clases es que en contra de las librerías, o en algunos casos de las librerías, según el lenguaje, el código no es
accesible por el usuario de la misma.
Hay más casos en los que se puede definir una clase, como son las denominadas interface, o las equivalente a los tipos, que por
cuestiones de rendimiento así se aconseja. Pero no es este el motivo principal del tema, por lo que solo dejar constancia de dicha situación para
que quien lo desee pueda buscar ampliar dichos contenidos.
23.4. Como escribir una clase.
Cuando usamos una clase, lo que se hace es siempre seguir los siguientes pasos.
109
Por lo tanto los datos que nos interese controlar, o las acciones a ejecutar en esa fase deben estar
escritas en ese método.
Asignar las características a las propiedades de la clase.
Pero puede que no se le asigne ninguna propiedad de las existentes.
Utilizar la clase con los objetos que se declaren de la misma.
Utilizar los métodos de la clase.
Finalizar el uso del objeto.
Se ejecuta el método destructor de la clase, Finalize, y se liberan recursos.
Clase Ejemplo
Crear Variable como String = "Variable inicializada"
Crear VariablePropiedad como String = "Propiedad inicializada"
Private Constructor()
// esto impide la creación de un objeto .
Fin procedimiento
Private Constructor()
Fin procedimiento
Publico Constructor()
// El primer paso es llamar al constructor de la clase origen, y
// proporcionar un valor de inicialización.
ClaseBase.Constructor("Valor desde la clase heredera")
110
Fin procedimiento
Fin de Clase
Ya se ha cubierto una primera etapa que es la de controlar la creación de un objeto de nuestra clase de forma incontrolada.
Las variables normales, les podemos dar el tratamiento que habitualmente le damos a las variables de cualquier programa, pero las que
se han de emparejar con las propiedades, o que simplemente son públicas, lo lógico es inicializarlas al valor que nos interese, con el fin de que la
clase a la hora de inicializarse no obligue a que sea imprescindible asignar valor a las propiedades, si no que estas ya dispongan de un valor que
pueda ser operativo, y solo sea necesario ajustar para personalizar el objeto.
De esta forma con un mínimo de código, el objeto que se deriva de nuestra clase se convierte en operativo.
Pág. 23.1
111
Public Class ClaseEjemplo
Public Publica As Integer
End Class
Esta sería la forma de declarar la variable en la clase.
Como podemos ver no hay ningún código de control.
Module Module1
Sub Main()
Dim Objeto As New ClaseEjemplo
Objeto.Publica = 25
End Sub
End Module
Esta es la forma de utilización en el programa.
Se puede asignar cualquier valor sin ninguna restricción.
Cuando menos peligroso, evidentemente cuando lo que represente sean valores que pueden perjudicar el buen funcionamiento de la
clase, del objeto.
Pág. 23.2
Unidad 23. Cómo programar una clase (III)
23.8. Desarrollar los métodos de la clase.
Está claro que éste no es un orden inamovible, y que se irán creando los métodos y las propiedades a medida que se vaya desarrollando
la clase.
En los métodos nos vamos a encontrar que necesitarán a su vez de datos para su ejecución.
Que criterio seguir a la hora de asignar los datos de los métodos, usar una propiedad o un argumento en la línea de llamada al método,
veamos.
Un criterio puede ser el siguiente.
Cuando se usa una propiedad y se valida la asignación del dato, no se está ejecutando ningún código que podamos decir que sea
ejecutivo, que realiza alguna acción, solo se controla su dato y ya está.
Cuando se asigna un valor en la llamada a un método, ese método va a ejecutar una acción, por lo tanto, ya podemos tener un criterio.
Así que en el método solo tenemos que recabar aquella información que sea imprescindible para la ejecución del mismo.
Otro apartado a la hora de crear los métodos, es si estos han de ser procedimientos a funciones.
Un criterio a seguir es que si el método solo es una acción a ejecutar y no devuelve nada, podemos crear un procedimiento, pero si ese
método como consecuencia de su ejecución ha de devolver un dato, entonces debemos crear una función.
112
Las propiedades de esta clase proporcionan información sobre la cantidad de memoria total disponible en el sistema y la categoría de
edad, o generación, de la memoria asignada a un objeto.
23.10. Secuencia de uso de un objeto.
El objeto creado como instancia de una clase, cuando se libera ejecuta el método Finalizar de la clase.
Ese método se ejecuta siempre de forma predeterminada antes de liberar el objeto, y suele existir en cada lenguaje.
Por lo tanto todas aquellas acciones que sean imprescindibles realizar antes de que se destruya el objeto se deben realizar en ese
método.
Por ejemplo realizar el cierre de archivos, o de una conexión con base de datos.
23.11. Recuperar los recursos utilizados que están libres.
Normalmente existe una clase para la gestión de los recursos liberados en memoria sin utilizarse, y que dispone de métodos para la
gestión y recuperación de dichos recursos.
El recolector de elementos no utilizados realiza un seguimiento de los objetos asignados en la memoria administrada, y los reclama. De
forma periódica, el recolector de elementos no utilizados reclama la memoria asignada a los objetos para los que no existen referencias válidas.
La recolección de elementos no utilizados se produce de forma automática, cuando una solicitud de memoria no puede satisfacerse
utilizando la memoria libre que queda disponible.
La recolección de elementos no utilizados puede constas de los siguientes pasos:
El recolector de elementos no utilizados busca los objetos administrados a los que se hace referencia en el
código administrado.
El recolector de elementos no utilizados intenta finalizar los objetos a los que no se hace referencia.
El recolector de elementos no utilizados libera los objetos a los que no se hace referencia y reclama la
memoria utilizada por estos objetos.
Durante la recolección de elementos no utilizados, el recolector no liberará un objeto si encuentra una o varias referencias al mismo en el
código administrado.
Pág. 23.3
Unidad 24. Cómo programar una clase en VB (I)
24.1. Objetivos del tema.
Vista la introducción a este tema, vamos a ver la parte propia de cada lenguaje.
24.2. Introducción.
Programar es un tema muy personal, de estilo, de gustos y más si hablamos de un elemento como una clase que luego se integra en un
programa, donde los matices son muy importantes y cada cual los ve o aprecia de forma distinta.
No vamos a entrar en todas las posibilidades de las clases, sino se convertiría en un apartado muy extenso, y la pretensión es la de sentar
un punto de partida, para que a partir de ahí se siga progresando.
Hay que tener presente que en todo desarrollo de código hay que tener siempre un tratamiento de errores, al cual aun no hemos llegado y
que aquí no se contempla, pero de lo cual hay que dejar constancia.
24.3. Declarar un objeto de esa clase.
En este punto es cuando se instancia el objeto, y en el que se queda configurado con los valores por defecto que nosotros hayamos
asignado a las variables internas, y a las propiedades.
113
Private Sub New()
End Sub
Por lo tanto ya se ha cubierto una primera etapa que es la de controlar la creación de un objeto de nuestra clase de forma incontrolada.
El siguiente paso es la declaración de las variables.
Pág. 24.1
Asignar los valores de sus propiedades en el momento de inicializar el objeto equivale a recibir sus valores en el constructor.
114
Asignar a posteriori implica recibir valores en la línea de argumentos de un método.
El segundo, y sobre todo si se consumen muchos recursos del sistema, es utilizar la instrucción Using, End Using.
Con esta instrucción se garantiza la recuperación de los recursos al finalizar el uso de los objetos.
Objeto = Nothing
También podemos preguntar por
El ejemplo que sigue expresa de forma bastante efectiva la secuencia y el funcionamiento de los métodos Dispose y Finalize, para su
correcto funcionamiento hay que poner en las propiedades de proyecto como elemento inicial el Sub Main.
116
Este es el código principal del ejemplo, donde se crean los objetos para la prueba.
Module Principal
Sub Main()
' Demostración de como Using llama al método dispose
Using Objeto As New ClaseHeredera(6)
MsgBox("El valor de la propiedad después de la “ & _
“inicialización es " & Objeto.Propiedad & ".")
End Using
Module ClaseDos
Public Class ClaseBase
Sub New()
MsgBox("ClaseBase inicializándose con el método New.")
End Sub
ValorPropiedad = Valor
End Sub
117
' No añadir Overridable a éste método.
Public Overloads Sub Dispose() Implements IDisposable.Dispose
MsgBox("Clase heredera haciendo shuttdown con el método Dispose.")
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
El recolector de elementos no utilizados busca los objetos administrados a los que se hace referencia en el
código administrado.
El recolector de elementos no utilizados intenta finalizar los objetos a los que no se hace referencia.
El recolector de elementos no utilizados libera los objetos a los que no se hace referencia y reclama la
memoria utilizada por estos objetos.
Durante la recolección de elementos no utilizados, el recolector no liberará un objeto si encuentra una o varias referencias al mismo en el
código administrado.
El recolector de elementos no utilizados no reconoce, sin embargo, las referencias a objetos desde el código no administrado y puede
liberar objetos que se estén utilizando exclusivamente en código no administrado, a menos que se le impida hacerlo de forma explícita.
Pág. 24.4
118
Un programa puede construirse, crearse perfectamente sin la utilización de clases, aunque en realidad lo que estamos utilizando de forma
continua, tanto en VB como en otros lenguajes, son todo objetos que derivan de sus correspondientes clases, pero me refiero a la posibilidad de
crear nuestro propio programa sin incorporar nuevas clases con nuestro código.
25.3. Cuando utilizar las clases.
Las librerías eran una colección de funciones y procedimientos que ya teníamos escritos y que se iban reutilizando y enriqueciendo de
una a otra aplicación.
Esto permitía que una aplicación se creara de forma más rápida y también con más comodidad, es más sencillo reutilizar código que
tenerlo que diseñar, escribir y probar.
Las librerías se incorporaban posteriormente cuando se creaba el ejecutable del programa, y el sistema de incorporación cambiaba en
función del lenguaje utilizado.
¿Que nos aportan las clases?, en principio en cuanto a lo principal, lo mismo, es decir podemos tener una colección de clases que nos
resolverán determinadas tareas de programación y solo deberemos utilizarlas, estando ya escritas y probadas.
Pero además el código está protegido, cosa que anteriormente en las librerías, en algunos lenguajes, no era así, el código no es accesible
por las personas que están utilizando la clase.
Además hemos de añadirle una serie de ventajas, que aunque antes también disponíamos, ahora lo llamamos herencia y sobrecarga,
etc..., pero era más complejo, ahora es más sencillo y útil su utilización.
Disponemos de la sobrecarga, que es una manera muy cómoda de disponer de distintas formas de realizar la misma tarea, lo que permite
facilitar la gestión del código del programa y facilitar su uso por terceros.
La herencia es otra historia, hay opiniones para todos los gustos, y hay que reconocer que aunque filosóficamente es muy claro y práctico,
en la realidad en muchos casos acaba no usándose, pero eso ya es una historia individual.
Clase Dato
Inicio
Nombre como String
Codigo como Entero
Siguiente como Dato
Anterior como Dato
Constructor ()
Inicio
Final
Final clase
Este podría ser un sencillo ejemplo de la mencionada estructura.
Siguiente y anterior son un enlace a un elemento de una lista compuesta por sucesivos elementos del tipo Dato, u objetos de la clase
Dato.
De esta forma podemos utilizar estos enlaces, punteros, para recorrer una colección de elementos hasta llegar a uno en el que el enlace
siguiente o anterior, este vacío.
Esta clase no tiene sentido compilarla, no alberga código escrito, es una estructura de datos.
25.6. Como incluir una clase en nuestra aplicación.
Si el código de la clase es nuestro, podemos utilizar el fuente de la clase directamente en nuestra aplicación sin necesidad de obtener una
versión compilada previamente, y cuando nuestra aplicación se compile, o publique, se integrará todo en un único archivo.
La otra posibilidad es la de, - independientemente de que sea nuestra o no -, incluirla compilada mediante el sistema que el lenguaje que
estemos utilizando nos permita.
En ese caso si la clase es nuestra hay que obtener una librería dll, o un archivo, por el medio que corresponda según el lenguaje
empleado.
Las clases las podemos tener en un único proyecto, o podemos tener un proyecto para cada clase, eso dependerá de nuestras
necesidades.
Pág. 25.1
Unidad 26. Utilizar clases en VB (I)
26.1. Objetivos del tema.
Vamos a ver como compilar una clase y obtener un archivo que se pueda utilizar desde un proyecto, sin poder acceder al código del
mismo, en VB una dll.
26.2. Introducción.
La creación de una clase tiene como uno de sus fines la utilización del código de la misma de forma que no pueda ser accesible por el
usuario.
Para ello es necesario obtener una versión compilada, que sea posible importar o referenciar en dicho proyecto.
26.3. Compilar la clase, primer paso.
119
El primer paso es disponer de la clase evidentemente, pero una vez que ya disponemos de ella, y sobre todo la hemos probado
adecuadamente, hay que compilarla.
Para ello, como posiblemente la habremos probado en un tipo de proyecto normal, de consola o de Windows, creamos un proyecto nuevo
del tipo Biblioteca de clases, en el ejemplo la hemos llamado Tema_24.
Después podemos copiar el archivo que contiene la clase en el directorio del nuevo proyecto, en este caso hemos utilizado la clase del
tema dieciséis,
C:\Apuntes\Tema_16\Tema_16
Y la hemos copiado en
C:\Apuntes\Tema_24\Tema_24
120
Pulsamos aceptar y en la ventana de nuestro proyecto podemos escribir.
Y podemos ver como tenemos disponibles todos los métodos del tema dieciséis en nuestro programa.
Podemos optar por ésta otra opción también.
Imports Tema_24
Module Module1
Sub Main()
Dim Objeto As Ejercicios = New Ejercicios
End Sub
End Module
Importamos el NameSpace, que es así como se denomina al Tema_24, y de esa forma después ya podemos utilizar la clase Ejercicios,
que es la que creamos en el proyecto Tema_24.
Imports Tema_24
La ventaja es que de esa forma puede haber más de una clase en el proyecto, y utilizar la que nos interese.
El primer paso es disponer de la clase, para ello, como se ha indicado en el tema, generamos un proyecto de Biblioteca de clases.
Incluimos todos los fuentes del tema dieciséis, copiando y pegando o bien, copiando el archivo Ejercicios en el directorio del proyecto.
121
Public Class Ejercicios
Public Sub New()
End Sub
122
Dim Fec As Boolean
Select Case M
Case 1, 3, 5, 7, 8, 10, 12
Fec = D > 0 And D < 32
Case 4, 6, 9, 11
Fec = D > 0 And D < 31
Case 2
Select Case A Mod 100 = 0
Case True
Fec = (D > 0 And D < 29) Or (D = 29 And A Mod 400 = 0)
Case Else
Fec = (D > 0 And D < 29) Or (D = 29 And A Mod 4 = 0)
End Select
End Select
Fecha = Fec
End Function
En la opción Proyecto Agregar referencia Examinar, vamos al directorio del proyecto Tema_26\bin\release en ese directorio y añadimos a
nuestro proyecto el archivo Tema_26.dll.
123
A continuación después de haber aceptado el archivo de la clase, en la primera línea de nuestro módulo principal
Como podemos ver en la imagen todos los métodos de la clase están disponibles.
Ahora solo queda utilizarlos.
2. Repetir unos cuantos ejercicios del tema dieciséis, pero ahora usando la clase compilada.
1. Hallar el área y la longitud de una circunferencia, solicitando el radio de la misma R . Area = PI * R al cuadrado,
Longitud = 2 * PI * R .
Imports Tema_26
Module Module1
Sub Main()
Dim Objeto As New Tema_26.Ejercicios
Dim Radio As Double
Console.ReadKey()
124
End Sub
End Module
3. A partir de los siguientes valores de moneda extranjera, crear una función que a partir de un importe en pesetas
devuelva su equivalente en la moneda que se indique.
1 Franco francés 25,2400 25,3920
1 Lira 0,0859 0,0864
1 Libra esterlina 245,5560 247,0340
1 Dólar americano 150,2280 151,1320
1 Marco alemán 84,6480 85,1570
1 Franco suizo 101,7550 102,3670
1 Florín holandés 5,1170 75,5690
1 Escudo portugués 0,8262 0,8312
Imports Tema_26
Module Module1
Sub Main()
Dim Objeto As New Tema_26.Ejercicios
Dim Pesetas As Integer
Dim Moneda As Char
Y la gestión de los datos cuando estos se almacenan en un soporte se realiza mediante el uso de archivos.
La información en un programa puede ser de muchos tipos y desde distintos puntos de vista.
La información, los datos, se utilizan en un programa en variables, y ya hemos visto anteriormente que las variables pueden ser
Numéricos.
Alfanuméricos.
Las estructuras de datos a utilizar en la gestión de los datos pueden ser de tipo
Estático, no pueden crecer o disminuir de tamaño.
Dinámico, pueden aumentar o disminuir de tamaño.
Las estructuras que se utilizan en la grabación de los datos en un soporte pueden ser
Archivos direccionables, acceso aleatorio o indexado.
Archivos no direccionables, acceso secuencial.
Seguro que aun podríamos buscar más clasificaciones o formas de agrupar información, pero con esto es
suficiente.
Como lo que aquí nos interesa es la parte útil para hacer un programa, nos limitaremos a:
Tipos de datos.
Tipos de usuario.
Estructuras de datos.
Almacenamiento de datos.
Pág. 27.1
En programación a la hora de definir un dato hay que indicar de que tipo es el mismo, hasta ahora hemos visto que los tipos básicos son
dos numéricos y alfanuméricos, con las variaciones que en cada uno de ellos hay en cada lenguaje de programación.
Hay un tipo de datos que se denomina de usuario, que no es otra cosa que una composición de datos compuesta por tipos de datos
primitivos o del lenguaje o por otros tipos de datos de usuario.
Tipo Monitores
Marca Como Texto
Pulgadas Como Entero
Resolución Como Texto
Velocidad Como Texto
Fin de tipo
Que significa
Tipo Monitores
El nombre del tipo o estructura.
Marca Como Texto
Pulgadas Como Entero
Resolución Como Texto
Velocidad Como Texto
Cada uno de los datos que la componen.
Fin de tipo
El final de la misma.
Crear Monitor Como Monitores
Y esta línea sería la creación de una variable usando el tipo predefinidio.
27.5. Ventajas.
126
Con los tipos de usuario después podemos declarar variables de ese tipo y sacar partido a las mismas.
De esta forma en realidad estamos consiguiendo que en una variable dispongamos de más de un dato.
Conseguimos agrupar datos que estén relacionados entre si, en un único nombre, y permite manejar los datos de una forma más cómoda.
Podemos declarar lo siguiente:
Fecha_Nacimiento del tipo Fecha.
Fecha_Factura del tipo Fecha.
Fecha_Actual del tipo Fecha.
Todas son del tipo Fecha, y en cada una podremos acceder al dato día, mes o año de forma individual.
Además podremos ejecutar la siguiente instrucción
Fecha_Act = Fecha_Fac
Fecha actual recibiría simultáneamente los tres datos de fecha factura en una sola línea de programa, sería el equivalente a escribir:
Dia_Act = Dia_Fac
Mes_Act = Mes_Fac
Año_Act = Año_Fac
Aunque para el ejemplo parezca poco importante, hay que pensar que igual que se crea con tres campos en este caso, pero en realidad
puede tener muchos más y sin embargo seguir siendo una sola línea de código, y eso es cómodo, seguro y facilita la comprensión del programa.
Pág. 27.2
Tipo Parrafo
Descripción del tipo Alfanumérico
Fuente del tipo Texto
Fin del tipo
Que nos proporciona la misma solución que antes, pero nos permite ilustrar que los tipos pueden estar anidados
unos dentro de otros y crear estructuras complejas, cuando interese claro.
Pág. 27.3
Unidad 27. Utilizar y definir datos (IV)
27.7. ¿Dónde utilizar los tipos de usuario.?
Evidentemente una vez que conocemos sus características o prestaciones, en cualquier sitio que nos venga bien.
Donde más utilidad se le ha sacado siempre es en el manejo de archivos, ya que se suele crear en muchas ocasiones un tipo de usuario
que coincida con el diseño de un archivo, se verán más adelante, de tal forma que permite manejar muchos datos de una forma muy cómoda y
rápida.
Tipo Persona
Código del tipo Entero.
Nombre del tipo alfanumérico.
Población del tipo alfanumérico.
Código postal del tipo numérico.
DNI del tipo numérico.
Teléfono del tipo numérico.
Fin de tipo
Pero claro, no tiene que ser para ese uso exclusivo, puede dedicarse a cualquier necesidad que nos pueda surgir.
27.8. Conclusiones.
Los datos son imprescindibles en la creación de un programa.
Los datos los utilizamos en una variable.
Las variables pueden ser de tipos estándar, o de tipos de usuario.
Los tipos de usuario permiten agrupar datos homogéneos o relacionados en una misma variable, bajo un mismo nombre, eso permite que
se puedan crear programas más cómodos de leer y que manejen volúmenes de datos elevados con mucha mayor comodidad.
27.9. Ejercicios propuestos.
1. Defina un tipo de usuario que le permita utilizar todos los datos relacionados con las características de un monitor.
2. Defina varios tipos de usuario de tal forma que le permita crear una estructura de datos anidada, es decir que al
menos uno de los tipos de usuario esté en el interior de otro tipo o estructura.
27.10. Solución a los ejercicios propuestos.
1. Defina un tipo de usuario que le permita utilizar todos los datos relacionados con las características de un monitor.
Tipo Monitor
Marca Como Texto
Pulgadas Como Entero
Resolución Como Texto
Velocidad Como Texto
128
Fin de tipo
2. Defina varios tipos de usuario de tal forma que le permita crear una estructura de datos anidada, es decir que al
menos uno de los tipos de usuario esté en el interior de otro tipo o estructura.
Tipo Mueble
Color Como Texto
Construido Como Texto Madera, Aluminio, Hierro
Uso Como Texto Interior, Exterior
Fabricante Como Texto Nombre
Fin de tipo
Tipo Silla
Caracteristicas Como Mueble
Precio Como Real
Cantidad Como Real
Fin de tipo
Tipo Cama
Caracteristicas Como Mueble
Medidas Como Texto
Precio Como Real
Cantidad Como Real
Fin de Tipo
Tipo Mueble
Color Como Texto
Construido Como Texto Madera, Aluminio, Hierro
Uso Como Texto Interior, Exterior
Fabricante Como Texto Nombre
Fin de tipo
Tipo Silla
Caracteristicas Como Mueble
Precio Como Real
Cantidad Como Real
Fin de tipo
Tipo Cama
Caracteristicas Como Mueble
Medidas Como Texto
Precio Como Real
Cantidad Como Real
129
Fin de Tipo
28.4. Declaración.
Los datos a lo largo de un programa pueden cambiar o permanecer inalterables.
Si cambian, o puede ser que cambien, la utilización del mismo se hará mediante el uso de variables.
Si el dato va permanecer inalterable a lo largo del programa, podemos utilizar una constante.
Una vez declarada una constante, por definición no se le puede asignar otro valor. Por ello, cuando se declara una constante debe ser
iniciada con un valor.
Las variables se pueden declarar en cualquier bloque de código, dentro de procedimientos o funciones.
La declaración es siempre indicando primero el nombre de la variable y después el tipo.
Dim Ruta As String
Podrá o no inicializarse.
Dim Ruta As String = “C:\Archivo.Ext”
Delante del tipo de la variable, también se puede indicar el ámbito de disponibilidad de la misma, indicando delante public o private.
La regla general es que el tipo convertido debe tener como mínimo un tamaño igual al tipo original.
28.6. Nombres, estructuras.
Con la riqueza del castellano, no tiene sentido complicarse la vida a la hora de asignar el nombre a una variable, por lo tanto, no
utilicemos las palabras propias del lenguaje, y no se pueden utilizar los símbolos especiales como los operadores, etc.
Palabras cortas y si deseamos dos las unimos con el guión bajo.
Dim precio_venta_publico As Double = 0
Pero mejor ...
Dim pre_vta_pub As Double = 0
131
Dim Marca As String
Dim Pulgadas As Integer
Dim Resolución As String
Dim Velocidad As String
End Structure
Que significa
Structure Monitor
El nombre de la estructura.
Dim Marca As String
Dim Pulgadas As Integer
Dim Resolución As String
Dim Velocidad As String
Cada uno de los datos que la componen.
End Structure
Y el final de la misma.
Su ubicación aunque puede estar en muchos sitios dentro de un proyecto, conviene que por cuestiones de organización las declaremos
en un modulo exclusivo para ello, y estará disponible para toda la aplicación, proyecto.
Después tendremos alguna estructura que será muy personal de un único programa, entonces se declara en el mencionado programa.
Pág. 28.2
Structure Silla
Dim Caracteristicas As Mueble
Dim Precio As Double
Dim Cantidad As Double
End Structure
En el ejemplo podemos observar como la estructura Mueble se utiliza en la definición de un dato llamado “Caracteristicas” en la estructura
“Silla”.
Otra forma de utilizarlos es creando estructuras de datos más amplias mediante el uso de arrays, en próximo tema los veremos, pero
dejamos aquí un avance.
Structure Asientos
Dim Asiento() As String
End Structure
Structure Sesiones
Dim Filas() As Asientos
End Structure
Structure Cine
Dim Fecha As String
Dim Sesion() As Sesiones
End Structure
Esta estructura podría ¿¿¿servir ??? para declarar algo parecido a un cine, teatro, etc., acabando con algo así como
Dim V() As Cine ' estructura del lugar
Que significa declarar un array, sin tamaño, del tipo, estructura Cine.
Después diremos que V tiene, por ejemplo, treinta elementos, un mes en pocas palabras.
28.11. Ventajas.
No tiene sentido volver a comentar lo mismo, es un tema innegable, y se vienen utilizando desde hace mucho tiempo, y más a medida que
los sistemas han ido mejorando en prestaciones y capacidades.
Aunque no sea muy real, solo hay que remitirse al ejemplo del cine, el uso de la estructura anterior queda dentro de un programa en algo
parecido a lo siguiente:
132
V(Dia).Fecha = FechaReserva
V(Dia).Sesion(Sesion).Filas(Fila).Asiento(Asiento) = Nombre
En la que previamente a las variables
Día un día dentro del margen de reservas.
FechaReserva le habremos asignado una fecha
Sesión una de las posibles sesiones de le fecha anterior.
Fila una fila del teatro, cine.
Asiento un asiento disponible
V(Dia).Sesion(Sesion).Filas(Fila).Asiento(Asiento) el nombre de unapersona.
Por lo que queda claro la facilidad de comprensión del ejemplo y lo práctico que puede ser el uso adecuado de la estructura.
La alternativa a esto podría ser
V(Dia,Sesion,Fila,Asiento) = Nombre
que implica una estructura más compleja de utilizar, no imposible, pero si es más sencilla la anterior.
Structure Silla
Dim Caracteristicas As Mueble
Dim Precio As Double
Dim Cantidad As Double
End Structure
Structure Cama
Dim Caracteristicas As Mueble
Dim Medidas As String
Dim Precio As Double
Dim Cantidad As Double
End Structure
133
Normalmente cuando en un programa tenemos que crear una distinción entre varios tipos de datos, optamos por asignar valores
numéricos desde cero o uno hasta el último de los tipos de datos que vayamos a utilizar.
El inconveniente es que hay que estar pendiente continuamente, amen de la documentación del mismo, de su correcta utilización.
Con las enumeraciones ese problema desaparece.
29.3. ¿Qué son?
Como hemos comentado en el programa optamos habitualmente por asignar valores desde cero hasta un valor determinado para separar
cada uno de los posibles tipos de datos, o circunstancias que se nos puedan presentar.
Una enumeración es exactamente lo mismo, pero con nombre, en lugar de lo visto anteriormente, haríamos lo siguiente.
Enumeración Cursos
Primero = 1
Segundo = 2
Tercero = 3
Fin de enumeración
Crear Curso del tipo Cursos
Pág. 29.1
Enum Monedas
Euro
Dolar
Libra
Yen
End Enum
En ambos casos la sintaxis es correcta, la diferencia es que en el primer caso forzamos los valores, Euro sería uno, y en el segundo sería
cero, que es el valor que VB le da por defecto.
Euro = 1
Dolar = 2
Libra = 3
Yen = 4
134
Es el contenido.
End Enum
Es el final de la descripción de los elementos de la enumeración.
Una de las utilizaciones se refleja en la imagen:
Podemos observar como se introduce un dato en la inicialización del objeto, y luego al llegar al campo de la enumeración,
automáticamente aparece el contenido de la enumeración, ya que el dato que ahí se espera es del tipo Monedas, y solo hay que elegir una de las
opciones disponibles, que además estamos viendo.
135
For each variable in Colección
La variable en este caso deberá ser del tipo String
Dim item As String
Una vez que disponemos de todos los elementos, ya podemos ejecutar el bucle, primero el de código.
' Se pasa al vector los códigos
X = 0
For Each item In Valores
V(X).Codigo = CInt(item)
X = X + 1
Next
Y otro bucle para los nombres, el orden de ejecución de los bucles es indistinto.
' Se pasa al vector los nombres
X = 0
For Each item In Nombres
V(X).Denom = item
X = X + 1
Next
Y ya disponemos del contenido de la enumeración en un vector, para el uso que deseemos.
30.5. Conclusiones.
El uso de una enumeración se convierte en imprescindible si se desea un programa ordenado y claro.
No tiene sentido el uso de valores enteros en un programa, cuando se pueden sustituir por descripciones, que siempre reducirá el número
de posibles errores.
2. Declarar una enumeración para los posibles valores de seguridad en los accesos que pueda tener una persona
las distintas zonas de un complejo con varios niveles de seguridad.
Enum Seguridad
Prohibido = 0
Normal = 1
Restringidas = 2
Total = 3
End Enum
4. Realizar la carga de los valores de una de las enumeraciones anteriores y visualizarlas por pantalla.
Module Ejemplos
Enum Seguridad
Prohibido = 0
Normal = 1
Restringida = 2
Total = 3
End Enum
Structure Enumeracion
Dim Codigo As Integer
Dim Denom As String
End Structure
136
Sub Main()
Dim X As Integer
Dim item As String
Dim Valores As Array
Dim Nombres As Array
137
Eso significa que las colecciones disponen de un índice por el que acceder a un elemento de la misma, si se desea utilizar, y que
disponen de un método que nos indicará cual es el número de elementos.
Los elementos de una colección se añaden, pero no se colocan en un puesto en concreto salvo que la adición se realice en orden.
En un vector definimos el número de elementos y después podemos colocar los datos en la posición que deseemos
cuando queramos, en una colección eso no es posible.
Las colecciones pueden empezar en la posición cero o uno, dependerá del lenguaje, e incluso dentro del mismo
lenguaje nos podemos encontrar con los dos tipos de inicialización, cero y uno.
Además se dispone de un string identificador que nos permite referirnos a un elemento de la colección sin recordar o
saber su índice.
31.5. Operaciones con una colección.
Las operaciones base, métodos de una colección suelen ser los imprescindibles para su gestión.
Añadir un elemento.
Quitar un elemento.
Limpiar, vaciar la colección.
Comprobar si existe un elemento determinado.
Recorrido de la colección.
Acceder, extraer un elemento de la colección.
Devolver cuentos elementos hay en la colección.
31.6. Tipos de colección.
Asimilado el concepto de colección, conviene aclarar que los tipos de colecciones existentes va en función de lo que se hace normalmente
con el manejo de los datos habitualmente.
Y el acceso a dichas colecciones, y sus métodos, dependerá del tipo de estructura a la cual esta dirigida la colección.
Pág. 31.1
Unidad 32. Colecciones en VB (I)
32.1. Objetivos del tema.
Explicar las características de las colecciones.
32.2. Introducción.
Podríamos definirlas como una enumeración, a la que se le pueden añadir o quitar elementos.
Podríamos definirlas como un array que en lugar de ser estático en el número de elementos, permite la adición y la eliminación de
elementos, o sea que es dinámico, y que además esos elementos pueden ser objetos.
Desde el momento en que podemos declarar un array del tipo de un objeto determinado, un array es muy similar a una colección.
En VB las clases que gestionan colecciones son
Array
System.Collections
Los métodos para una colección son los necesarios para la gestión de la misma, y
dado que no disponemos de un índice propiamente dicho, la gestión se basa en su recorrido,
adición y eliminación.
Las colecciones disponen de un Enumerador que es un objeto que recorre en iteración su colección asociada.
La instrucción for each utiliza el enumerador y oculta la complejidad que supone su uso.
Todas las colecciones pueden copiarse en una matriz usando el método CopyTo, sin embargo, el orden de los elementos de la nueva
matriz se basará en la secuencia en la que los devuelve el enumerador.
La matriz resultante siempre es unidimensional, vector, y su límite inferior es cero.
Algunas clases Collections tienen capacidades de ordenación y la mayor parte están indexadas.
La administración de la memoria se controla automáticamente y la capacidad de una colección se expande si es necesario.
Colecciones utilizadas normalmente. Son las variaciones habituales de las colecciones de datos, como tablas hash, colas, pilas,
diccionarios y listas. Las colecciones que su usan habitualmente tienen versiones
genéricas y no genéricas.
Colecciones de bits. Se trata de colecciones cuyos elementos son indicadores de bits. Se comportan de forma ligeramente
diferente de las demás.
Colecciones especializadas. Se trata de colecciones con fines muy específicos, normalmente para tratar un tipo concreto de
elemento, como StringDictionary.
138
Snack, Pilas
Queue, Colas
LinkedList
Pero el uso de una colección no se limita al uso de algo tan sencillo como un string.
Podemos utilizar objetos en una colección.
Podemos hacer éste otro uso en una colección:
Item.Nombre = "Silla"
Coleccion.Add(Item)
139
Sub Main()
Dim Coleccion As New System.Collections.Generic.List(Of Datos)
Dim Item As New Datos
Item.Nombre = "Silla”
Coleccion.Add(Item)
Dim x As Integer = 0
While x < Coleccion.Count
Console.WriteLine(Coleccion.Item(x).Nombre)
x = x + 1
End While
Console.ReadLine()
End Sub
Y en este caso utilizando el bucle del tipo For each, que suele ser válido para casi todas.
Dim Dato As Datos
For Each Dato In Coleccion
Console.WriteLine(Dato.Nombre)
Next
El primer ejemplo es fácil de entender, hemos creado un bucle en el que progresamos desde x igual a cero hasta el número de elementos
que tiene la colección.
El segundo ejemplo se basa en que el bucle For each es un bucle especializado en esta tarea y solo hay que darle el tipo de dato a leer
en la colección a la que pertenece.
En las colecciones donde se utiliza clave y valor, el recorrido es de esta forma.
Dim Coleccion As New System.Collections.Generic.SortedList(Of Integer,
String)
Coleccion.Add(1, "Silla")
Coleccion.Add(2, "Mesa")
Coleccion.Add(3, "Puerta")
140
Sort Clasifica la colección.
ToArray Copia la colección en un array.
2 Adición, add.
Hemos visto como se usa el método add,
Coleccion.Add(Item)
Pero hay que tener presente que hay varios tipos de colecciones, y el método Add puede cambiar según el tipo de la misma, he aquí un
ejemplo.
Dim Coleccion As New System.Collections.SortedList
Coleccion.Add(1, "Silla")
Coleccion.Add(2, "Mesa")
Coleccion.Add(3, "Puerta")
Console.WriteLine(Coleccion.ContainsValue("Silla"))
O bien esta otra.
Dim Coleccion As New System.Collections.Generic.SortedList(Of String,
String)
Coleccion.Add("1", "Silla")
Coleccion.Add("Dos", "Mesa")
Coleccion.Add("3", "Puerta")
En la que podríamos haber declarado también
Dim Coleccion As New System.Collections.Generic.SortedList(Of Integer,
String)
Para el primero de los ejemplos.
Coleccion.Add(2, "Mesa")
Las dos colecciones no son iguales.
Dim Coleccion As New System.Collections.SortedList
Dim Coleccion As New System.Collections.Generic.SortedList(Of Integer,
String)
Pág. 32.2
Unidad 32. Colecciones en VB (III)
3 Borrado, clear, remove.
Para borrar disponemos de los métodos Clear, Remove, RemoveAt, RemoveRange.
Coleccion.RemoveRange(PosiciónInicial, Cuantos)
Borra el primer elemento que sea igual al objeto de referencia.
Item.Nombre = "Silla"
Coleccion.Remove(Item)
También podemos borrar todo el contenido de la colección utilizando el método clear.
Colección.Clear()
La sintaxis es
Posicion = Coleccion.IndexOf(Item)
Console.WriteLine(Coleccion.IndexOf(Item))
Para la siguiente colección.
Sub Main()
Console.WriteLine("Carga colección de objetos.")
Dim Coleccion As New System.Collections.Generic.List(Of Datos)
Dim Item As New Datos
141
Item.Nombre = "Silla"
Coleccion.Add(Item)
Dim x As Integer
While x < Coleccion.Count
Console.WriteLine(Coleccion.Item(x).Nombre)
x = x + 1
End While
End Sub
Un ejemplo :
Item = Coleccion.Item(0)
Console.WriteLine(Coleccion.IndexOf(Item))
Posicion = Coleccion.IndexOf(Item)
Console.WriteLine(Posicion)
La salida del ejemplo es cero en los dos casos.
Como peculiaridad hay que ver el siguiente ejemplo.
Item = New Datos
Item.Nombre = "Silla"
Console.WriteLine(Coleccion.IndexOf(Item))
Siendo que el elemento “Silla” existe en la colección previamente a la declaración del nuevo Item, el resultado de la salida será –1, no
encontrado, y es que aunque el valor existe en la colección, el item declarado en si es nuevo, y no está en la misma, aunque su valor sea
coincidente, es la única explicación coherente basada en
Console.WriteLine("Despues")
Console.WriteLine("Adición de item")
Coleccion.Add(Item)
Console.WriteLine("HashCode {0} ", Item.GetHashCode)
Console.WriteLine("IndexOf {0} ", Coleccion.IndexOf(Item))
Console.WriteLine("Contains {0} ", Coleccion.Contains(Item))
Console.WriteLine("Bucle")
For Each Dato In Coleccion
Console.WriteLine("Valor {0} ", Dato.Nombre)
Console.WriteLine("HashCode {0} ", Dato.Nombre.GetHashCode)
Next
Console.ReadLine()
End Sub
End Module
Si nos fijamos en el hashcode, veremos que cuando está fuera de la colección tiene un valor distinto que cuando está dentro, que además
es el mismo que el elemento con el mismo valor.
Ambos ejemplos arrancan con la misma carga de la colección previa.
Si este ejemplo le repetimos con datos de tipos estándar, el ejemplo sin embargo no se cumple, ¿por qué?, porque si yo busco el 2, o la
“A” en una colección de enteros o de caracteres, el dos o está o no, pero porque es el número dos no es un objeto nuevo en una colección que
contiene la misma información que otro elemento de la colección.
El dos o la “A”, pertenecen a la colección de los números enteros o de caracteres, ya de antemano, y existen o no en nuestra colección.
Pág. 32.3
Unidad 32. Colecciones en VB (IV)
5 Inserción, insert, insertRange.
Inserta el elemento especificado en la posición indicada.
Item.Nombre = "Tres"
Item.Longitud = 3
Coleccion.Insert(2, Item)
En el ejemplo se inserta el item indicado en la colección en la posición dos, la posición ha de existir en la colección, y su contenido se
sustituye por el nuevo.
Coleccion.InsertRange(2, Otra)
Valor inicial de la colección Valor final de la colección después de la inserción.
1 Uno 1 Uno
2 Dos 2 Dos
3 Tres
4 Cuatro
143
es
Coleccion.CopyTo(V)
V = Coleccion.ToArray()
La utilización puede ser:
Dim V(Coleccion.Count - 1) As Datos
Coleccion.CopyTo(V)
For Each Dato In V
Console.WriteLine("Valor {0} ", Dato.Nombre)
Console.WriteLine("HashCode {0} ", Dato.Nombre.GetHashCode)
Next
Coleccion.Add(1, "Silla")
Coleccion.Add(2, "Mesa")
Coleccion.Add(3, "Puerta")
For x = 0 To Coleccion.Count - 1
Console.WriteLine(" Clave {0} Valor {1} ", _
Coleccion.GetKey(x), Coleccion.GetByIndex(x))
Next
For x = 0 To Otra.Count - 1
Console.WriteLine(" Clave {0} Valor {1} ", Otra.GetKey(x),
Otra.GetByIndex(x))
Next
144
Console.WriteLine(Coleccion.ContainsKey("2"))
Pág. 32.4
Una de ellas es la de obtener todos los elementos de una colección que cumplan un requisito, para ello utilizamos el método FindAll.
Nueva = Coleccion.FindAll(AddressOf Resultado)
12 Clasificación, Sort.
Realiza la clasificación del contenido de la colección.
Todos los tipos de colecciones no disponen de este método debido a las características de la colección en si.
Un ejemplo de su utilización.
Console.WriteLine("Sort")
145
Dim Coleccion As New System.Collections.Generic.List(Of String)
Coleccion.Add("Silla")
Coleccion.Add("Mesa")
Coleccion.Add("Armario")
Dim D As String
For Each D In Coleccion
Console.WriteLine("Valor {0} ", D)
Next
Coleccion.Sort()
32.6. Propiedades.
Capacity Obtiene o establece el número de elementos de una colección.
Count Devuelve el número de elementos de una colección
Item Obtiene o establece el elemento en la posición indicada.
3.- Crear un programa que nos permita gestionar la cola de un dentista con el siguiente contenido
Número de orden
Nombre
4.- Tenemos que almacenar los nombres de las personas que van a asistir a un evento.
Estas personas se irán identificando a medida que se van incorporando al mismo.
Necesitamos poder acceder posteriormente a sus datos, teniendo en cuenta que pueden ser
Ponentes
Invitados
Organización
Sub Main
Uno()
End Sub
2.- Introducir diez números y luego visualizarlos en orden inverso, al de entrada.
146
Module Ejercicios
Public Sub Dos()
Dim Pila As New Collections.Stack
Dim Dato As Ejercicio
Console.WriteLine("Quitado un elemento.")
Dato = CType(Pila.Pop, Ejercicio)
Console.WriteLine("código {0} nombre {1} ", Dato.Codigo, Dato.Nombre)
Sub Main
Dos()
End Sub
3.- Crear un programa que nos permita gestionar la cola de un dentista con el siguiente contenido
Número de orden
Nombre
Module Ejercicios
Private Class Ejercicio
Public Nombre As String
Public Codigo As Integer
Public Sub New()
147
End Sub
End Class
Sub Main
Tres()
End Sub
4.- Tenemos que almacenar los nombres de las personas que van a asistir a un evento.
Estas personas se irán identificando a medida que se van incorporando al mismo.
Necesitamos poder acceder posteriormente a sus datos, teniendo en cuenta que pueden ser
Ponentes
Invitados
Organización
Module Ejercicios
Private Class Ejercicio
Public Nombre As String
Public Codigo As Integer
Public Tipo as String
148
Public Sub New()
End Sub
End Class
Podemos mejorar la utilización de dicha información diseñando un tipo de usuario y agrupando los datos, pero eso solo soluciona parte
del problema.
Hemos mejorado la gestión de los datos, pero necesitamos todavía disponer de una variable para cada grupo de datos.
Podríamos crear una variable que se llamará Persona_1 y otra que se llamará Persona_2.
Pero seguimos teniendo un problema, si en lugar de tener dos personas tenemos muchas, esa solución no es operativa.
La solución pasaría por crear un array, para ceñirnos al ejemplo de dos elementos.
Ahora disponemos de una estructura que nos permite utilizar los dos datos bajo una única denominación.
150
Solo tenemos que cambiar el índice que se utiliza en el nombre del array para referirnos a uno u otro elemento del array, a uno u otro dato.
Como el vector es del tipo Personas, para hacer referencia a la información que en él se almacena será de la siguiente forma.
Juan à Clientes(1).Nombre
Pedro à Clientes(2).Nombre
C/ Bajada de la Gloria, 12 à Clientes(1).Direccion
Pág. 33.1
Unidad 33. Arrays (II)
33.4. Definición.
Los arrays pueden ser de cualquiera de los tipos disponibles en el lenguaje que estemos utilizando.
La sintaxis en el nombre de un array se compone siempre de un nombre y de un índice que es el que nos permite acceder a cada uno de
los elementos que lo componen.
Las matrices se componen por lo tanto de un número determinado de filas y columnas en las que disponemos de los datos organizados si
lo deseamos ver así en celdas.
Por lo tanto, lo que se necesita cuando se utiliza un array para acceder de forma rápida a la información es que esta esté ordenada.
33.7. Recorrido.
Un vector se puede recorrer en cualquiera de los dos sentidos.
Desde la primera a la última posición, o desde la última a la primera posición, o desde cualquier punto hasta cualquier otro, siempre y
cuando estén dentro de los límites entre 0 y n-1, siendo n el número de elementos del vector.
Una matriz se puede recorrer en sentido horizontal, si lo deseamos ver de esta forma, fila a fila, o en sentido vertical, columna a columna.
1 2 3
4 5 6 Matriz M
7 8 9
Para el ejemplo de la matriz anterior, horizontal sería.
151
Recorrido horizontal
Entero X, Y
Crear M(3,3)
X = 0
Mientras (x < 3) // Filas
Y = 0
Mientras (y < 3) // Columnas
Visualizar M(X,Y)
y = y + 1
Fin de mientras
x = x + 1
Fin de mientras
Y el resultado de la visualización sería:
Recorrido vertical
Entero X, Y
Crear M(3,3)
Y = 0
Mientras (y < 3) // Columnas
X = 0
Mientras (x < 3) // Filas
Visualizar M(X,Y)
X = X + 1
Fin de mientras
Y = Y + 1
Fin de mientras
Y el resultado de la visualización sería:
Hay que darse cuenta que la estructura es la misma, el único cambio es el uso de los contadores, que en lugar
de recorrer en el bucle interior las columnas, lo que se recorren son las filas.
152
Hasta que X=10
33.9. Visualización.
Con la visualización sucede lo mismo.
Visualización
X=0
Hacer
X=X+1
Visualizar V(X)
Hasta que X=10
Podemos implementar este bucle o cambiarlo con la versión anterior.
33.10. Búsquedas.
Otra de las acciones habituales con un array es la de realizar la búsqueda de un dato dentro de esa estructura.
En la búsqueda se pueden plantear dos situaciones distintas.
Array ordenado.
Array sin ordenar.
Cuando la búsqueda se realiza en un array que está sin ordenar no queda más remedio que realizar una búsqueda desde el primer hasta
el último elemento del vector.
Cuando está ordenado se pueden establecer distintos sistemas de búsquedas, unos más o menos eficientes.
Esta puede ser una estructura de búsqueda cuando el array no está ordenado.
Búsqueda sin ordenar
X=0
Hacer
X=X+1
Encontrado = V(X) = DatoBuscado
Hasta que X=10 Or Encontrado
Esta variable tomará el valor cierto cuando se de la situación de que V(X) sea igual a DatoBuscado.
Encontrado = V(X) = DatoBuscado
Cuando el array, vector, esté ordenado puede realizarse así.
Búsqueda vector ordenado
X=0
Hacer
X=X+1
Encontrado = V(X) = DatoBuscado
Hasta que X=10 Or Encontrado OR V(X) > DatoBuscado
De esta forma, cuando V(X) sea mayor que el elemento buscado, se finalizará la búsqueda.
Aquí si que es importante la estructura del bucle.
Si en lugar de
X=0
Hacer
X=X+1
Encontrado = V(X) = DatoBuscado
Hasta que X=10 Or Encontrado OR V(X) > DatoBuscado
Se monta
X=0
Hacer
Encontrado = V(X) = DatoBuscado
X=X+1
Hasta que X=10 Or Encontrado OR V(X) > DatoBuscado
Hay que tener en cuenta que V(X) no habrá sido todavía analizado en
Encontrado = V(X) = DatoBuscado
Pero existen otros sistemas de búsqueda más eficientes.
Uno de ellos es la búsqueda dicotómica o binaria.
El sistema de búsqueda se basa en hallar sucesivos centros en los índices del vector, hasta que se de la situación de que se encuentra o
bien los límites izquierdo y derecho se cruzan.
153
Derecha = LongitudVector – 1
// Punto medio entre los dos límites
x = Entero((Izquierda / Derecha) / 2)
DiaSemana = 7
Dia = 28
Mes = 12
Año = 2008
Pág. 33.4
Unidad 34. Arrays en VB (I)
34.1. Objetivos del tema.
Hecha la introducción a los arrays en el tema anterior, toca ahora su visión desde VB, las distintas acciones que se pueden llevar a cabo
con ellos y su utilización.
34.2. Introducción.
Los arrays, también se pueden conocer como vectores, cuando son de una sola dimensión y como matrices cuando son de más de una
dimensión.
Hasta ahora en las estructuras de datos hemos visto que utilizamos variables para almacenar cada uno de los datos que
se utilizan en un programa.
154
Pero en algunas ocasiones, en un programa es necesario guardar muchos datos que en su conjunto pueden tener el mismo nombre, por
ejemplo podríamos guardar el nombre de un mes, y podríamos llamar a la variable NombreMes, pero también tenemos que tener presente que
para asignarle el nombre, tendríamos que hacer antes un sin fin de sentencias condicionales hasta localizar la que coincida el nombre del mes
con el de la fecha.
if mes = 1 then
nombremes = ”Enero”
else if mes = 2 then
nombremes = ”Febrero”
‘ ... / ...
o bien
Select Case Mes
Case 1
nombremes = "Enero"
case 2
nombremes = "Febrero"
case 3
nombremes = "Marzo"
‘ ... / ...
End Select
Por supuesto es válido, porque funciona, pero existe una alternativa mucho más cómoda a la solución anterior, y es crear un array de
doce elementos en el que almacenamos el nombre de todos los meses y luego para hacer referencia al que nos interesa utilizamos la variable del
ejemplo anterior como índice, y quedaría algo parecido a lo siguiente.
Los arrays son direccionables, no hay que buscar un elemento para utilizarlo, si es que conoces su dirección, por el contrario, en según
que acciones son mucho más lentos que las listas.
Las listas no son direccionables, para utilizar un elemento hay que llegar a él, hay que buscarlo.
Las listas son unas estructuras dinámicas en cuanto a su tamaño, los arrays por principio no, aunque en muchos lenguajes se dispone de
instrucciones para cambiar su tamaño en tiempo de ejecución.
En cuanto a la discrepancia entre listas o arrays, es una historia absurda, lo adecuado es tener claro el funcionamiento de ambas
estructuras y utilizarlas cada una en el momento adecuado, pero para ello hay que tener un criterio abierto, o no hay que cerrarse en banda, igual
que con los lenguajes de programación.
Pero si que hay que tener claro que no tiene sentido implementar una lista con un array.
34.3. Declaración
Cuando declaramos un vector
Meses(0) = "Enero"
Meses(1) = "Febrero"
Meses(2) = "Marzo" .. / ..
Pero si se ha de cargar dentro del programa con datos, no tiene sentido.
Si se carga después desde un archivo o por teclado, si.
2 Declaración estática inicializada.
' Declaración e inicialización del vector con los
155
' nombres de los meses, de tipo string
Dim Meses() As String = {"Enero", "Febrero", "Marzo", _
"Abril", "Mayo", "Junio", _
"Julio", "Agosto", "Septiembre", _
"Octubre", "Noviembre", "Diciembre"}
3 Declaración dinámica.
Para cuando la dimensión del array depende de la ejecución del programa.
Module Ejemplo
Sub Main()
Dim Valor As String
‘ Declaración e inicialización
Dim Meses() As String = {"Enero", "Febrero", "Marzo", _
"Abril", "Mayo", "Junio", _
"Julio", "Agosto", "Septiembre", _
"Octubre", "Noviembre", "Diciembre"}
‘ Declaración dinámica
Dim OtrosMeses() As String
‘ Asignación de dimensión
ReDim Otrosmeses(Meses.GetUpperBound(0))
Console.WriteLine("Visualizamos el contenido")
' Visualizamos el vector
156
For Each Valor In Meses
Console.WriteLine(Valor)
Next
Console.ReadLine()
End Sub
End Module
Pero también se puede seguir haciendo lo clásico, con la función Ubound, aunque ahora también hay un método del objeto Meses, que se
llama GetUpperBound.
Y también podemos utilizar los siguientes métodos, en lugar del X=0 to 11, o to Ubound(meses)
For X=Meses.GetLowerBound(0) To Meses.GetUpperBound(0)
O bien
For X = 0 To UBound(Meses)
Module Ejemplo
Sub Main()
' Declaración e inicialización del vector con los
' nombres de los meses, de tipo string
Dim Meses() As String = {"Enero", "Febrero", "Marzo", _
"Abril", "Mayo", "Junio", _
"Julio", "Agosto", "Septiembre", _
"Octubre", "Noviembre", "Diciembre"}
Dim X As Int16
Dim Valor As String
Console.WriteLine("Visualizamos el contenido")
Console.ReadLine()
End Sub
End Module
Visto como se recorre el vector, veamos como se hace con una matriz, o un array de dos dimensiones.
Como principio, hay que indicar que una matriz necesita para recorrerse tantos contadores como dimensiones tiene, es decir tres
dimensiones, tres contadores.
157
X = X + 1
Loop Until X > UBound(M, 1)
End Sub
End Module
Una vez cargada la matriz para que tenga datos, vemos el uso completo carga y visualización.
Module Ejemplo
Sub Main()
' Declaración
Dim M(3, 4) As Integer ‘ veinte elementos 4 x 5
Dim X As Integer
Dim Y As Integer
Console.WriteLine("Visualizamos el contenido")
De ésta forma el bucle se ejecutará correctamente siempre independientemente del número de elementos del array.
Evidentemente la sintaxis que sigue también es correcta.
while (y < 5)
Loop Until Y > 5
En los ejemplos, por costumbre, se ha recorrido la matriz por filas, pero no hay nada que impida que se recorra por columnas.
Pág. 34.2
Unidad 34. Arrays en VB (III)
El siguiente es un sencillo ejemplo de clase.
Muy mejorable, pero fácil de entender.
Public Class ClaseVectores
Dim V() As Integer
158
' Es una variable inicializada, pero no es una propiedad
Private ValorMaximo As Integer = 100
Private Sub New()
' Impedimos que se declare sin recibir el vector en el constructor, new.
End Sub
En el siguiente ejemplo, no es necesario buscar un elemento, delante del mes de Enero, hay un valor nulo, de forma que toma el índice
cero y así Enero es el índice uno.
Dim Meses() As String = {"Enero", "Febrero", "Marzo", "Abril", _
"Mayo", "Junio", "Julio", "Agosto", _
"Septiembre","Octubre", "Noviembre",
"Diciembre"}
Sabemos que el mes de Enero es el número uno en el año, Febrero el dos, etc..
Por lo tanto podemos perfectamente, sin necesidad de buscar el dato, hacer lo siguiente.
Console.Writeln(NomMeses(mes))
Siendo “mes” una variable que contiene el mes de la fecha con la que trabajamos.
Pero como siempre eso no es posible, a veces hay que buscar la información.
2 Copia.
Una de las acciones posibles es la copia del contenido de un vector sobre otro.
Para ello en VB disponemos del método Copy, que lo realiza con comodidad.
La sintaxis de éste método es la siguiente
Meses.Copy(Meses, OtrosMeses, OtrosMeses.GetUpperBound(0))
Donde:
Meses Es el origen
OtrosMeses Es el destino
OtrosMeses.GetUpperBound(0) El número de elementos que deseamos copiar
OtrosMeses.GetUpperBound(0) lo utilizamos para indicar cuantos elementos deseamos copiar, ya que nos devuelve el número de
elementos que tiene el vector de destino.
Existe otra alternativa que es Clone, a diferencia de Clone, Copy hace un duplicado del vector, solo del número de elementos que se
indica en el argumento.
3 Clasificación.
Con las búsquedas sucede lo mismo, hay distintos tipos de algoritmos, unos más eficientes y otros menos, y como siempre depende del
momento y lo que hay que hacer.
Como ejemplo exponemos un método de clasificación, el de la burbuja, el menos eficiente, pero el más fácil de recordar, a partir de ahí, a
mejorar.
A la clase anterior le podemos añadir éste método, y podremos desde el main visualizar el vector ordenado.
Public Sub OrdenaVectorAscendente()
Dim Y As Integer
Dim Fin As Integer = V.Length
Dim Aux As Integer
While Fin > 0
Y = 0
' cada pasada se reduce en uno el
' número de elementos a comprobar
Fin = Fin - 1
' el mayor, en cada pasada se lleva al final del vector.
While (Y < Fin)
' comprobar si es mayor que el siguiente
If (V(Y) > V(Y + 1)) Then
' intercambio, cuando es mayor
Aux = V(Y)
V(Y) = V(Y + 1)
V(Y + 1) = Aux
End If
Y = Y + 1 ' incremento
End While
End While
End Sub
En función de cómo guste más la clase, el inicio del método puede ser como se ha visto o como sigue,
public Sub OrdenaVectorAscendente(ByRef V() as Integer) ' se recibe el
vector.
Todo depende de que método de inicialización se haya dejado.
161
Dim V(10) as Integer
Dim Objeto As New ClaseVector()
Objeto.GeneraVector(V)
Objeto.VerVector(V)
Objeto.OrdenaVectorAscendente(V)
Objeto.VerVector(V)
Console.ReadKey()
End Sub
Expliquemos las diferencias
Sub Main() ' No hay ni generación ni envío del vector.
Dim Objeto As New ClaseVector(10) ' Se crea en la clase, y está en la
clase
Objeto.GeneraVector()
entre estas dos opciones de crear una clase en un programa.
Sub Main() ' Si que hay generación y envío del vector.
Dim V(10) as Integer ' Se crea en el programa y se envía a la clase
Dim Objeto As New ClaseVector()
Objeto.GeneraVector(V)
Cuando hemos anulado la declaración del objeto con el envío del vector, la clase no tiene el vector en su poder, por decirlo de alguna
forma, por lo que si queremos visualizar el vector, se lo hemos de enviar, la clase solo sabe del vector que recibe, por que no tiene ninguno.
Por lo tanto el método de ordenación, al igual que el de visualización, debe recibir el vector.
Pág. 34.4
Unidad 34. Arrays en VB (V)
¿Pero que sucede?, si lo ordena, lo lógico es que lo devuelva, si no, para que sirve, por eso de ahí viene el cambio sintáctico de la
utilización del método.
162
Poco eficiente y mejorable, si se le envía el vector ordenado.
Hay otras más eficientes, pero no es el fin de este tema.
5 Invertir.
Otra de las posibles operaciones con un array, es la de invertir el contenido del mismo, ponerlo del
revés.
Para ello creamos un bucle con dos contadores uno ascendente y otro descendente.
Podemos añadir el siguiente método a la clase.
Public Sub Inversion()
Dim W(V.Length - 1) As Integer
Dim X As Integer
Dim Y As Integer
X = 0
Y = V.Length - 1
While X < V.Length
W(Y) = V(X)
X = X + 1
Y = Y - 1
End While
V = W
End Sub
El main para ésta opción sería el siguiente.
Sub Main()
Dim Objeto As New ClaseVector(10)
Dim Posic As Integer
Objeto.GeneraVector()
Objeto.VerVector()
Objeto.Inversion()
Objeto.VerVector()
Console.ReadKey()
End Sub
Pero para ello también podemos utilizar uno de los tipos de colecciones vistos anteriormente.
Public Sub Inversion()
Dim X As Integer
' definir la pila.
Dim Pila As New System.Collections.Stack
' volcado del vector a la pila
x = 0
While X < V.Length
' Introdución del contenido en la pila
Pila.Push(V(X))
X = X + 1
End While
Vamos a ver la utilidad de cada uno de los métodos existentes en cada una de las dos clases.
1 Clear
Siguiendo con el ejemplo anterior, el método Clear realiza el vaciado del contenido del vector, pero no del número de elementos, que seguirá
siendo el mismo
Module Ejemplo
Sub Main()
Dim Meses() As String = {"Enero", "Febrero", "Marzo", "Abril", _
"Mayo", "Junio", "Julio", "Agosto", _
"Septiembre","Octubre", "Noviembre",
"Diciembre"}
Dim Valor As String
2 Clone
Este método lo que hace es generar una copia de un array ya existente.
Module Ejemplo
Sub Main()
Dim Meses() As String = {"Enero", "Febrero", "Marzo", "Abril", _
164
"Mayo", "Junio", "Julio", "Agosto", _
"Septiembre","Octubre", "Noviembre",
"Diciembre"}
Dim OtrosMeses() As String
Dim Valor As String
3 ConstrainedCopy
Copia el número de elementos indicado de un array de origen a un array de destino, en la dimensión que se indica, y del número de
elementos que se indique.
Module Ejemplo
Sub Main()
Dim Meses() As String = {"Enero", "Febrero", "Marzo", "Abril", _
"Mayo", "Junio", "Julio", "Agosto", _
"Septiembre","Octubre", "Noviembre",
"Diciembre"}
Dim Mesesitos(3) As String
Dim Dato As String
Dim DimOrigen As Integer = 0
Dim DimDestino As Integer = 0
Dim Cuantos As Integer = 2 ' probar con 2 y 4
165
‘ Meses.Copy(Meses, OtrosMeses, OtrosMeses.GetUpperBound(0))
Module Ejemplo
Sub Main()
Dim Meses() As String = {"Enero", "Febrero", "Marzo", "Abril", _
"Mayo", "Junio", "Julio", "Agosto", _
"Septiembre","Octubre", "Noviembre",
"Diciembre"}
' Le damos cinco elementos
Dim OtrosMeses(5) As String
Dim Valor As String
Console.WriteLine("Visualizamos el contenido ")
Console.WriteLine("Elementos del vector {0} ", Meses.GetUpperBound(0))
' Visualizamos el vector
For Each Valor In Meses
Console.WriteLine(Valor)
Next
6 CreateInstance
Crea un array a partir de la información existente en el array de origen.
Observar que en este ejemplo está activado Option Strict a Off, sin comentarios.
Option Strict Off
Module Ejemplo
Sub Main()
Dim Meses() As String = {"Enero", "Febrero", "Marzo", "Abril", _
"Mayo", "Junio", "Julio", "Agosto", _
"Septiembre","Octubre", "Noviembre",
"Diciembre"}
Dim Dato As String
' Contenido vector origen
For Each Dato In Meses
Console.WriteLine(Dato)
Next
' Crear el vector con createinstance
' Dim Otro = Array.CreateInstance(Meses.GetType, Meses.Length)
' El formato anterior, aunque parece lógico no sirve.
Dim Otro = Array.CreateInstance(GetType(String), Meses.Length)
' Cargarlo con datos
Meses.CopyTo(Otro, 0)
' Contenido vector destino
Console.WriteLine("Visualizar el vector de destino")
For Each Dato In Otro
Console.WriteLine("Mes de {0} ", Dato)
Next
Console.ReadLine()
End Sub
End Module
167
End Module
8 GetType
Devuelve el tipo que tiene el array dentro de la clase System
Module Ejemplo
Sub Main()
Dim X As Int16
9 GetValue
Devuelve el contenido de la posición que indicamos en el argumento.
En el ejemplo el valor devuelto es Abril.
Pero también es válido y da también Abril.
Console.WritelLine(Meses(3))
Module Ejemplo
Sub Main()
Dim X As Int16
168
Console.WriteLine(Meses.IndexOf(Meses, "Febrero")) ‘ 1
Console.WriteLine(Meses.LastIndexOf(Meses, "Febrero")) ‘ 7
Console.WriteLine("Visualizamos el contenido ")
For Each Valor In Meses
Console.WriteLine(Valor)
Next
Console.ReadLine()
End Sub
End Module
11 Rank
Devuelve el número de dimensiones de un array.
Console.WriteLine("Meses tiene {0} dimensiones ", Meses.Rank)
12 Reverse
Invierte el contenido actual del vector.
Module Ejemplo
Sub Main()
Dim X As Int16
Dim Meses() As String = {"Enero", "Febrero", "Marzo", _
"Abril", "Mayo", "Junio", _
"Julio", "Agosto", "Septiembre", _
"Octubre", "Noviembre", "Diciembre"}
Dim Valor As String
Console.WriteLine("Visualizamos el contenido ")
Meses.Reverse(Meses)
[Array].Reverse(Meses) ‘ se queda como estaba
13 SetValue
Establece un valor nuevo para el elemento que se indica, en el ejemplo sustituimos Noviembre por Juan.
Module Ejemplo
Sub Main()
Dim X As Int16
Dim Meses() As String = {"Enero", "Febrero", "Marzo", _
"Abril", "Mayo", "Junio", _
"Julio", "Agosto", "Septiembre", _
"Octubre", "Noviembre", "Diciembre"}
Dim Valor As String
14 Sort
Este método lo que hace es clasificar el vector, que evidentemente siempre se agradece.
Hay dos sistemas en el ejemplo,
[Array].Sort(Meses)
En este se usa la clase genérica Array para usar sus métodos.
Meses.Sort(Meses)
Aquí se usa el vector, con el método sort.
169
Como se puede comprobar cualquiera de los dos es válido.
Module Ejemplo
Sub Main()
Dim X As Int16
Dim Meses() As String = {"Enero", "Febrero", "Marzo", "Abril", _
"Mayo", "Junio", "Julio", "Agosto", _
"Septiembre","Octubre", "Noviembre", "Diciembre"}
Dim Valor As String
Console.WriteLine("Visualizamos el contenido ")
Meses.Sort(Meses)
[Array].Sort(Meses)
170
End Sub
End Class
Para facilitar la prueba de los ejercicios se ha creado un método que genera valores aleatorios de forma automática.
Public Sub Genera()
Dim X As Integer
' Inicializa el generador de números aleatorios
Randomize()
While X <> V.Length
' Genera un valor aleatorio entre 1 0 50
V(X) = CInt(Int((50 * Rnd()) + 1))
X = X + 1
End While
El control de los bucles se podría haber realizado con
While X <> V.Length
O bien con
While X <= Ubound(V)
El método Length devuelve un cual es el número de elementos del vector.
La función Ubound devuelve cual es el valor del índice del último elemento del vector.
1. Crear un vector de 10 elementos numéricos enteros, cargarlo con datos y visualizar su contenido.
Public Class Vectores
Dim V() As Long
Dim Cuantos As Integer = 20
171
End class
El programa principal.
Module Tema_34
Sub Main()
Dim Objeto As Vectores = New Vectores(10)
Objeto.Genera()
Objeto.Visualiza()
Console.Read()
End Sub
End Module
2. Crear un vector de 10 elementos alfanuméricos, cargarlo con datos y visualizar el contenido de los que están
ocupando la posición par.
A la clase anterior añadimos el método que se puede ver en la solución.
Public Sub VisualizaPosicion(ByVal PosicionMultiplo As Integer)
Dim X As Integer
While X <> V.Length
Select Case X Mod PosicionMultiplo = 0
Case True
Console.WriteLine("Posición {0} Contenido {1}", X, V(X))
End Select
X = X + 1
End While
End Sub
Al hacer está pregunta, podemos visualizar cualquier posición múltiplo de un valor x, y si su valor es uno, visualiza todos los elementos del
array.
El programa principal
Module Tema_34
Sub Main()
Dim Objeto As Vectores = New Vectores(10)
Objeto.Genera()
Objeto.VisualizaPosicion(2)
Console.Read()
End Sub
End Module
3. Crear una matriz de 3 x 3 numérica, cargar los datos y visualizarla dando la visión de matriz.
Private Sub GeneraMatriz(ByVal M(,) As Integer)
Dim X As Integer
Dim Y As Integer
Dim Filas As Integer = UBound(M, 1) ' M.GetLength(0) '
M.GetUpperBound(0)
Dim Columnas As Integer = UBound(M, 2) ' M.GetLength(1) '
M.GetUpperBound(1)
Console.ReadLine()
End Sub
End Module
4. Crear una matriz de 3 x 3 numérica, cargar los datos, intercambiar los datos de la 1 fila con la tercera fila, y
visualizarla dando la visión de matriz.
Private Sub Intercambio(ByVal M(,) As Integer, _
ByVal F1 As Integer, _
ByVal F2 As Integer)
Dim Y As Integer
Dim Columnas As Integer = UBound(M, 2)
Dim Aux As Integer
' Intercambio
Y = 0
Do
Aux = M(F2, Y)
M(F2, Y) = M(F1, Y)
173
M(F1, Y) = Aux
Y = Y + 1
Loop Until Y > Columnas
Console.WriteLine()
End Sub
El programa principal sería
Module Tema_34
Private Sub Main()
' Declaración e inicialización
Dim M(2, 2) As Integer
GeneraMatriz(M)
VisualizaMatriz(M)
Intercambio (M,0,2)
VisualizaMatriz(M)
Console.ReadLine()
End Sub
End Module
5. Tenemos un Vector V de cincuenta elementos, generar un vector P de cincuenta elementos de forma que:
P(1) = V(1)
P(2) = V(1)+V(2)
P(3) = V(1)+V(2)+V(3) .. / ..
P(50) = V(1) ...V(50)
A la clase anterior le podemos añadir este método
X = 1
P(0) = V(0)
While X < V.Length
P(X) = P(X - 1) + V(X)
X = X + 1
End While
V = P
End Sub
Como cada elemento es la suma del anterior más el nuevo, empezamos en la posición uno, pero hay que :
P(0) = V(0)
Para disponer de anterior.
P(X) = P(X - 1) + V(X)
Al final de la ejecución asignamos el nuevo vector al de la clase, así podemos utilizar los métodos ya escritos.
V = P
El programa principal sería:
Sub Main()
Dim Objeto As New Vectores(10)
Dim P(10) As Integer
Objeto.GeneraVector()
Objeto.VerVector()
Objeto.Quinto(P)
Objeto.VerVector()
Console.ReadKey()
End Sub
6. Introducir diez números y luego visualizarlos en orden inverso, al de entrada.
A la clase anterior podemos añadir el siguiente método.
Public Sub VisualizaInverso()
Dim X As Integer = V.Length
While X > 0
X = X - 1
Console.WriteLine(V(X))
End While
174
End Sub
Y el Main quedaría
Sub Main()
Dim Objeto As New Vectores(10)
Dim P(10) As Integer
Objeto.GeneraVector()
Objeto.VerVector()
Objeto.VisualizaInverso()
Objeto.VerVector()
Console.ReadKey()
End Sub
7. Introducir veinte números entre uno y cincuenta, y luego indicar cuales de esos cincuenta son los que se han
utilizado.
Podemos resolver el ejercicio con este procedimiento.
El vector a utilizar es del tipo bolean, solo nos piden cuales han sido usados.
Sub Main()
Dim V(51) As Boolean
Dim X As Integer
Dim Numero As Integer
La validación de año bisiesto es circunstancial, es más compleja que dividir por cuatro.
La estructura del ejercicio es poco adecuada, como mínimo debería haberse utilizado una función para la conversión de las fechas en
días.
Conviene probar al menos en un par de ejercicios estas opciones, para captar sus diferencias.
UBound(V) V.GetLength(0) V.GetUpperBound(0)
177
Unidad 35. Captura de errores (I)
35.1. Objetivos del tema.
Adentrarse dentro de la captura de errores en programación.
35.2. Introducción.
Todo programa tiene un nivel de calidad.
La calidad vendrá marcada por distintos factores, un buen análisis, una buena depuración, etc..., y un adecuado control y captura de
errores.
Un programa no debe finalizar nunca de forma brusca, siempre debe tener una salida ante cualquier contingencia, por varios motivos,
calidad del producto, por un resultado elegante en la forma de funcionar el programa, y otro importante, porque de esa forma se consigue la
posibilidad, si se desea, de dejar un histórico de fallos, que después permitirá obtener datos para la solución de los mismos.
En la captura de errores, hay que tener presente que no siempre son errores de ejecución, si no que en muchas ocasiones la única forma
de poder tomar la decisión adecuada en un momento determinado, es la de forzar un fallo en el programa, para su captura posterior.
35.3. Captura de errores.
La captura de errores por lo tanto se hace indispensable.
Cada lenguaje dispone de un sistema de captura, podrá ser mejor o peor, podrá o no gustarnos pero hay que utilizarlo, y no porque sea
un mal sistema o un engorro utilizarlo, dejar de hacerlo.
Este apartado es el que puede marcar la diferencia entre nuestro programa y otros similares.
Tanto en VB como en otros lenguajes, la instrucción de captura es la misma, Try, con las diferencias que cada lenguaje le otorga.
public ClaseArchivos(String Ruta, String Nombre)
{
try
{
FileWriter Salida = null;
File Archivo = new File(Ruta + Nombre);
Salida = new FileWriter(Archivo);
}
catch (IOException ex)
{
Logger.getLogger(ClaseArchivos.class.getName()).log(Level.SEVERE, null,
ex);
}
}
En Vb
Try
FileOpen(Canal, Nombre, OpenMode.Input)
Catch ex As IO.IOException
Console.WriteLine("Error en acceso al archivo")
End Try
35.4. Errores.
En cualquier caso, para poder hacer una gestión de dichos errores, es necesario siempre tener prevista la clase adecuada para su gestión
y estudiar las capacidades del lenguaje para explotarlas al máximo.
Como podemos observar aumenta el volumen en el programa principal, y por otro lado se pierde la ubicación de donde se genera el error,
que en el ejemplo no tiene ninguna importancia, pero en un uso real sí puede tenerla.
package trazas;
La clase sin embargo pasa al contrario, pero hay que tener presente que una clase se escribe una vez, y se usa muchas.
Por lo tanto, visto los dos caminos, todo es cuestión de gustos, y de cómo queramos que sea nuestro código.
Pág. 35.1
Un programa no debe finalizar nunca de forma brusca, siempre debe tener una salida ante cualquier contingencia, por dos motivos, por
elegancia en la programación, y otro, el más importante, porque de esa forma se consigue la posibilidad, si se desea, de dejar un histórico de
fallos, que después permitirá obtener datos para la solución de los mismos.
En la captura de errores, hay que tener presente que no siempre son errores de ejecución, si no que en muchas ocasiones la única forma
de poder tomar la decisión adecuada en un momento determinado, es la de forzar un fallo en el programa, para su captura posterior.
Salida:
Exit Sub
Errores:
Select case Err.Number
Case Codigo_Error
Resume
Case Codigo_Error
Resume Salida
Case Codigo_Error
Resume Next
Case else
Procedimiento_Salida_Error_Imprevisto
End select
End Sub
La ejecución del procedimiento o función se realiza de manera normal, hasta que se produce una situación de error, en ese momento se
desvía la ejecución a la zona de captura de errores donde se trata el mismo, pudiéndose tomar las siguientes opciones según interese:
Resume Vuelve donde se produce el error
Resume Next Vuelve a la siguiente instrucción que provocó el error
179
Resume Etiqueta Se desvía la ejecución a la etiqueta indicada.
Try
' el programa
A = b / c
Catch Ex As OverflowException ' tratamiento de error
Alberga nuestro código a proteger.
Catch Ex As OverflowException ' tratamiento de error
Console.WriteLine("Error overflow del tipo {0}", Ex.Message)
Es la parte de tratamiento de error previsto en el tipo definido por As OverflowException
Finally ' siempre se ejecutará
Console.WriteLine("Siempre se ejecutará")
Todo lo que se escriba entre Finally y End Try siempre se ejecuta, pase lo que pase, excepto un aborto de ejecución del programa.
Como se puede comprobar en el ejemplo se pueden abordar diversas situaciones de error en un mismo Try.
36.5. Inhibición.
En VB se podría decir que es una inhibición real, pues no hacer nada, implica que el error se devuelve por la línea de ejecución hasta
encontrar un procedimiento que lo trata o se llega al programa principal y se aborta el programa por error manifiesto.
36.6. Conclusiones.
Con el desvío de excepciones se obtienen varias ventajas, e inconvenientes.
Se reduce el volumen de código, por lo que es más sencillo de releer y seguir. También se obtiene de esa forma la posibilidad, de que
cuando se crea código para terceros, se deja la forma o la interface de los mensajes de error, en manos de quien la usa, lo cual en la mayoría de
los casos es una buena alternativa, ya que el código queda completamente integrado en el programa donde se incrusta la clase.
Evidentemente tiene como inconveniente, que no responsabilidad, de que eso genere una ejecución inadecuada, pero lo será por quien la
usa, no por quien la escribió.
Pág. 36.2
Unidad 37. Archivos (I)
37.1. Objetivos del tema.
Entrar en la filosofía de utilización de los archivos en programación.
37.2. Introducción.
En todos los programas es necesario en algún momento la conservación y la recuperación de datos.
La información que se maneja en el ordenador esta gestionada en base a dos medios de almacenamiento, uno
temporal como es la memoria y otro mas duradero como es el soporte magnético.
180
Las diferencias entre ambos, a parte del tema de la ejecución de los programas, estriban en la capacidad de permanecer la información
en los soportes cuando el ordenador es desconectado, mientras que la memoria no tiene esa característica, además la capacidad de
almacenamiento de la memoria es reducida.
La información, datos y programas que se utilizan tienen una estructura.
En la memoria la información se maneja en variables, arrays y listas.
En los soportes la información se maneja como archivos, registros y campos, con distintos tipos de acceso, que a su vez están
condicionados por el tipo de soporte utilizado que sea o no direccionable.
Existen distintos tipos de archivos que se clasifican por el acceso a los datos que en ellos se graban.
También se podría hablar de los soportes para el almacenamiento de los datos de dichos archivos, pero sería salirse demasiado del
contenido de estos apuntes.
Los archivos son direccionables y no direccionables, y los soportes han de guardar dicha relación, aunque hoy en realidad no hay
soportes no direccionables, están en desuso, pero nombrado queda al menos.
Para la comunicación de un programa con los datos depositados en un archivo, necesitamos conocer varios datos.
Nombre del archivo.
Su ubicación en el sistema en el que trabajamos.
La estructura de los datos almacenados en ese archivo.
La comunicación del programa con los datos a su vez se realiza a través del Sistema Operativo, al cual le facilitamos dicha información
utilizando las instrucciones disponibles en el lenguaje de programación para el manejo de archivos.
El Sistema Operativo nos devolverá un medio de enlace que el lenguaje de programación utilizará para la comunicación con los datos del
archivo.
Ese medio de enlace es un canal, dicho canal en cada lenguaje de programación es representado de una forma diferente, pero al fin y al
cabo es el elemento que representa al archivo en nuestro programa.
En este apartado de utilización de archivos para el manejo de estructuras de datos, grabación y lectura, también se debe incluir las bases
de datos, que al fin y al cabo son archivos en los que depositamos información, pero debido a que las bases de datos generan archivos y
estructuras de datos que son gestionados por otros programas externos a nuestro lenguaje, -Sistemas Gestores de Bases de datos-, MySql,
Oraqle, SQL Server, etc..., la gestión de los mismos es más compleja y no vamos a entrar en ello ahora.
Nombre.
El nombre con el que el programador le asigna cuando lo crea.
Este nombre reunirá una serie de características léxicas y sintácticas que varían en función del S. O. como
longitud, extensiones, tipos de caracteres a usar.
Las extensiones se utilizan para identificar los archivos del mismo tipo.
El nombre incluye la dirección del archivo en el ordenador o en el lugar en el que esté colocado.
“Unidad:\Archivo.Ext”
C:\Archivo.ext
“\\Ordenador\Unidad:\Archivo.Ext”
\\Ordenador\C:\Directorio\MiArchivo.ext”
Tamaño.
El tamaño hace referencia al volumen de datos que tiene el fichero generalmente, no al espacio que ocupa en
disco, que puede ser superior. Se mide en bytes, palabras o bloques.
Ubicación.
Hace referencia a una dirección de inicio del archivo, o donde esta el puntero del último registro.
Luego cada uno de los bloques que el archivo ocupa está encadenado con los otros bloques que ocupa.
Características del archivo, una serie de bytes que activados o no indican las propiedades del
archivo, posibilidades de acceso para el control de lectura y escritura.
181
Datos de fecha y hora.
Ultima fecha de cuando se modificó o creó el archivo.
Pág. 37.1
Empezando por los archivos de datos, en ellos vamos a encontrarnos básicamente con dos tipos de
estructuras.
Entendemos por estructura la distribución de los datos en el archivo.
Cada uno de los campos contendrá una información y le corresponderá un tipo de datos de los que el lenguaje de programación
contemple.
A su vez puede darse el caso que un archivo pueda tener distintos tipos de estructuras:
Todos los registros son iguales.
Hay uno o varios registros de cabecera.
Registros de detalle.
No direccionables.
Direccionables.
Los archivos no direccionables son archivos en los cuales no podemos acceder a un registro de datos sin haber leído previamente los
anteriores.
A pesar de su característica, no están por ello en desuso ya que tiene como contrapartida lo
compacto que son ya que el aprovechamiento del espacio ocupado es del cien por cien.
Suelen utilizarse para almacenar información que se intercambia entre distintos procesos o
empresas para el envío de información en formatos compatibles.
Los archivos direccionables permiten acceder a la información sin haber leído los registros
anteriores, lo cual les da velocidad en el acceso.
Se pueden grabar en cualquier tipo de soporte, ya que al no ser direccionable, no requiere que el
soporte lo sea.
A cambio, nunca hay nada gratis, no son tan compactos como un archivo secuencial, por el sistema
de direccionamiento necesario en su gestión.
Se tiene que grabar en un soporte direccionable, no se pueden grabar en una cinta de casete por
ejemplo.
Echo
Echo " Generando respaldo de los FS de usuarios, WebSphere y db2 ...."
tar cvf \dev\rmt0 \usr\usuarios \usr\local\WebSphere \usr\local\Software
\usr\local\db2\dbgis
echo ""
echo " Generando respaldo de los FS de usuarios, WebSphere y db2 ...."
tar cvf /dev/rmt0 /usr/usuarios /usr/local/WebSphere /usr/local/Software
/usr/local/db2/dbgis
sleep 5;
echo " Fin del respaldo ...... OK "
echo " DONE "
echo
#
Lo mismo sucede con los archivos de sonido, imágenes, video, etc.
A su vez cada uno de estos archivos tiene asociado un programa que es capaz de leerlo para interpretar y poder utilizar sus datos.
Pág. 37.2
Unidad 37. Archivos (III)
37.7. Tipos de archivos, por su duración en el tiempo.
Los archivos también pueden clasificarse por el uso que se hace de ellos.
Copias de seguridad.
Son archivos que tienen la imagen de otro igual a ellos, en otro soporte o directorio.
De trabajo, temporales.
Son los que se crean de forma provisional para realizar un trabajo y al finalizar el trabajo desaparecen.
Maestros.
Contienen todos los datos de una determinada información, clientes, artículos, proveedores, etc..
Movimientos.
Contienen información cuya duración es breve, pues esta a la espera de ser procesada para desaparecer una
vez ejecutado el programa de bajas de clientes, altas, una vez ejecutado el programa ya no hace falta la
información.
Histórico.
Contienen la información que es el resultado de procesos normales de gestión de periodos de tiempo ya
pasados, facturas, movimientos contables, calificaciones.
37.8. Estructuras de los registros.
Los registros de datos pueden grabarse básicamente en dos tipos de formatos.
Con delimitadores de campos
Sin delimitadores de campos
En el primer caso permite sin ningún problema los registros de longitud variable, en el segundo normalmente serán de longitud fija.
Los delimitadores son las comas para separar los campos y las comillas para delimitar los campos de texto, los campos numéricos no
llevan delimitadores de campo.
Al final de cada registro hay una marca de final de registro.
183
Este registro puede ser indistintamente de longitud fija o variable.
Su definición podría ser así:
Tipo de archivo Secuencial
Nombre Archivo.Ext
Nombre Tipo
Código Alfanumérico
Denominación Alfanumérico
Precio Alfanumérico
Cantidad Alfanumérico
Descuento Alfanumérico
Los datos numéricos se pueden almacenar de ambas formas, numéricos o alfanuméricos, siempre y cuando previo a su utilización se conviertan
al tipo de dato adecuado.
En el primer caso la definición de los campos no necesita de una delimitación de los mismos desde el programa que los trata, solo es
necesario conocer el orden en el que aparecen los datos.
En el segundo se hace imprescindible que el programa conozca el diseño del registro incluyendo la longitud de cada uno de los campos y
su tipo de campo para saber que lo que se está leyendo es un campo numérico o alfanumérico.
Esta es la definición de la estructura de dos tipos de archivos de datos estándar.
La estructura de los tipos de archivos restantes vendrá dada por el propietario del formato y se basan siempre en estructuras que
arrancan a partir de estas.
Pág. 37.3
En el caso de archivos no direccionables, secuenciales, el proceso de actualización se basa en la creación previa de un archivo que
contiene las modificaciones del archivo original, para posteriormente lanzar un programa que realice la inserción, actualización y borrado de los
registros en el archivo original, creando un nuevo archivo con los cambios realizados.
En el caso de archivos direccionables la actualización se realiza sobre el registro directamente, sin necesidad de actuar sobre el archivo
en su conjunto.
Conviene tener presente que un archivo se puede leer con cualquier programa, independientemente del lenguaje en el que esté escrito,
respetando eso sí, los tipos de datos que en el mismo se han grabado.
Si se conoce la estructura del archivo, los tipos de datos que posee son compatibles con el lenguaje que estamos utilizando, el archivo
puede ser leído por el programa que escribamos, aunque no se haya escrito en el mismo lenguaje que en el que se grabó.
184
2 Procesos de impresión.
Los procesos de impresión pueden o no considerarse dentro de los anteriores, es cuestión de gustos.
La impresión de los datos habitualmente implica ofrecer la posibilidad de obtener los datos clasificados por alguno de los datos que
existen en el archivo, alfabéticamente, por código, por cursos, por población, etc..
También la de realizar filtrados de dicha información, bien porque se realice una impresión parcial de la información, desde el diez hasta el
30, o porque se seleccione solo determinados datos, los de una población, etc..
Pág. 37.4
A continuación necesitaremos conocer las distintas instrucciones disponibles en nuestro lenguaje para acceder al archivo en cuestión.
38.3. Abrir, acceder al archivo.
En la apertura de un archivo se pueden dar varias situaciones.
Queremos grabar un nuevo archivo.
Queremos grabar un archivo y ya existe.
Queremos leer un archivo y éste puede existir o no.
Hay que tener presente que cuando inicializamos la variable “Nombre” con el dato del nombre del archivo simultáneamente hay que
indicar la dirección del archivo,
185
38.4. Grabar.
Si deseamos añadir datos al archivo utilizaremos el método writeline en el canal que hemos establecido anteriormente.
Module Ejemplo
Sub main()
Dim Canal As Int16 = FreeFile()
Dim Nombre As String = "Prueba.Txt"
Dim Valor As String
Dim Meses() As String = {"Enero", "Febrero", "Marzo", _
"Abril", "Mayo", "Junio", _
"Julio", "Agosto", "Septiembre", _
"Octubre", "Noviembre", "Diciembre"}
186
Además para que todo lo visto, tanto en lectura como en escritura, funcione adecuadamente conviene establecer una captura de errores,
por lo que todo lo expuesto debería ir entre
try
‘ todo el ejemplo visto anteriormente
catch Ex as Io.Ioexception
Console.WriteLine("Error en acceso al archivo")
End try
Como se puede apreciar al inicio del ejemplo.
38.6. Cerrar.
Cerrar el archivo solo precisa de la utilización del método close.
FileClose(Canal)
38.7. Matices.
Mientras la instrucción de grabar
WriteLine(Canal, Valor) ‘ con marca fin de registro
Permite que en la misma línea de código se graben varios campos
WriteLine(Canal, Codigo, Denominación, Cantidad)
Su equivalente en lectura no lo permite ya que solo admite un campo en cada instrucción, por lo tanto la lectura para
WriteLine(Canal, Codigo, Denominación, Cantidad)
sería
Input(Canal, Codigo)
Input(Canal, Denominacion)
Input(Canal, Cantidad)
Una línea para cada campo.
Sub Main()
Dim Canal As Integer
Dim Texto As String
AbreArchivo("Texto.txt", Canal)
Texto = Console.ReadLine
GrabarFrase(Canal, Texto)
FileClose(Canal)
End Sub
End Module
2.- Acceder al archivo anterior y visualizar la frase que se ha grabado.
Module Tema_38
Private Sub AbreArchivo(ByVal Nombre As String, ByRef Canal As Integer)
Canal = FreeFile()
187
Dim Archivo As String = My.Application.Info.DirectoryPath & "\" &
Nombre
FileOpen(Canal, Archivo, OpenMode.Input)
End Sub
Sub Main()
Dim Canal As Integer
Dim Texto As String
AbreArchivo("Texto.txt", Canal)
Console.WriteLine(LeerFrase(Canal))
FileClose(Canal)
Console.ReadLine()
End Sub
End Module
3.- Crear un archivo y copiar el contenido del archivo anterior.
Module Tema_38
Private Sub AbreArchivoNuevo(ByVal Nombre As String, ByRef Canal As
Integer)
Canal = FreeFile()
Dim Archivo As String = My.Application.Info.DirectoryPath & "\" &
Nombre
FileOpen(Canal, Archivo, OpenMode.Output)
End Sub
Sub Main()
Dim Canal As Integer
Dim CanalNuevo As Integer
Dim Texto As String
AbreArchivo("Texto.txt", Canal)
AbreArchivoNuevo("Nuevo.txt", CanalNuevo)
GrabarFrase(CanalNuevo, LeerFrase(Canal))
FileClose(Canal)
FileClose(CanalNuevo)
Console.ReadLine()
End Sub
End Module
4.- Acceder al nuevo archivo y visualizar su contenido.
188
Module Tema_38
Private Sub AbreArchivo(ByVal Nombre As String, ByRef Canal As Integer)
Canal = FreeFile()
Dim Archivo As String = My.Application.Info.DirectoryPath & "\" &
Nombre
FileOpen(Canal, Archivo, OpenMode.Input)
End Sub
Sub Main()
Dim Canal As Integer
AbreArchivo("Nuevo.txt", Canal)
Console.WriteLine(LeerFrase(Canal))
FileClose(Canal)
Console.ReadLine()
End Sub
End Module
Por ejemplo la lectura de un registro de longitud fija puede darse en dos formatos.
Como cadena de caracteres, sin delimitadores.
Como ascii delimitado, con delimitadores.
La estructura de longitud variable también puede darse bajo los dos tipos de formatos, siempre y cuando cada registro se acompañe con
las marcas de fin de registro.
39.7. Ejemplos de formatos.
El formato que sigue es un formato de registro de longitud fija y con marcas de final de registro.
No incorpora delimitadores de campos.
0001DENOMINACIONCAMPOCAMPOCAMPO
0002DENOMINACIONCAMPOCAMPOCAMPO
El formato que sigue es ascii delimitado con campos de longitud fija, pero podrían haber sido de longitud variable.
Incorpora delimitadores de campo y separadores
","
Y las marcas de final de registro.
"0001","DENOMINACION","CAMPO","CAMPO","CAMPO"
"0002","DENOMINACION","CAMPO","CAMPO","CAMPO"
El registro que sigue es de longitud fija, sin delimitadores de campo y sin marcas de final de registro.
Se hace algo más complejo su proceso, pues requiere de algún ajuste, y tiene sentido usarse cuando los registros son pequeños, el
soporte también, que hoy no es el caso, y queremos ajustar por el motivo que sea.
0001DENOMINACIONCAMPOCAMPOCAMPO0002DENOMINACIONCAMPOCAMPOCAMPO
Pág. 39.1
A pesar de ser archivos que no son habituales en un proceso de gestión, sin embargo surge la necesidad de su utilización en algunas
ocasiones, o en muchas.
Dado que no es un archivo direccionable, el proceso de actualización se basa siempre en un proceso de emparejamiento de registros de
dos archivos secuenciales, de entrada que da uno nuevo de salida.
El que contiene los datos actuales.
El que contiene los nuevos datos.
El resultado es un archivo nuevo, en el que han desaparecido los registros que había que borrar, se han incorporado los nuevos y se han
actualizado los que tenían algún cambio.
Además de la acción de leer y grabar, hay un apartado importante en su tratamiento, y es el de la necesidad de la utilización de una
estructura repetitiva para su proceso, listado, consulta etc.
190
Mientras no Fin de archivo
Leer registro
Proceso
Fin Mientras
Es importante tener presente que este es el mejor sistema para su proceso.
Por este motivo antes de entrar en el bucle de proceso, se debe cargar una pareja de registros fuera del bucle.
Al realizar la lectura en un archivo si se da la circunstancia de final de archivo, es cuando al código de ese archivo se le asigna el high
value.
No sirve utilizar variables de tipo booleano, ni cualquier otra combinación, cuyo único resultado al final es maquiavélico, comparado con la
sencillez de éste proceso.
If No final(Incidencias) Entonces
Leer(Canal, Codigo, .....)
Sino
Codigo = Hv
Fin
If No final(Datos) Entonces
Leer(CanalDatos, CodDatos)
Sino
CodDatos = Hv
Fin
191
Fin
Fin segun
Fin Mientras
La variable o constante HV debe recibir un valor que sea inalcanzable por los datos del archivo, en caso contrario el proceso no
funcionará adecuadamente.
Los archivos a procesar deben estar ordenados, pues el proceso realiza una comparación de los códigos
El archivo de incidencias será igual en diseño que el archivo de datos actuales, y además incorporará un dato que indicará si es una
modificación, alta o borrado.
El proceso se realiza en función de los valores del campo código.
Pág. 39.2
Lo primero es definir una variable que haga referencia al canal, en VB, la forma de identificar un archivo, es saber que canal de enlace
utiliza con el sistema.
Dim Canal As Integer
Después lo más cómodo es utilizar la función freefile, que nos devolverá un canal disponible, en lugar de tenerlo que gestionar nosotros.
Canal = FreeFile()
Esta instrucción debe ejecutarse justo antes de abrir el archivo, nunca antes, si no la información obtenida puede no ser correcta.
El siguiente paso es realizar la apertura, en el modo que nos interese.
FileOpen(Canal, "Nombre.dat", OpenMode.Output)
Para grabar datos la sintaxis es la que sigue:
Dim Canal As Integer
Canal = FreeFile()
FileOpen(Canal, "Nombre.dat", OpenMode.Output)
Para realizar una lectura:
Dim Canal As Integer
Canal = FreeFile()
FileOpen(Canal, "Nombre.dat", OpenMode.Input)
Para añadir datos, a un archivo ya existente.
Dim Canal As Integer
Canal = FreeFile()
FileOpen(Canal, "Nombre.dat", OpenMode.Append)
Matices, si se abre para grabar con Output, si el archivo existe perderá su contenido, si no existe se creará.
Si se abre para grabar con el modo Append, se añaden los datos a los que pudiera tener.
Si se abre con input se accede a él para leer su contenido.
40.4. Grabar una estructura de datos.
Bueno visto como efectuar la lectura y escritura en un archivo secuencial, conviene ampliar el tema para un archivo con una estructura
algo más amplia.
Para la estructura de datos podemos utilizar un array o una colección, con el fin de almacenar los datos a utilizar en la misma.
La grabación de los datos no es nada más que la generación de un registro de datos con un formato en concreto, uno de los más
extendidos es el ASCII delimitado.
En este formato se graban los datos numéricos separados por comas y los alfanuméricos encerrados entre comillas dobles.
VB integra directamente el formato ASCII delimitado, y no es necesario ningún tipo de acción especial.
Además permite grabar registros de longitud variable, bajo una única variable, útil para datos de texto.
Para la grabación de los datos de un registro podemos hacerlo bajo dos formatos.
La estructura se graba como una variable definida con una estructura de usuario.
Public Structure Tiostro
192
Public Exped As String
Public Nomb As String
Public Ape1 As String
Public Ape2 As String
Public Domic As String
End Structure
Dim Registro as TipoRegistro
Y grabar
WriteLine(Canal, Registro)
O bien podemos grabar los datos en una variable cada uno de ellos, prescindiendo de la estructura.
WriteLine(Canal, Expediente, Nombre, Domicilio)
Pág. 40.1
Unidad 40. Archivos secuenciales en VB (II)
40.5. Leer un registro.
El siguiente paso sería intentar leer el registro que hemos grabado anteriormente.
Para la grabación sin usar la estructura la lectura es como sigue:
Input(Canal, Expediente) ' código
Input(Canal, Nombre)
Input(Canal, Domicilio)
Para la grabación usando la estructura la lectura es como sigue:
Input(Canal, Registro) ' código
Por este motivo antes de entrar en el bucle de proceso, se debe cargar una pareja de registros fuera del bucle.
Al realizar la lectura en un archivo si se da la circunstancia de final de archivo, es cuando al código de ese archivo se le asigna el high
value.
No sirve utilizar variables de tipo booleano, ni cualquier otra combinación, cuyo único resultado al final es maquiavélico, comparado con la
sencillez de éste proceso.
A continuación exponemos el núcleo del proceso.
No está completo, se ha extraído lo esencial, y se ha realizado sin el uso de estructuras.
If Not EOF(CanalMalum) Then
LeerMaes(CanalMalum, ExpedM, NombM, Ape1M, Ape2M, DomicM)
Else
ExpedM = Hv
End if
If Not EOF(CanalMoviv) Then
LeerMoviv(CanalMoviv, Exped, Nomb, Ape1, Ape2, Domic, Tipo)
Else
Exped = Hv
End IF
193
While Exped <> Hv Or ExpedM <> Hv
Select Case Exped
Case Is > ExpedM ' copiar maestro
Grabacion(CanalMaes, ExpedM, NombM, Ape1M, Ape2M, DomicM)
If Not EOF(CanalMalum) Then
LeerMaes(CanalMalum, ExpedM, NombM, Ape1M, Ape2M, DomicM)
Else
ExpedM = Hv
End if
Case Is < ExpedM
Select Case Tipo
Case "1" ' alta
Grabacion(CanalMaes, Exped, Nomb, Ape1, Ape2, Domic)
If Not EOF(CanalMoviv) Then
LeerMoviv(CanalMoviv, Exped, Nomb, Ape1, Ape2, Domic, Tipo)
Else
Exped = Hv
End IF
Case Else
' Error
LineaDet(Exped, Nomb, Ape1, Ape2, Domic, Tipo, "Actualiza")
If Not EOF(CanalMoviv) Then
LeerMoviv(CanalMoviv, Exped, Nomb, Ape1, Ape2, Domic, Tipo)
Else
Exped = Hv
End If
End Select
Case Is = ExpedM
Select Case Tipo
Case "1" ' alta, error
' Línea de detalle
LineaDet(Exped, Nomb, Ape1, Ape2, Domic, Tipo, "Alta")
If Not EOF(CanalMoviv) Then
LeerMoviv(CanalMoviv, Exped, Nomb, Ape1, Ape2, Domic, Tipo)
Else
Exped = Hv
End if
Case "2" ' baja, no se graba
If Not EOF(CanalMoviv) Then
LeerMoviv(CanalMoviv, Exped, Nomb, Ape1, Ape2, Domic, Tipo)
Else
Exped = Hv
End if
If Not EOF(CanalMalum) Then
LeerMaes(CanalMalum, ExpedM, NombM, Ape1M, Ape2M, DomicM)
Else
ExpedM = Hv
End if
Case "3" ' modificación, se graba el nuevo
Grabacion(CanalMaes, Exped, Nomb, Ape1, Ape2, Domic)
If Not EOF(CanalMoviv) Then
LeerMoviv(CanalMoviv, Exped, Nomb, Ape1, Ape2, Domic, Tipo)
Else
Exped = Hv
End if
If Not EOF(CanalMalum) Then
LeerMaes(CanalMalum, ExpedM, NombM, Ape1M, Ape2M, DomicM)
Else
ExpedM = Hv
End if
End Select
End Select
194
End While
40.8. Cierre
Para ello se utiliza la instrucción FileClose(Canal)
Y se cierra cada uno de los archivos que nos interesa.
Module Funciones
Public Function Respuesta() As Boolean
Dim Resp As String
Do
Console.WriteLine("Los datos son correctos S/N.")
Resp = Console.ReadLine()
Loop Until UCase(Resp) = "S" Or UCase(Resp) = "N"
Respuesta = UCase(Resp) = "S"
End Function
End Module
Module Menu
Sub Main()
Dim Cual As String
Do
Console.Clear()
Console.WriteLine("1 Crea amigos ")
Console.WriteLine("2 Listar amigos ")
Console.WriteLine("3 Grabar cambios de amigos ")
Console.WriteLine("4 Actualización ")
Console.WriteLine("5 Cambiar archivos ")
Console.WriteLine("6 Final ")
Console.WriteLine("Seleccione opción ")
195
Do
Cual = Console.ReadLine
Loop Until Cual > "0" And Cual < "7"
UltCod = ""
Canal = FreeFile()
FileOpen(Canal, "Amigos.sec", OpenMode.Output)
Do
196
Console.Clear()
Console.WriteLine("Grabar datos de los amigos.")
Console.WriteLine("Introduce el código del amigo")
Codigo = Console.ReadLine
Validar(Codigo, UltCod)
If Codigo <> "" Then
Datos.Codigo = Codigo
Console.WriteLine("Introduce el nombre.")
Datos.Nomb = Console.ReadLine()
Console.WriteLine("Introduce el primer apellido.")
Datos.Ape1 = Console.ReadLine()
Console.WriteLine("Introduce el segundo apellido.")
Datos.Ape2 = Console.ReadLine()
Console.WriteLine("Introduce el domcilio.")
Datos.Domic = Console.ReadLine()
Select Case Respuesta()
Case True
Grabacion(Canal, Datos, UltCod)
End Select
End If
Loop Until Codigo = ""
FileClose(Canal)
End Sub
End Module
2.- Realizar el listado de esos datos en pantalla.
Module Listado
Private Sub Cabecera()
Console.Clear()
Console.WriteLine("Listado de los amigos")
Console.WriteLine()
End Sub
Canal = FreeFile()
FileOpen(Canal, "Amigos.sec", OpenMode.Input)
Cabecera()
While Not EOF(Canal)
' lectura de un registro
With Datos
Input(Canal, .Codigo) ' código
Input(Canal, .Nomb)
Input(Canal, .Ape1)
Input(Canal, .Ape2)
Input(Canal, .Domic)
End With
' Línea de detalle
Visualizar(Datos)
Lin = Lin + 1
' Control de fin de página
Select Case Lin Mod 20 = 0
Case True
197
Console.ReadKey()
Cabecera()
End Select
End While
FileClose(Canal)
Console.WriteLine()
Console.WriteLine("Listado finalizado, pulse una tecla para seguir")
Console.ReadKey()
End Sub
End Module
3.- Cree ahora un archivo igual al anterior y añádale el dato tipo y grabe datos en él. El campo tipo será 1 para
nuevos datos, 2 para actualizar datos existentes, 3 para borrar datos.
Module Cambios
Private Sub Validar(ByRef Codigo As String, _
ByVal UltCod As String)
UltCod = ""
Canal = FreeFile()
FileOpen(Canal, "Cambios.sec", OpenMode.Output)
Do
Console.Clear()
Console.WriteLine("Grabar cambios de los amigos.")
Console.WriteLine("Si es nuevo, el código no ha de existir, en caso
contrario sí.")
Console.WriteLine("Introduce el código del amigo.")
Codigo = Console.ReadLine
Validar(Codigo, UltCod)
If Codigo <> "" Then
Datos.Codigo = Codigo
Console.WriteLine("Introduce el nombre.")
Datos.Nomb = Console.ReadLine()
Console.WriteLine("Introduce el primer apellido.")
Datos.Ape1 = Console.ReadLine()
Console.WriteLine("Introduce el segundo apellido.")
Datos.Ape2 = Console.ReadLine()
198
Console.WriteLine("Introduce el domcilio.")
Datos.Domic = Console.ReadLine()
Console.WriteLine("Introduce el 1 para Nuevo, 2 para Cambios, 3
para Borrar.")
Datos.Tipo = Console.ReadLine()
Select Case Respuesta()
Case True
Grabacion(Canal, Datos, UltCod)
End Select
End If
Loop Until Codigo = ""
FileClose(Canal)
End Sub
End Module
4.- Realice el proceso de actualización del primer archivo con los datos del segundo.
Module Actualizar
Private Sub LeerAmigos(ByVal Canal As Integer, _
ByRef Codigo As String, _
ByRef Nomb As String, _
ByRef Ape1 As String, _
ByRef Ape2 As String, _
ByRef Domic As String)
200
Proceso(Canal, CanalCamb, CanalNuevo)
Además los campos no llevan separadores entre si, y al final de los registros no existe marcas de final de
registro.
Evidentemente, a partir de aquí cada cual puede inventar lo que desee, pero esta es la forma adecuada de
hacerlo y como lo manejan los lenguajes de programación mas habituales.
Si el registro tiene 30 bytes de longitud, el registro número dos empezará en el byte 30.
Posición = 30 * (2 – 1)
Se considera que el primer byte disponible es el cero, y el primer registro válido es el cero.
201
La situación más lógica es utilizar la primera, hoy no tiene sentido utilizar el segundo sistema, pues sería
solaparse con un archivo indexado o con una base de datos.
En el primer caso, cada registro ocuparía siempre una posición distinta, no pueden haber dos códigos iguales.
En el segundo caso, al ser una dirección proporcionada por un algoritmo, se podría dar la situación de que
códigos distintos generarán direcciones iguales y hay que controlar esa posible duplicidad, de ahí que no tenga
sentido llegar a esa complejidad, cuando hoy se disponen de los sistemas de gestión de bases de datos, que nos
proporcionan esa tarea hecha.
Hay que tener también presente que el sistema de código posición tiene el inconveniente de que puede
generar mucho espacio vacío y poco aprovechado, por eso en la actualidad estos archivos se utilizan para
almacenar datos muy compactos, y que generan muy poco espacio libre en el archivo, Provincias, Países, etc.
41.6. Libre u ocupado.
Los archivos random son direccionables, cuando se abre, o se accede a
ellos, se puede grabar o leer indistintamente, esto provoca que necesitemos
saber si un registro al que accedemos está libre u ocupado, para saber que
hacer con él en el momento de la lectura.
Podemos hablar de dos sistemas principalmente para distinguir cuando
está libre u ocupado un registro.
El primero consiste en grabar a blancos todo el espacio que se prevé
utilizar para el archivo, utilizando el ASCII treinta y dos.
Si grabamos una marca para indicar libre u ocupado, eso implica que
podemos conservar los datos originales en el registro aunque se borre, eso es
bueno y malo, en función de lo que se tenga grabado, ya que implica que se
puede recuperar todo lo que hay, lo cual a lo mejor no interesa.
Como podemos ver no hay separación entre campos, ni entre registros hay marcas de
separación, de ahí que es imprescindible conocer el diseño del registro para su
utilización.
41.8. Cómo diseñar los registros.
En el ejemplo anterior se puede observar que se ha incluido el campo código
en el diseño del registro, pero eso no es necesario, si se utiliza el primero de los
sistemas de direccionamiento.
Si nosotros asumimos que el registro con el código siete lo colocamos en el
séptimo registro, cuando accedemos a él, lo localizamos porque sabemos su código, y
consecuentemente su dirección, por lo que grabar el código no representa ningún
problema, pero resulta redundante.
202
41.9. Utilización.
A partir de lo visto los pasos en la utilización de un archivo random son los siguientes.
Normalmente las instrucciones de lectura y grabación en un archivo random no son las mismas que las de un archivo secuencial.
Sin embargo la filosofía no cambia, abrir, usar y cerrar al final.
El acceso a los datos sin embargo si que sufre cambios, pues como hemos comentado antes, se puede leer o grabar indistintamente sin
necesidad de cerrar y volver a abrir el archivo.
Cuando leemos hemos de realizar los siguiente pasos.
42.2. Introducción.
En los pasos a seguir para el uso de los archivos random, no hay diferencias con los archivos secuenciales, los pasos son los mismos.
Abrir el archivo.
203
Acceder al mismo.
Finalizado el programa cerrarlo.
42.5. Lectura.
Una vez que tenemos definida la estructura del registro y hemos abierto el archivo, podemos leer un registro.
FileGet(Canal, Registro, Posicion)
Donde
Canal será la misma variable utilizada en la apertura.
Registro es la variable definida del tipo de la estructura creada.
Posición es la dirección donde deseamos realizar la lectura.
La variable registro una vez realizada la lectura, contendrá los datos resultantes de la misma bajo la sintaxis
Registro.Nom
Regisro.Direc
204
Comprobamos que está dentro de los límites y procedemos a leer.
FileGet(CanalAgenda, Reg, Posicion) ' Lectura
Hecha le lectura se comprueba su resultado
Select Case Reg.Nom <> StrDup(15, " ")
Comprobando en este caso que el campo nombre no esta en blanco.
Case True ' Ocupado
Visualiza() ' Visualiza registro
Si esta ocupado se procede a visualizar su contenido.
Case Else ' Código libre
Mensaje = "El código no existe"
End Select ' Campo siguiente
En caso contrario se deja seguir el programa, o se informa de que no existe el código, según corresponda.
El resto es ya informar de que el código está fuera de rango, o que el valor facilitado es incorrecto, en éste caso porque está vacío.
Pág. 42.1
La variable registro es la variable que contiene los datos que se van a grabar.
Un ejemplo de grabación podría ser:
Private Sub Grabacion()
Dim Posicion As Integer
' GRABACION
Posicion = CLng(Codigo)
Reg.Nom = Nombre
Reg.Dire = Direccion
Reg.Pobl = Poblacion
Reg.Prov = Provincia
Reg.Tele = Telefono
FilePut (Canal,Registro,Posicion)
MsgBox("Datos grabados", MsgBoxStyle.OKOnly, Me.Text)
End Sub
Los pasos son igual que en la lectura, porque de hecho el primer paso es una lectura de control.
Select Case Reg.Nom <> StrDup(15, " ")
Case True ' Ocupado
Visualiza() ' Visualiza datos, y seguimos
Case Else ' Código libre, dejamos que siga
End Select ' Campo siguiente
Una vez realizada la introducción de los datos, el siguiente paso es grabar el registro.
La grabación se haría como se ha visto antes, no hay ninguna diferencia.
Pág. 42.2
206
En el mensaje que emitimos y en que de alguna forma hay que conseguir que no se pueda seguir con la introducción de datos.
Cuando comprobamos que el registro está libre u ocupado,
Si esta ocupado podemos visualizar su contenido, y después actuar ya según nuestro estilo de hacer las
cosas.
Si está libre no deberíamos permitir que se siga con la introducción de datos.
Una vez realizada la introducción de los datos, el siguiente paso es grabar el registro, que se realizará siempre de la misma forma.
207
Pág. 42.3
208
Preguntamos si el registro leído esta ocupado.
Select Case Reg.Nom <> StrDup(15, " ")
Case True ' Ocupado
Visualiza() ' Visualizar datos y esperar
Case Else ' Código libre, dejamos que se continúe
End Select ' Campo siguiente
Si está ocupado visualizamos su contenido, se pasa al siguiente dato y se queda a la espera de que
el usuario seleccione la opción de borrar.
desee introducir un código nuevo, retrocediendo al campo código.
o continúe en el campo actual realizando por tanto una modificación.
Select Case Reg.Nom <> StrDup(15, " ")
Case True ' Ocupado
Visualiza() ' Visualizar datos y esperar
Case Else ' Código libre, dejamos que se continúe
End Select ' Campo siguiente
No se realiza ninguna acción, se pasa al siguiente campo y se asume que es un alta, un dato nuevo.
Si es un error porque quería acceder a un código existente, como la pantalla está vacía comprobará si es un error el código que ha
introducido y si no lo es podrá ver que el código no está grabado, porque no se visualiza nada.
Este criterio es fácil de comprender por quien utiliza el programa y fácil de implementar.
Tal cual, evidentemente con los cambios requeridos por una base de datos, se aplica para los mantenimientos de las tablas de la base de
datos.
42.12. Conclusiones.
El uso de un archivo Random permite direccionar los datos que se desean leer o grabar.
Conviene reservar o generar todo el espacio que va a utilizar el archivo con blancos para facilitar la gestión.
El asignar un espacio al archivo no significa que no pueda aumentar su capacidad de almacenamiento más adelante.
El sistema más cómodo de direccionamiento es relacionar el código del dato con la posición del mismo en el archivo.
Siempre conviene realizar una lectura de comprobación para saber cual es la situación del registro que vamos a tratar.
Actualizar es grabar un registro existente con datos.
Insertar es grabar un registro que no existe, con datos.
Borrar es grabar blancos en un registro que existe.
Tienen evidentemente un uso muy concreto actualmente, puesto que las aplicaciones se desarrollan todas en un entorno de base de
datos.
Module Procedimientos
Public Sub AbreFicheros()
' ABRIR FICHEROS
Canal = FreeFile() ' No se puede hacer en la creación
FileOpen(Canal, NomArchivo, OpenMode.Random, OpenAccess.Default, OpenShare.Shared, Len(Reg))
End Sub
Module Funciones
Public Function Respuesta(ByVal Texto) As Boolean
Dim Resp As String
Do ' pregunta recibida desde el programa,
Console.WriteLine(Texto) ' siempre es del tipo S/N
Resp = Console.ReadLine()
Loop Until UCase(Resp) = "S" Or UCase(Resp) = "N"
Respuesta = UCase(Resp) = "S" ' cierto si es afirmativa
End Function
Module Principal
Sub Main()
AbreFicheros()
Dim Cual As String
Do
Console.Clear()
Console.WriteLine("1 Crea archivo ")
Console.WriteLine("2 Inserta registro ")
Console.WriteLine("3 Leer registro ")
Console.WriteLine("4 Mantenimiento ")
Console.WriteLine("5 Copiar archivo secuencial ")
Console.WriteLine("6 Listar archivo ")
Console.WriteLine("7 Final ")
Console.WriteLine("Seleccione opción ")
Do
210
Cual = Console.ReadLine
Loop Until Cual > "0" And Cual < "8"
1. Realizar la generación de un archivo random con 20 registros de 56 bytes de longitud cada uno.
Desde el menú principal se llama al procedimiento
Case 1
CreaFichero()
El campo código no se graba, el sistema de direccionamiento se entiende que es campo de código como dirección del registro.
El campo código tendrá un valor entre 1 y 20.
Module Grabar
Public Sub InsertarRegistro()
Dim Codigo As String
Do
Console.Clear()
Console.WriteLine("Grabar datos de los amigos.")
Console.WriteLine("Introduce el código del amigo")
Codigo = Console.ReadLine
211
Module Leer
Public Sub LeerRegistro()
Dim Codigo As String
Console.Clear()
Do
Console.WriteLine("Leer los datos de los amigos.")
Console.WriteLine("Introduce el código del amigo")
Codigo = Console.ReadLine
Console.Clear() ' limpiar pantalla
Select Case Ocupado(Canal, Reg, Codigo)
Case True
With Reg
Console.WriteLine("Nombre {0}", .Nom)
Console.WriteLine("Dirección {0}", .Dire)
Console.WriteLine("Población {0}", .Pobl)
Console.WriteLine("Provincia {0}", .Prov)
Console.WriteLine("Teléfono {0}", .Tele)
End With
Case Else
Console.WriteLine("El código {0} no está útilizado.", Codigo)
Console.ReadKey()
End Select
Loop Until Codigo = ""
End Sub
End Module
Module Mantener
Private Function LeerCodigo() As String
Dim Codigo As String
Console.Clear()
Console.WriteLine("Leer los datos de los amigos.")
Console.WriteLine("Introduce el código del amigo")
Codigo = Console.ReadLine
Console.Clear()
LeerCodigo = Codigo
End Function
212
Reg.Tele = Space(9)
Graba = True ' cualquier acción acaba en grabar
End If
End Select
End Select
' si es alta, baja o modificación
Select Case Graba
Case True
Grabacion(Canal, Reg, Codigo)
End Select
End With
End Sub
La opción utilizada en las soluciones está basada en el uso de la consola, donde los recursos son algo más limitados, mientras que en los
ejemplos del tema se han planteado desde un entorno gráfico, lo que facilita la creación del ejemplo.
Si tomamos como punto de partida el ejemplo visto en el tema, podría quedar así el ejercicio.
Module Mantener
Private Sub Visualiza()
With Reg
Console.WriteLine("Nombre {0}", .Nom)
Console.WriteLine("Dirección {0}", .Dire)
Console.WriteLine("Población {0}", .Pobl)
Console.WriteLine("Provincia {0}", .Prov)
Console.WriteLine("Teléfono {0}", .Tele)
End With
End Sub
213
End Select
End Select
' si es alta, baja o modificación
Select Case Graba
Case True
Grabacion(Canal, Reg, Codigo)
End Select
End With
End Sub
Como puede verse, de alguna forma hay que introducir los datos, lo que hace que el código no sea todo lo adecuado que podría ser, sin
aumentar el volumen del mismo, para no hacerlo excesivamente largo.
5. Copie el diseño del tema de archivos secuenciales del archivo de Amigos, para un archivo Random.
Public Structure FilDatos
Public Codigo As String
Public Nomb As String
Public Ape1 As String
Public Ape2 As String
Public Domic As String
End Structure
6. Copie los datos del archivo secuencial en uno Random, asignándole como posición el código de cada uno de sus amigos.
Module CopiaSecuencial
Private Sub CreaFichero(ByVal Canal As Integer)
Dim Reg As FilDatosSec
Dim X As Integer
' Carga de blancos en los campos
Reg.Nomb = Space(15)
Reg.Ape1 = Space(15)
Reg.Ape2 = Space(15)
Reg.Domic = Space(30)
' Crear registros en blanco
For X = 1 To 20
214
FilePut(Canal, Reg, X)
Next
Console.WriteLine("Archivo generado.")
Console.ReadKey()
End Sub
CanSec = FreeFile()
FileOpen(CanSec, "Amigos.sec", OpenMode.Input)
CanRan = FreeFile()
FileOpen(CanRan, "Amigos.ran", OpenMode.Random, OpenAccess.ReadWrite, OpenShare.Shared, Len(RegRan))
CreaFichero(CanRan)
215
End While
Console.WriteLine("Listado finalizado")
Console.ReadKey()
End Sub
CanRan = FreeFile()
FileOpen(CanRan, "Amigos.ran", OpenMode.Random, OpenAccess.ReadWrite, OpenShare.Shared, Len(RegRan))
El entorno de una clase lo hemos visto anteriormente en modo reducido, pero se han dejado sentadas las formas y sus elementos.
El entorno en el modo consola es el que se ha estado utilizando en todos los ejemplos de los temas que se han visto con anterioridad.
El entorno gráfico es el que vamos a ver en los próximos temas.
43.3. Introducción.
Las herramientas de programación se han visto en su totalidad en los temas anteriores, sin embargo los programas que de ellas se
podían obtener eran algo pobres estéticamente, aunque si disponíamos de todo el potencial para realizar un buen programa.
La programación en un entorno gráfico está basada en la utilización de una herramienta de diseño gráfico en la cual se diseña la ventana,
el formulario, el entorno gráfico en el que se va a diseñar el aspecto gráfico del programa que va a utilizar el usuario.
216
Este entorno gráfico cambiará de un lenguaje a otro, pero en definitivas cuentas se compone de una serie de elementos gráficos que
poseen unas características tales que nos permiten crear un programa en el cual podamos solicitar y mostrar
datos al usuario de una manera estética más agradable e intuitiva que lo que permite
el modo consola.
Estos objetos dado que tienen que mostrarse con una serie de características
que permitirá su forma agradable a la vista, disponen de una serie de propiedades
que permite que se le pueda asignar colores, tamaños, posición adecuados dentro
del componente o ventana en el que lo mostraremos al usuario.
A su vez como necesitamos saber cuales son las intenciones de quien está
usando el programa con respecto al objeto en cuestión, dichos objetos disponen de
una serie de eventos que nos permite saber si el usuario usa el teclado, el ratón, o
algún otro evento que pueda ser necesario para dicho objeto.
Además también podemos necesitar que dichos objetos nos faciliten algún
tipo de acción propia del mismo, por lo que en la mayoría de los casos estos objetos
incorporan los métodos adecuados al destino para el cual están diseñados.
Estos objetos pueden agruparse en los que podríamos llamar básicos, y especializados.
Los elementos básicos son los que en un principio se crearon en las primeras versiones de programación para un entorno gráfico,
básicamente son los que se pueden ver en las imágenes del entorno de VB y de NetBeans que se ven en el documento.
Después se han ido creando una serie de elementos más especializados y que han facilitado en gran medida la creación de nuevos y
mejores programas.
Son objetos que podrían ser prescindibles en algunos casos, pero que sin embargo su aparición se agradece en gran medida en la
creación de nuevos programas.
Por otro lado existe la posibilidad de crear nuestros propios objetos para el uso en nuestros programas.
Pág. 43.1
De esta forma se podrá personalizar cada objeto a las necesidades del programa.
Ejemplos de propiedades pueden ser:
Nombre del objeto
Color de fondo
Tipo de fuente
Tamaño de fuente
Coordenada vertical y horizontal
Tamaño en altura y anchura
43.5. Eventos.
Se activan a medida que se produce alguna acción en el objeto en cuestión.
Muchos de los procedimientos y métodos que se escriban en nuestro programa tendrán como punto de inicio la activación de un evento.
Los eventos existentes están relacionados con
El teclado
El ratón
Los producidos por el sistema.
Si observamos los elementos que son capaces de producir los eventos, veremos que son precisamente los elementos que permiten
comunicarnos con la interface del programa.
Ejemplos de eventos pueden ser:
Pulsar tecla
Tecla abajo
Tecla arriba
Clic con el ratón
Doble clic con el ratón
43.6. Métodos.
Los métodos son la forma que tiene un objeto de poder realizar algún tipo de acción propia del mismo, como puede ser el provocar que
pase al fondo del orden de visualización, o pase a un primer plano.
43.7. Objetos.
Son los elementos con los cuales vamos a poder realizar el diseño gráfico de nuestro programa.
Podemos clasificarlos en varios tipos.
Mostrar información
Etiquetas
Grupos de objetos
Visualizar imágenes
Introducción de datos.
Cajas de texto
Grid, rejillas
217
Ordenes.
Botones para activar la acción a realizar por el usuario.
Opciones.
Para seleccionar una opción entre varias
Activar una opción en concreto
Selección de datos
Cajas desplegables
Listas de datos
Pero hay más, ya especializados en realizar tareas determinadas.
Impresión
Conexión con bases de datos
Menús y barras
Las contenedoras son aquellas que habitualmente contienen el menú de la aplicación y desde la cual se van cargando el resto de
ventanas que componen la aplicación.
Las contenidas son las ventanas, programas que se van ejecutando desde el menú de la aplicación.
Las ventanas independientes, son las que se ejecutan sin estar contenidas en ninguna otra.
2 Activación.
Una vez finalizada la fase de carga pasamos a la activación de la ventana, el programa a partir de ahí estará disponible para las acciones
del usuario.
La activación se produce cuando el formulario toma el foco, el sistema le presta atención.
En esta fase se puede actualizar el contenido de aquellos objetos que se cargan desde archivos, bases de datos por si han sufrido
cambios, y cualquier otro objeto susceptible de haber sufrido cambios en el tiempo que no ha estado activo.
El contenido de un formulario, programa, durante el periodo que pierde la atención del sistema, el foco, puede haber sufrido variaciones,
de ahí la necesidad o posibilidad de realizar la recarga de determinados objetos y actualizar sus contenidos.
La desactivación se produce cuando sin salir del programa, pasamos a la ejecución de otro programa, la ventana queda abierta pero no
hacemos nada en ella.
Cuando volvemos se vuelve a activar.
3 Ejecución.
Es el periodo que transcurre desde que se inicia hasta que se finaliza, descarga el formulario, es el periodo en el que se producirán todas
las acciones para las cuales ha sido diseñado el programa, y que en la mayoría de los casos arrancarán desde alguno de los eventos de los
objetos que componen la ventana, formulario.
4 Finalización.
Cerraremos archivos, conexiones con bases de datos.
En esta fase se dispone de la posibilidad de cancelar la acción de salida.
La finalización pasa por distintas fases, de tal forma que podemos cancelar la salida del programa si no se dan las condiciones
adecuadas, datos pendientes de guardar.
Pág. 43.3
218
Unidad 44. ¿Cómo se hace un programa? (I)
44.1. Objetivos del tema.
Conocer la forma en la cual se crea un programa, y la forma de abordarlo.
Intentar explicar como hacer un programa es algo harto complicado, ya que es una tarea muy personal de cada cual, y a cada uno le
gustará hacerlo de una forma o de otra, pero al menos vamos a intentar explicar una forma de hacerlo.
Por otro lado el ejemplo que se muestra es un programa de mantenimiento, es una visión de cómo se puede plantear el mismo, y claro
está que ni la mejor, ni la única.
Pero es un ejemplo válido de cómo se ha de enfocar un programa, y de cual es el punto de partida de las cosas que queremos hacer en el
mismo, así como de las distintas etapas a cubrir.
44.2. Introducción.
En un entorno gráfico se tiende a que cada uno de los programas esté compuesto por un formulario, aunque no es una regla, pero es
bastante habitual.
Por lo tanto cada una de las opciones que tenga una aplicación se puede asociar a un formulario, ventana.
Para crear un formulario, para crear un programa en un entorno gráfico, podemos partir de los siguientes criterios.
Un programa se compone de varios elementos:
El que se comunica con el usuario, la interfaz.
El que recibe esa información y la trata en función del destino de la misma, y de sus características.
El que se encarga, si procede, de grabar y recuperar información de un soporte de datos, dígase sistema
clásico de archivos, base de datos, etc.
A partir de aquí podemos empezar a crear los programas siguiendo esas premisas es decir, Crear el elemento de:
Comunicación con el usuario, interfaz.
Que trata los datos que en esa interfaz se muestran o se recogen.
De recuperación y grabación de los datos, si procede.
Después existe una serie de programas cuya interfaz es una simple pregunta de si se desea o no realzar un proceso, o los de capturar
una serie de datos para llegar a una conclusión o realizar un proceso basado en ellos, los denominados asistentes.
Especializados.
Impresión
Conexión con bases de datos
Menús y barras
Lo que hay que hacer ahora es pensar como queremos que sea nuestra ventana y pensar cuales
de estos objetos vamos a utilizar.
La fase de análisis y de diseño nunca es un tiempo perdido, suele ser al revés, una inversión en
tiempo.
Siempre es interesante dedicar un tiempo adecuado hasta obtener ese diseño que nos gusta, de
forma que podamos a partir de él obtener nuevos programas o simplemente ya no tengamos que pensar
en como hacerlos y podamos progresar más rápidamente en su creación.
Tenemos que pensar que en una aplicación siempre vamos a tener distintos tipos de programas y
debemos buscar una forma de diseño que nos permita crear interfaces lo más homogéneas y agradables
posibles para facilitar su posterior utilización y aprendizaje.
219
Después hay que darle forma con un estilo que nos resulte agradable.
Hay que cuidar los espacios, la distribución, los colores a utilizar y como será el texto a utilizar, tamaño y color.
Las ayudas que vamos a incorporar y su ubicación.
La estética es muy importante, de nuestros programas lo primero que se ve es la parte visual, por lo tanto hay que cuidar esa primera
impresión.
La ergonomía también:
Hay que crear las ventanas desde el centro del monitor hacia el exterior, de tal forma que el ojo del usuario
deba moverse lo menos posible, lo cual reduce el cansancio.
Los colores fosforescentes son inadecuados.
Los contrastes entre los colores han de permitir que se puedan ver adecuadamente los contenidos, fondo
negro y texto rojo no es correcto.
La intermitencia con determinados colores es peligrosa para algunas personas.
También se puede, o se debe, crear sistemas que permitan al usuario personalizar la aplicación.
Cuando tengamos acabada la parte de diseño de la interfaz, tendremos un espacio ocupado en el monitor, el que ocupa la ventana, si
este tamaño a una resolución habitual es suficiente no será necesario que el usuario maximice la ventana, por lo tanto podemos evitar poniendo a
false la propiedad maximizebox, el que se use ese botón de la ventana, lo cual evitará que se destroce el diseño que hemos realizado.
También podemos evotar que modifiquen el tamaño de la ventana arrastrando desde las esquinas, asignando a la ventana en la
propiedad FormBorderStyle el valor de fixedsingle.
Y por último para que la ventana quede centrada en la pantalla o en la ventana que la contenga del menú, podemos asignar a la
propiedad StartPosition el valor de centerscreen.
De esta forma conseguimos que no se pueda cambiar el diseño realizado por nosotros.
Pero no hay que olvidar que también se tiene que cuidar la parte ejecutiva.
Pág. 44.1
Para ello hemos de pensar a que queremos que reaccione nuestra aplicación y escribir los procedimientos adecuados.
1 Estética.
Por ejemplo para la ventana del ejemplo podemos escribir mensajes de ayuda para los campos de introducción de datos.
220
Campo02.Enter
Dim Cual As Integer
Cual = CInt(Strings.Right(CType(sender, TextBox).Name, 2))
MensajesCampo(Cual)
End Sub
Si queremos hacer lo mismo con los objetos de ordenes escribimos el procedimiento en cuestión para los mensajes.
Private Sub MensajesComando(ByVal Cual As Integer)
Select Case Cual
Case 1
Mensajes.Text = "Pulse para grabar los datos actuales."
Case 2
Mensajes.Text = "Pulse para borrar el registro actual."
Case 3
Mensajes.Text = "Pulse para cancelar los datos introducidos."
Case 4
Mensajes.Text = "Pulse para abandonar el programa."
End Select
End Sub
Y repetimos la misma acción que antes en los eventos que nos interesen.
Private Sub Comando01_Enter(ByVal sender As Object, ByVal e As
System.EventArgs) _
Handles Comando01.Enter, _
Comando02.Enter, _
Comando03.Enter, _
Comando04.Enter
Dim Cual As Integer = CInt(Strings.Right(CType(sender, Button).Name, 2))
MensajesComando(Cual)
End Sub
Y repetimos la misma acción que antes en los eventos que nos interesen.
Private Sub Comando01_MouseMove(ByVal sender As Object, _
ByVal e As
System.Windows.Forms.MouseEventArgs) _
Handles Comando01.MouseMove, _
Comando02.MouseMove, _
Comando03.MouseMove, _
Comando04.MouseMove
Dim Cual As Integer = CInt(Strings.Right(CType(sender, Button).Name, 2))
MensajesComando(Cual)
End Sub
Llegados a éste punto, lo único que tenemos resuelto es la parte estética de la aplicación, ahora hay que añadir el código que en realidad
resuelve el problema.
Pág. 44.2
Unidad 44. ¿Cómo se hace un programa? (III)
2 Solución al problema.
Empecemos por la parte de validación de los datos.
La validación se puede dividir:
Filtrado de datos en el teclado, eliminando aquello que no nos interesa.
Validación y control de los datos introducidos.
El filtrado de los datos que se introducen por teclado se basa en la implementación de código de filtrado de las teclas que se pulsan para
cada dato que se introduce en una caja de texto, evidentemente en el resto de objetos en los que no interviene la entrada de datos por teclado
eso no es posible.
Para ello partimos que los datos a introducir se pueden agrupar en dos tipos básicos, aunque se pueden crear tantos como se necesite
para personalizar la entrada de datos en cada campo.
Podemos crear una entrada de datos para campos numéricos y otra para alfanuméricos.
En el primero podemos filtrar toda tecla que no sea un valor entre 0 y 9, y podemos contemplar según corresponda “+”,”-“,”,”,”.”,”/”,”*”, etc,
adecuados al dato.
En los alfanuméricos podemos permitir todos los caracteres desde el espacio, ascii 32 hasta el 255, aunque también se puede reducir el
rango, todo dependerá del momento.
Para obtener buenos resultados debemos intervenir en los eventos de teclado.
Private Sub Campo01_KeyPress(ByVal sender As Object, _
ByVal e As
System.Windows.Forms.KeyPressEventArgs) _
221
Handles Campo01.KeyPress, _
Campo02.KeyPress
Dim Cual As Integer = CInt(Strings.Right(CType(sender,TextBox).Name,2))
TratarTeclado(Cual, e)
End Sub
En este evento se puede controlar cual es la tecla que se está usando y anular su uso o admitirlo.
Podemos hacerlo utilizando
Select Case Char.IsDigit(e.KeyChar) Or _
Char.IsNumber(e.KeyChar) Or _
Char.IsPunctuation(e.KeyChar) Or _
Char.IsLetter(e.KeyChar) Or _
Char.IsSeparator(e.KeyChar)
O utilizando
Select Case Asc(e.KeyChar)
Case 48 To 57 ' números solo, es código
Case 8, 13 ' retroceso e intro
Veamos un ejemplo completo.
Private Sub TrataTeclado(ByVal Cual As Integer, _ ByVal e As
System.Windows.Forms.KeyPressEventArgs)
Select Case Cual
Case 1 ' código
Select Case Asc(e.KeyChar)
Case 48 To 57 ' números solo es código
Case 8, 13 ' retroceso e intro
Case Else
' no vale
e.Handled = True
End Select
Case 2 ' nombre
Select Case Asc(e.KeyChar)
Case 32 To 255 ' es texto, se admite todo
Case 8, 13 ' retroceso e intro
Case Else
' no vale
e.Handled = True
End Select
End Select
End Sub
Es una versión reducida y ampliable.
Resuelta la parte de control de escritura hay que resolver la parte de control de lo que se ha escrito.
Para ello hay que actuar cuando se ha finalizado la introducción de los datos.
Normalmente se realiza solo para las cajas de texto, pues en los demás objetos no suele ser necesario.
El evento en el que hay que realizar el control debe ser el que se produce al abandonar el objeto, o en el que esté especializado para ello,
en el caso de VB es el validating.
Private Sub Campo01_Validating(ByVal sender As Object, _
ByVal e As
System.ComponentModel.CancelEventArgs) _
Handles Campo01.Validating, _
Campo02.Validating
Dim Cual As Integer
Cual = CInt(Strings.Right(CType(sender, TextBox).Name, 2))
Validacion(Cual, CType(sender, TextBox), e.Cancel)
End Sub
Y el procedimiento encargado de la tarea de control:
Private Sub Validacion(ByVal Cual As Integer, _
ByRef Campo As TextBox, _
ByRef Cancel As Boolean)
Cancel = False
Select Case Cual
Case 1
If Campo.Text <> "" Then
Campo.Text = Format(CInt(Campo.Text), "0000")
222
LeerRegistro(Campo01.Text, Cancel)
End If
Case 2
End Select
End Sub
En el ejemplo solo se transcribe el campo código, pero se controlan todos los campos de texto del programa, realizando control en
aquellos que es posible, ya que los datos como nombre, domicilios etc. , no es posible controlarlos y solo cabe realizar el pasar al siguiente dato.
Si en el control de lectura del código se produce un error la variable cancel tomaría el valor cierto y se anularía la transición de un campo
al siguiente.
El código del procedimiento de lectura ya dependerá del sistema de datos utilizado.
Pág. 44.3
223
"WHERE (Autores.Codigo = '" & Campo01.Text & "');"
La ejecución de este código arrancará del evento clic de uno de los botones de orden, de tal forma que al pulsar aceptar se ejecutará la
acción de grabado, actualización o inserción según proceda.
44.6. Complementos.
En los procedimientos que se han visto, se producen circunstancias como datos incorrectos, códigos que no existen, etc.
Estas situaciones conviene acompañarlas con mensajes informativos para que el usuario sepa porque se le rechazan determinados datos.
MsgBox("Datos grabados.", MsgBoxStyle.Information, Me.Text)
MsgBox("Datos inexistentes.", MsgBoxStyle.Information, Me.Text)
MsgBox("Error en actualización", MsgBoxStyle.Information, Me.Text)
Otro apartado es el control a nivel del programa del teclado
Private Sub Programa_KeyDown(ByVal sender As Object, _
ByVal e As
System.Windows.Forms.KeyEventArgs)
Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.Enter
SendKeys.Send(ControlChars.Tab)
Salir = False
Case Keys.Escape
Salida()
End Select
End Sub
Para el control de teclas como Escape, Intro, teclas de función y resto de teclas especiales.
Todas estas tareas se deben realizar en el evento de carga del formulario, load.
Después de esta fase de inicialización existe una fase activación que se produce cada vez que el programa recupera el foco de atención
del S. O., en esa fase se pueden actualizar los contenidos de algunos objetos que se cargaron en la fase inicial, por si se han realizado cambios
en las tablas de origen.
Private Sub Programa_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Me.Text = NomProgram
Canal = FreeFile()
FileOpen(Canal, _
My.Application.Info.DirectoryPath & NomFileProvi, _
OpenMode.Random, , OpenShare.Shared, Len(RegProvinc))
ConfigCampo(Me)
ConfigLiteral(Me)
ConfigMensajes(Me)
ConfigComando(Me)
End Sub
El evento en el que se realizaría la actualización de los cambios sería activated.
Pág. 44.4
224
De esta forma la salida del programa puede personalizarse en función de las necesidades del mismo, y controlar si hay datos pendientes
de guardar para realizar una confirmación de salida.
If DatosPendientes then
e.Cancel = MsgBox("Hay datos sin grabar, ¿desea salir?.",
MsgBoxStyle.YesNo) = MsgBoxResult.No
End if
Pág. 44.5
La opción más sencilla es la utilizar el denominado Label, es un objeto al cual en su propiedad de texto le
asignamos el contenido, el dato que deseamos mostrar con el tipo de fuente que deseamos que nos lo muestre.
En este objeto los eventos que se produce son mínimos pues en realidad una vez que se muestra la información en el mismo, su tarea en
el programa es reducida.
Aun y así, el número de los mismos es elevado, pero podríamos decir que en su mayoría son eventos de los que podríamos clasificar
como secundarios.
Pág. 45.1
225
Pueden visualizar imágenes, Image, o bien permitir que se pueda dibujar en ellos, PictureBox.
La utilización es sencilla
Hoja.Image = Image.FromFile(NombreArchivo)
Pág. 45.2
46.2. Introducción.
La captura de datos en un programa se realiza mayoritariamente a través del teclado.
Para ello se utiliza lo que se denomina la caja de texto, textbox o textfield, el nombre depende del lenguaje utilizado.
La escritura, la captura, no es solo recoger datos y asignarlos en el programa si no que es una filosofía de trabajo.
Lo que un usuario escribe normalmente tendrá que ser filtrado y verificado, por lo que se deberá realizar un control de los datos recibidos.
226
Además existe la posibilidad de realizar el control de teclado a nivel de la ventana, de tal forma que aquellas teclas como Intro, Escape,
Función, en fin teclas de control, se realizan en un primer nivel para todo el programa, y se deja para la caja de texto, el control de los datos de
cada campo.
46.4. Filtrado.
La tarea de filtrado de la información que se introduce en el programa debe empezar en el teclado.
Tanto en la caja de texto, como en los grid y cualquier objeto en el que intervenga el teclado, debemos intentar indicar cual es el número
máximo de caracteres que se van a introducir, con lo que ya conseguimos que se elimine la introducción incontrolada de datos por su longitud.
El siguiente paso es filtrar los datos que se van a teclear.
Los datos se pueden clasificar en dos grandes tipos
Numéricos
Alfanuméricos
Los campos numéricos serán datos que contengan caracteres del “0” al “9”, o del “0” al “9” y además “+-.,*/”.
Los campos alfanuméricos serán datos que contengan cualquier carácter que se pueda escribir, es decir desde el “0” al “9”, la “A” a la “Z”,
mayúsculas, minúsculas y acentuaciones.
Por lo tanto en los eventos de teclado hay que buscar cual es la forma de rechazar aquellos caracteres que no formen parte de esos
rangos según el campo en el que estemos ubicados.
Pág. 46.1
No siempre es posible realizar este control exhaustivo con los datos de un objeto, porque el objeto no dispone de los medios, eventos
adecuados para ese fin, en ese caso la validación habrá que realizar la validación en el momento de abandonar el objeto, perder el foco, y
siempre antes de realizar la grabación de los datos, rechazando la grabación si no se cumplen los requisitos que nosotros necesitamos.
Disponemos de los eventos validating y validated para realizar dicha tarea en cada objeto.
En estos eventos podremos comprobar los datos y cancelar la transición de un objeto al siguiente, si no se dan las circunstancias
adecuadas.
El datagrid es otro tema, es un objeto muy amplio y con una serie de características que requieren un tema a parte.
227
Se supone que además en la propiedad que índica la máxima longitud del campo, ésta se ha ajustado al tamaño del campo.
46.7. Validación.
Esta podría ser una opción de validación de un programa.
Arrancamos del evento validating del objeto en cuestión.
End Select
End Sub
Suponemos que el campo uno es un código y se realiza una lectura de comprobación sobre un sistema de almacenamiento, archivos,
bases de datos.
En este procedimiento cuando proceda la variable Cancel se activa a cierto, y de esta forma se cancela la transición de uno a otro objeto.
Un ejemplo más amplio de una validación.
Se puede observar que no siempre hay acción de control, y que solo hay acciones de formato en algunos casos.
Private Sub Validacion(ByVal Cual As Integer, _
ByRef Campo As TextBox, _
ByRef Cancel As Boolean)
Cancel = False
Select Case Cual
Case 1, 2, 3 ' Porcentaje de descuento
Select Case Campo.Text <> ""
Case True
Select Case InStr(Campo.Text, ".") > 0
Case True
MsgBox("El símbolo decimal ha de ser la coma.", _
MsgBoxStyle.Information, NomProgram)
Cancel = True
Case Else
Select Case CDbl(Campo.Text) < 0 Or CDbl(Campo.Text) > 100
Case True
MsgBox("Porcentaje de descuento incorrecto.", _
MsgBoxStyle.Information, NomProgram)
Cancel = True
Case Else
Campo.Text = Format(CDbl(Campo.Text), "00.00")
228
End Select
End Select
Case Else
Campo.Text = "0.0"
End Select
Case 4
Select Case Campo.Text <> ""
Case True
Campo.Text = Format(CDbl(Campo.Text), "#,##0.00")
Case Else
Campo.Text = "0.0"
End Select
Case 5, 6, 7, 8
Campo.Text = Format(CDbl(Campo.Text), "#,##0.00")
Case 9, 10
Campo.Text = Format(CInt(Campo.Text), "00")
End Select
End Sub
El resumen es sencillo:
Control de entrada de datos, longitud y selección de teclado.
Validación de lo que se ha introducido.
Para posteriormente proceder según lo requiera el programa.
Pág. 46.2
Unidad 47. Botones de órdenes (I)
47.1. Objetivos del tema.
Visto como se ha mostrado datos y se ha filtrado la introducción de los mismos, el siguiente paso puede ser como el usuario nos índica las
acciones que desea realizar en el programa, para ello vamos a ver el objeto button.
47.2. Introducción.
Toda ejecución de un programa tiene que ir precedida de una confirmación por parte del usuario, es un error grave el iniciar una acción a
partir de una suposición nuestra de lo que pensamos que se desea realizar, sin menospreciar a nadie, puesto que nosotros somos los primeros
como usuarios de un sistema informático, en algunas ocasiones el usuario es impredecible, por lo tanto no hay que dejar margen de dudas a la
hora de que nuestros programas ejecuten una acción determinada.
Si las acciones a realizar pueden ser en algún momento peligrosas, borrado o actualización de un elevado volumen de datos, una
segunda confirmación puede parecer excesiva, pero no deja de ser un segundo más, y una posible eliminación de un accidente.
La barra de herramientas es una agrupación de button.
47.3. Características.
Tienen poca historia, su colocación en la ventana debe responder a cuestiones de homogeneidad con
respecto a la aplicación en su conjunto, y a la estética del programa.
Pueden colocarse en horizontal o en vertical.
Si se da la circunstancia de tener botones para dos tipos de acciones distintas, conviene separarlos con
paneles para tenerlos agrupados por tipos.
Conviene ajustarlos en tamaño, para permitir que mediante la conveniente personalización puedan
albergar el texto en una fuente adecuada a los gustos o necesidades del usuario.
Pueden representarse
con texto,
acompañados de una imagen
solo una imagen.
Cada acción a la que el usuario deba responder debe tener asociado un botón.
En cualquier caso la mejor forma de utilizarlos es con el texto adecuado y acompañados de un pequeño
comentario en la zona adecuada de la ventana, para evitar cualquier tipo de dudas en la acción a elegir.
A la hora de crear la ventana, cuando vamos colocando los objetos de la misma, se les asigna
de forma automática un valor a la propiedad TabIndex, que es la que marca el orden en el que se van
ejecutando cada uno de los objetos, el orden en el que toman el foco.
Conviene tener la precaución de que el orden de ejecución de los botones no sea peligroso por
tomar la ejecución, el foco, un botón que pueda resultar peligroso.
Grabar datos de forma accidental puede resultar incomodo, borrar puede ser peligroso.
Estos objetos responden de forma automática a la pulsación de la tecla intro, sin necesidad de
escribir código adicional, igual que a las teclas de cursor.
En el momento de asignarles en la propiedad Text el texto a representar si colocamos el carácter “&” delante de una letra, esta se
convierte en una tecla activa al seleccionarla junto con la tecla Alt.
229
Podemos ver en la siguiente imagen como el texto de los botones incorpora una letra subrayada Cancelar, que es el resultado de
incorporar en la propiedad “&Cancelar”.
Pág. 47.1
Unidad 47. Botones de órdenes (II)
47.4. Utilización.
En un uso adecuado, en muchas ocasiones en función de la situación de la ejecución del programa, el button debe de estar deshabilitado.
Por ejemplo disponemos, como en el ejemplo un button para borrar un dato, si estamos grabando un registro nuevo, no tiene sentido tener
habilitado el botón de borrar, por lo tanto de podemos deshabilitar con
Borrado.Enabled = False
Y cuando se de la circunstancia de datos existentes tenerlo activado.
Borrado.Enabled = True
Podrían darse también la circunstancia de que no nos interese que esté a la vista, por el motivo que sea, pues podemos ocultarlo con
Borrado.Visible = False
Referente al tema de colores, se puede modificar el color de fondo y de la fuente, pero quizás no tenga demasiado sentido romper la
homogeneidad de los mismos, pero evidentemente es posible, las propiedades son BackColor y Forecolor.
Pág. 47.2
48.2. Introducción.
La selección de una entre varias opciones es inherente a la presentación de datos en un programa.
Para ello disponemos de varias posibilidades, el objeto RadioButton y el objeto CheckBox,
La diferencia entre ambos está en la forma en la que se realiza la oferta al usuario de la selección a realizar.
48.3. Características.
En el ejemplo que vemos le ofrecemos la posibilidad de elegir entre ventas o devoluciones, y de
obtener un informe en formato de gráfica o valorado.
Le ofrecemos dos situaciones distintas y cada una con una combinación de dos posibilidades.
En este caso el objeto adecuado es el radiobutton.
La diferencia entre uno y otro objeto estriba en como se ofrece al usuario las opciones.
Como podemos observar en los ejemplos, el radiobutton permite describir cada una de las opciones posibles para que se seleccione una
sola de ellas.
El checkbox permite describir una condición
la cual activaremos o no.
A nivel de representación existe la posibilidad de
utilizarlos de dos formas distintas, la habitual que es la
que vemos en los ejemplos, y otra en la que se sustituye
la imagen clásica redonda del objeto por la de un
pulsador que estará o no pulsado según su situación sea la de seleccionado o no, como podemos ver en la imagen de ejemplo, en la que el radiobutton
superior se ha configurado como button, e igual para el checkbox.
RadioButton.Appearance = Button
CheckBox.Appearance = Button
Además existe la posibilidad de incorporar una imagen en lugar de un texto, pero como siempre ocurre con las
imágenes, el problema no es ponerla, si no encontrar la imagen adecuada para expresar lo que se desea, la propiedad que
la gestiona es Image, y va relacionada con otras que permiten gestionarla de entre una lista, de forma que se puede cambiar la imagen en función
del estado del objeto.
230
Pero el problema es que estos formatos no son muy habituales, y puede llevar a equívocos al usuario del programa, por lo que lo que a
veces hacemos con la intención de facilitar el uso, se acaba convirtiendo en un problema.
Pág. 48.1
El valor de la propiedad checked, que es la que índica su estado, puede ser modificada por programa, pero eso implica que se activa el
evento clic, y hay que tenerlo presente, pues el código que tengamos escrito en dicho evento se ejecutaría aunque no haya intervenido el usuario.
Hay un matiz en éste objeto con respecto al radiobutton, y es que tiene un tercer valor además de cierto o falso, el cual no existe en el
radiobutton, que es algo así como indeterminado.
Los valores de las propiedades checked y checkstate son las que vemos.
Checked CheckState
True Checked
False UnChecked
Para comprender su funcionamiento lo mejor es probarlo con ejemplos y comprobar sus valores.
Su utilización dentro del programa es como el radiobutton.
Select Case CheckBox.Checked
Case True
Tratamiento
End Select
O bien:
If CheckBox.Checked Then Tratamiento
Los eventos disponen de las mismas características y se debe tener las mismas precauciones al asignar el valor de la propiedad checked
por programa, para evitar la ejecución imprevista del evento clic y de su código asociado.
Otro apartado a tener en cuenta es el tipo de condiciones a representar en cada momento con estos objetos para hacer un uso adecuado
de los mimos.
Si deseamos utilizar un checkbox para que se seleccione el sexo de una persona mostrando un checbox para cada posibilidad, se podrá
generar un error pues se pueden activar los dos o al revés, y eso no es posible, el objeto adecuado sería un radiobutton, que solo se puede
activar uno simultáneamente, ese es el tipo de precauciones que hemos de tener.
Pág. 48.2
49.2. Introducción.
Otra de las opciones dentro de un programa es la de ofrecer un bloque de datos de los que el usuario debe
seleccionar uno.
La ventaja de este sistema es que el usuario no debe conocer el código del dato que desea utilizar y además está
visualizando el dato que va a seleccionar, lo que reduce la posibilidad de errores.
49.3. Características.
El fondo, su utilización, en estos objetos es el mismo, son iguales en ese aspecto, pero la forma en la cual
representan los datos, siendo igual, se enfoca de forma distinta, ese es el cambio entre uno y otro.
El listbox muestra los datos en un área asignada, y en función del tamaño podrá o no representar un mayor
número de datos.
El combobox, el espacio que ocupa es mínimo, solo podemos cambiarlo en ancho, pero no en altura, y para visualizar el contenido del
mismo lo que se hace es desplegarlo cuando se utiliza al pulsar en el lateral.
En la imagen adjunta podemos ver los dos objetos, y el combobox en los dos estados, en situación normal y desplegado.
El listbox dispone de un segundo formato que puede facilitar su utilización en según que momentos, que es el CheckedListBox, es el
mismo objeto pero con la visualización de una casilla checked para cada elemento que hay en la lista, lo cual facilita la multiselección de datos en
la lista.
Así que desarrollamos una clase que nos permita generar un objeto que contenga los dos datos, el código y
la denominación.
Private Class Combo_List
232
Private Denom As String
Private Codig As String
' Inicialización del objeto
Public Sub New(ByVal Descripcion As String, _ ByVal Codigo As String)
Denom = Descripcion
Codig = Codigo
End Sub
' Devuelve la denominación
Public Overrides Function ToString() As String
Return Denom
End Function
' Devuelve el código
Public Function Codigo() As String
Return Codig
End Function
Public Function Denominacion() As String
Return Denom
End Function
End Class
1 Carga.
Una vez que disponemos de una clase que nos permite generar objetos de la forma que nos interesa a
nosotros, lo que queda es añadir objetos de esa clase a la colección de objetos del listbox o del combobox.
Dim Objeto As Combo_Lista
Objeto = New Combo_Lista(Denom,Codigo)
Combo.Items.Add(Objeto)
La explicación es la siguiente.
Dim Objeto As Combo_Lista
Definimos un objeto del tipo Combo_Lista, la clase que hemos creado antes.
Objeto = New Combo_Lista(Denom,Codigo)
Creamos una instancia del objeto incorporándole en su constructor el código y la denominación del dato que
deseamos incorporar al ComboBox o ListBox.
Combo.Items.Add(Objeto)
2 Recuperación.
El siguiente paso es recuperar los datos que hay en los mismos.
Podemos hacerlo con el siguiente código.
Dim Nacion As Combo_Lista
Nacion = CType(ComboBox.SelectedItem, Combo_Lista)
Codigo = Nacion.Codigo
La explicación es la siguiente.
Dim Nacion As Combo_Lista
Después solo queda asignar a la variable que nos interese el valor del código.
233
3 Cuantos tenemos,
Utilizando el método Count de las colecciones disponibles podemos saber cuantos elementos hay en la
colección de objetos, o en la de seleccionados.
Cuantos = Lista.Ítems.Count
5 Eliminar un elemento.
Disponemos de los métodos Remove y RemoveAt, en cualquiera de los dos objetos.
La sintaxis es la que sigue.
Combo.Items.RemoveAt(2)
Combo.Items.RemoveAt(Combo.SelectedIndex)
O bien
Lista.Items.Remove
Lista.Items.Remove(Lista.SelectedItem)
7 Recorrido.
La colección de objetos se puede recorrer con el siguiente ejemplo.
En este ejemplo se copia el contenido de un combobox en un listbox.
Recordemos que en un combobox solo puede haber seleccionado un elemento, por lo que no se puede recorrer la colección de elementos
seleccionados.
Dim X As Int16
ListaNueva.Items.Clear()
For X = 0 To Combo.Items.Count – 1
ListaNueva.Items.Add(Combo.Items.Item(X))
Next
O bien como colección.
Dim Elemento As Combo_Lista
ListaNueva.Items.Clear()
For Each Elemento In Combo.Items
ListaNueva.Items.Add(Elemento)
Next
El recorrido en la colección de objetos seleccionados es como sigue:
Dim Elemento As Combo_Lista
Combo.Items.Clear()
For Each Elemento In Lista.SelectedItems
ListaNueva.Items.Add(Elemento)
Next
El recorrido en la colección de objetos seleccionados del checkedlistbox es como sigue:
Dim Elemento As Combo_Lista
Combo.Items.Clear()
For Each Elemento In Lista.CheckedItems
ListaNueva.Items.Add(Elemento)
Next
8 Eventos.
Suele utilizarse los eventos clic y selectedindexchanged.
A partir de estos suele arrancar el tratamiento de los elementos que tenemos en la lista.
234
También hay que tener presente que podemos seleccionar por programa un elemento de estos objetos, y que eso provocará que se active
los eventos mencionados, por lo que el código asociado se ejecutará.
Pág. 49.3
Unidad 50. Los menús (I)
50.1. Objetivos del tema.
Vamos a ver los distintos menús en una aplicación.
50.2. Introducción.
Toda aplicación se compone de un número de programas que en su conjunto resuelven el problema para el cual se diseña la aplicación.
Una aplicación se puede dividir en varios tipos de programas.
Mantenimientos
Listados
Utilidades
Procesos
Los mantenimientos nos permiten poder realizar las labores de corrección y adición de datos en el sistema de archivos que utiliza la
aplicación.
Los listados permitirán que podamos obtener copia impresa o en pantalla de los datos que tenemos grabados en la aplicación.
En utilidades podremos agrupar aquellos programas de configuración, personalización, copias de seguridad etc.
Los procesos son realmente la parte de la aplicación que resolverá el problema para el cual se ha diseñado la misma.
Los procesos, que serán la parte más importante, a su vez interesa crearlos en un orden lógico de ejecución en la aplicación, y agruparlos
por temas, en lugar de crear una opción con muchas opciones.
La organización de los menús puede seguir el criterio expuesto o cualquier otro evidentemente, pero un criterio que dará siempre buenos
resultados, es el crear un orden de menú que el usuario que va a utilizar la aplicación comprenda, que esté relacionado con su entorno habitual de
trabajo, en caso contrario eso creará un rechazo de entrada por utilizar un lenguaje u organización extraño para él, y eso siempre es negativo.
50.3. Menús.
Dos tipos de menú, el que podemos encontrarnos en el formulario principal de la aplicación en la barra de menú, y el que se obtiene a
partir del botón secundario del ratón.
El primero es genérico para toda la aplicación, el segundo es personalizado para el objeto que se crea, podríamos decir que es una forma
más rápida de acceder a las mismas opciones.
El objeto que contiene el menú, puede utilizarse indistintamente en un formulario contenedor, o en formulario normal, no hay diferencia en
su uso, el objeto es del tipo MenuStrip, y lo encontraremos en la caja de herramientas en el bloque de menú y barras
de herramientas.
La creación es sencilla.
Colocamos, arrastramos, el objeto hacia el formulario y quedará colocado en la barra de objetos inferior de la
ventana de diseño de formularios y en el mismo formulario, le daremos un nombre adecuado después, en el ejemplo
BarraMenu
Colocado el objeto en el formulario, la forma más sencilla de crear el menú, es la de ir escribiendo en la zona que él mismo habilita
cuando está seleccionado.
Como podemos ver en la imagen, al colocar el ratón para escribir nos aparece inmediatamente la opción
de poder escribir posteriormente en la parte inferior o en la lateral.
De esta forma lo que hacemos es ir escribiendo los distintos elementos que componen el menú.
Pero eso es la parte visible, ahora hay que conectar esa opción del menú con nuestros programas.
Lo más sencillo es hacer doble clic en la opción que deseemos, de esa forma el entorno de VB, nos visualizará la ventana de código con
el evento clic del objeto seleccionado disponible para escribir nuestro código.
Private Sub ProcToolStripMenuItem_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _ Handles ProcToolStripMenuItem.Click
End Sub
Pero esto es solo la parte del evento ahora hay que añadir la parte de enlace con el programa.
Dim Programa As Form = New MantenRandom
Programa.MdiParent = Me
Programa.Show()
Me.CenterToParent()
Y todo junto quedaría
Private Sub ProcToolStripMenuItem_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _ Handles ProcToolStripMenuItem.Click
Dim Programa As Form = New NombreFormulario
235
Programa.MdiParent = Me
Programa.Show()
Me.CenterToParent()
End Sub
Pág. 50.1
La parte que se ha desarrollado es la de creación de un menú de forma habitual, que es la que nos
encontramos habitualmente, pero también podemos desarrollar un menú de forma algo más personalizada o
avanzada, como deseemos verlo.
Para ello podemos acceder con la opción de Editar Elementos, del menú contextual que se despliega al hacer
clic con el botón secundario del ratón, encima de la barra de menú que se ha añadido.
En esa opción se habilita una ventana con los objetos que componen el menú que hemos creado, o bien sin ningún elementos y de esa
forma podemos añadirlos pero con la ventaja de que podrán ser de uno de entre tres tipos posibles, el visto , MenuItem, o bien del tipo ComboBox
o TextBox, aunque hay que decir que son poco habituales, pero cada uno tiene su estilo a la hora de hacer los programas y cada programa a su
vez es un mundo, por lo tanto lo importante es conocer su existencia y usarlas cuando sea conveniente.
A continuación podemos ver la ventana que se abre al seleccionar dicha opción.
Sin embargo el menú del ejemplo es mínimo, para de verdad poder ver las características mejor uno hecho, y para ello podemos seleccionar la
opción de
Proyecto > Agregar Windows Form
Y seleccionar la opción de Formulario Primario MDI, el cual incorpora un menú por defecto, que podemos aprovechar para poder obtener
nuestras propias conclusiones, además, dispone de código escrito para algunas opciones que pueden ser interesantes y podemos aprovechar.
Cada opción del menú puede tener a su vez submenús, solo hace falta ir añadiendo objetos a la colección de elementos del menú. Para
ello en la ventana de parametrización hay que ir a la propiedad DropDownItems, y al seleccionarla se vuelve a abrir una ventana igual que la
actual pero con los elementos existentes en el submenú, o bien vacía para añadirlos.
En la ventana de parametrización, o personalización como deseemos llamarla, podemos encontrar la forma de añadir o quitar algunas características.
Asignar teclas de acceso rápido.
ShortCutKeys Definir las teclas de acceso rápido
ShowShortCutKeys Activar o no su visualización
ShortCutKeysDisplayString El texto que se visualiza para informar de las teclas
236
Si deseamos visualizar un vise de checked en la opción.
Checked Si se visualiza o no el vise del checked
CheckState El estado por defecto del checked.
Esta opción dependerá del valor de la propiedad DisplayStyle, pues si está en el modo texto e imagen, no se visualiza el checked, y al
revés.
Si deseamos visualizar un icono con la opción, si se activa hay que asignar que imagen se visualiza.
DisplayStyle Dispone de varios valores, texto, texto imagen, imagen y nada.
Image Icono que se visualizará.
TextImageRelatión Posición de la imagen respecto al texto.
Y aunque en el ejemplo de menú, a la opción le hemos asignado la carga de un programa, evidentemente en el evento podemos realizar
cualquier tipo de acción que podamos necesitar.
Pág. 50.2
Creado el menú el siguiente paso es asignarlo al objeto de la ventana con el cual queremos
interactuar.
Para ello seleccionamos el objeto en cuestión y acudimos a la propiedad ContextMenuStrip, al seleccionar la propiedad y
desplegar el combo podremos ver el nombre que le hemos asignado a nuestro objeto, lo seleccionamos.
Ejecutamos el programa y cuando hagamos clic con el botón secundario en el objeto que le hemos asignado el menú,
éste se desplegará.
Ahora hemos de asignarle a cada opción del menú el código correspondiente, para ello solo basta que seleccionemos el objeto en la barra
inferior de objetos en la vista de diseño de formulario, y hacer doble clic, aparecerá el evento y ahí asignamos nuestro código.
Private Sub Alta_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Alta.Click
MsgBox("Eureka, funciona", MsgBoxStyle.Information)
End Sub
El objeto que contiene los elementos de la barra de herramientas es del tipo ToolStrip, y está en el mismo bloque
de objetos que el menú.
Una barra de herramientas puede contener cualquier objeto de los habituales en el formulario.
Podemos comprobarlo fácilmente en el formulario MDI utilizado como ejemplo anteriormente, si accedemos a la opción de editar
elementos del menú contextual, bien a Items de la ventana de propiedades, - del objeto barra de herramientas -, podemos acceder desde ahí a la
ventana de personalización de la misma, y podemos comprobar que los objetos que podemos añadir a la barra son más amplios que en el caso
de la barra de menú.
Y ya solo queda seleccionar el objeto más adecuado para la acción que deseemos realizar y añadirlo a la barra.
237
La forma de asignarle código a cada uno de los objetos de la barra es idéntica que en el caso del menú, podemos hacer doble clic en el objeto y nos
aparecerá en la ventana de código el evento del objeto en cuestión.
Private Sub SaveToolStripButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles SaveToolStripButton.Click
End Sub
Y solo queda colocar el código adecuado.
Como habrá objetos que tendrán un equivalente en la barra de menú, en función del tipo de programa, lo adecuado es que la acción a
realizar este albergada en un procedimiento y se llame a dicho procedimiento desde ambos eventos.
Pág. 50.3
Unidad 51. Cuadros de diálogo (I)
51.1. Objetivos del tema.
Disponemos de una colección de objetos que son los mismos que se usa en las aplicaciones de Office y otras para abrir, guardar,
seleccionar impresoras etc., vamos a ver como utilizarlos.
51.2. Introducción.
Una excelente presentación de nuestra aplicación con muy poco esfuerzo, pues están resueltos, y se pueden adaptar a las necesidades
de cada momento pues las propiedades permiten su personalización.
Estos cuadros son
Abrir archivo.
Guardar archivo.
Seleccionar impresora.
Seleccionar color.
Seleccionar fuente.
Para utilizarlos hay que seguir la rutina de siempre, seleccionar el objeto en la caja de herramientas y arrastrarlo al formulario, como es un
objeto que no tiene una vista o colocación concreta en el formulario, veneremos como aparece una referencia al mismo en la barra de objetos
inferior.
A nivel de código es fácil de utilizar, en términos generales podríamos hablar de tres pasos:
Establecer las propiedades de personalización.
Visualizar con el método ShowDialog
Recoger el resultado.
A la hora de su uso, hay que tener presente que la elección del usuario no ha de ser siempre afirmativa, también pueden cancelar el uso
del mismo, esto hay que preverlo, se soluciona capturando la opción de cancelar.
Try
OpenFileDialog.ShowDialog()
PictureBox1.Image=Image.FromFile(OpenFileDialog.FileName)
Catch ex As Exception
End Try
Con este código se captura la situación de cancelar mediante el uso de la estructura de captura de errores Try.
En el ejemplo anterior, al contemplar en la respuesta que su acción se active por el valor de OK del resultado, el cancelar se asume de
forma indirecta, no valdrá OK la respuesta.
También podemos declarar una variable booleana
Dim Ok As DialogResult
y utilizarla para almacenar el resultado de la acción,
Ok = PrintDialog1.ShowDialog.OK
O bien directamente
If PrintDialog1.ShowDialog.OK then
End if
Algunos de estos objetos disponen de un evento OK.
Private Sub OpenFileDialog_FileOk(ByVal sender As Object, _
238
ByVal e As
System.ComponentModel.CancelEventArgs) _
Handles OpenFileDialog1.FileOk
‘ Acción a realizar.
PictureBox1.Image=Image.FromFile(OpenFileDialog.FileName)
End Sub
Y en su conjunto siempre disponemos de
Objeto.ShowDialog.OK
Los valores de DialogResult disponibles son:
DialogResult.Ok DialogResult.Cancel
DialogResult.Ignore DialogResult.Retry
DialogResult.Yes DialogResult.No
DialogResult.None
Este objeto es el clásico de Windows, aunque aquí veamos está versión, la misma puede cambiar en función de la versión instalada en
cada equipo.
La utilización es como vemos a continuación.
Try
OpenFileDialog.ShowDialog()
PictureBox1.Image=Image.FromFile(OpenFileDialog.FileName)
Catch ex As Exception
End Try
O también en el evento FileOk del objeto escribir la acción a realizar.
Private Sub OpenFileDialog_FileOk(ByVal sender As Object, _
ByVal e As
System.ComponentModel.CancelEventArgs) _
Handles OpenFileDialog1.FileOk
‘ Acción a realizar.
PictureBox1.Image=Image.FromFile(OpenFileDialog.FileName)
239
End Sub
Previamente se supone que hemos personalizado el objeto en función de nuestras necesidades, con el uso de las propiedades
adecuadas.
CheckFileExists Comprueba que el archivo existe antes de salir del cuadro de dialogo. En caso de producirse un error, se
visualiza una ventana que indica dicha circunstancia.
CheckPathExists Comprueba que la ruta especificada existe antes de salir del cuadro de dialogo. En caso de producirse un
error, se visualiza una ventana que indica dicha circunstancia.
DefaultExt Esta propiedad permite especificar una extensión predeterminada de nombre de archivo, como .txt o .doc,
que es añadida al nombre del archivo si el usuario no especifica ninguna.
Abrir.DefaultExt = “.Txt”
FileName Esta propiedad devuelve o establece el nombre del archivo que se ha seleccionado en el cuadro Abrir.
El nombre incluye la ruta de ubicación del archivo.
Si la cadena es de longitud cero, es que no hay archivo seleccionado.
Ruta = Abrir.FileName
Filter Especifica el tipo de archivos que se presentan en el cuadro de lista de archivos del cuadro de diálogo. Esta
propiedad permite proporcionar al usuario una lista de filtros que se pueden seleccionar cuando
se presente el cuadro de diálogo.
Para crear una lista de posibles filtros hay que utilizar el carácter ( | ) (ASCII 124) para separar los valores
descripción y filtro.
No se pueden incluir espacios en blanco delante o a continuación de la barra vertical, ya que dichos
espacios aparecerán en los valores descripción y filtro.
FilterIndex Una vez que se ha creado una lista de filtros de archivos, la propiedad FilterIndex nos permite indicar cual
es el que queremos que se visualice por defecto.
Abrir.FilterIndex = 2
Abrir.ShowDialog
Abrir.InitialDirectory = “C:\”
Pág. 51.2
240
El uso del objeto es similar a otros.
Configurar el objeto en función de nuestras necesidades y capturar después el resultado de su utilización.
Try
SaveFileDialog.ShowDialog()
Catch ex As Exception
End Try
O bien
Private Sub SaveFileDialog_FileOk(ByVal sender As Object, _
ByVal e As System.ComponentModel.CancelEventArgs) _
Handles SaveFileDialog1.FileOk
‘ Proceso a ejecutar
End Sub
El tener activadas las propiedades CheckFileExists y CheckPathExists, permite que se filtren las acciones erróneas, y se visualiza de
forma automática una ventana indicando la situación de error.
Las propiedades de éste objeto más usadas son:
CheckFileExists Comprueba que el archivo existe antes de salir del cuadro de dialogo.
En caso de producirse un error, se visualiza una ventana que indica dicha circunstancia.
CheckPathExists Comprueba que la ruta especificada existe antes de salir del cuadro de dialogo.
En caso de producirse un error, se visualiza una ventana que indica dicha circunstancia.
Sus valores son True / False
ValidateName
Controla que el nombre utilizado cumple sintácticamente y no contiene caracteres no
válidos.
Es necesario que esté activada a True si se desea utilizar OverWritePrompt.
DefaultExt Esta propiedad permite especificar una extensión predeterminada de nombre de archivo, como .txt o
.doc, que es añadida al nombre del archivo si el usuario no especifica ninguna.
Guardar.DefaultExt = “.Txt”
FileName Esta propiedad devuelve o establece el nombre del archivo que se ha seleccionado en el cuadro Abrir.
El nombre incluye la ruta de ubicación del archivo.
Si la cadena es de longitud cero, es que no hay archivo seleccionado.
Ruta = Abrir.FileName
Filter Especifica el tipo de archivos que se presentan en el cuadro de lista de archivos del cuadro de diálogo.
Esta propiedad permite proporcionar al usuario una lista de filtros que se pueden seleccionar cuando se
presente el cuadro de diálogo.
Para crear una lista de posibles filtros hay que utilizar el carácter ( | ) (ASCII 124) para separar los
valores descripción y filtro.
241
No se pueden incluir espacios en blanco delante o a continuación de la barra vertical, ya que dichos
espacios aparecerán en los valores descripción y filtro.
FilterIndex Una vez que se ha creado una lista de filtros de archivos, la propiedad FilterIndex nos permite indicar
cual es el que queremos que se visualice por defecto.
Guardar.FilterIndex = 2
Guardar.ShowDialog
Guardar.InitialDirectory = “C:\”
OverWritePrompt Indica si hay que avisar o no de la existencia de un archivo con el mismo nombre.
Solo se puede utilizar con ValidateName activado a True
OverWritePrompt = True / False
Title Esta propiedad permite presentar un texto en la barra de título del cuadro de diálogo.
El título predeterminado de un cuadro de diálogo es Guardar como
Pág. 51.3
De las que además printersettings alberga en su interior otro juego de parámetros modificables como son:
Copies
Duplex
FromPage, ToPage
IsDefaultPrinter
IsPlotter
IsValid
242
SupportsColor
Que en su conjunto permite obtener la personalización adecuada a nuestras necesidades de cada momento.
El uso de estas propiedades dependerá de la impresora que haya instalada.
243
Select Case TypeOf sender Is Control
Case True
Objeto = CType(sender, Control)
CuadroFont.Font = Objeto.Font
End Select
Por lo tanto el código completo, con las tres posibilidades vistas, quedaría:
' Preparación
CuadroFont.MinSize = 6
CuadroFont.MaxSize = 20
CuadroFont.AllowScriptChange = True
CuadroFont.AllowSimulations = True
CuadroFont.ShowEffects = True
' Asignar los datos del objeto de muestra
Select Case TypeOf sender Is Control
Case True
Objeto = CType(sender, Control)
CuadroFont.Font = Objeto.Font
End Select
' Visualización del objeto y asumir cambios si se pulsa Aceptar
If CuadroFont.ShowDialog = Windows.Forms.DialogResult.OK Then
Objeto.Font = CuadroFont.Font
End If
Pág. 51.5
52.2. Introducción.
Si observamos la caja de herramientas de VB, veremos que dispone de muchos más objetos de los que se han visto, todos no los vamos
a ver, porque son fáciles de usar, o porque se usan poco, pero algunos de ellos sí.
Quedan otros por ver, pero dado que su potencial se aprecia cuando se utilizan con una base de datos, los dejamos para más adelante.
Veamos algunos de ellos.
Barra de progresión.
Incremento numérico.
Pestañas, TabControl.
Calendario.
52.3. Barra de progresión.
La misión de este objeto es la ofrecer la sensación de funcionamiento adecuado de un programa cuando la ejecución del mismo es larga,
de tal forma que se perciba su progresión.
El funcionamiento del mismo se basa en un valor máximo, y un valor que progresa desde un punto inicial hasta el valor máximo.
En algunas ocasiones el problema estriba en como marcar el valor máximo para ajustar la ejecución a la proporción de la barra de
progresión, es cuestión de imaginación, pero lo que no tiene sentido es lanzar dos veces el proceso para averiguar este valor.
El tamaño que le asignamos al objeto es importante, pues el tamaño de los cuadritos de progresión cambian, y eso modifica la estética, y
la sensación de velocidad.
El objeto cuando no esta activo puede o debe estar oculto.
Las propiedades principales son
Maximum
Minimum
246
Value
Una forma alternativa de darle solución a distintas posibilidades de utilización de la interface es el uso de un objeto con pestañas,
TabControl.
Este objeto es un contenedor, y en el interior de cada pestaña podemos colocar cualquier objeto.
Por lo que podemos obtener el mismo resultado pero de una forma estéticamente mas aparente.
Cada una de las pestañas puede albergar en su interior los objetos necesarios para cada opción, lo que facilita la gestión.
Además al cambiar de pestaña los objetos se ocultan de forma automática, lo que facilita la programación también.
247
En la imagen podemos ver un ejemplo de tabcontrol, podemos observar como en la primera pestaña se ha colocado un Listbox, con la
propiedad Dock para que se ajuste al contenedor, y en la segunda pestaña se ha colocado un conjunto de label y textbox, para una introducción
por teclado.
Case Else
End Select
De ésta forma sabemos cual es la opción seleccionada y decidimos.
Pág. 52.2
Si activamos la opción ShowUpDown, cuando deseemos cambiar de fecha lo haremos con las flechitas
laterales, para cambiar los valores de día, mes y año.
Si su valor es falso, el formato será este, en el cual aparece la hoja de calendario, y que permite navegar.
podemos ejecutar
Informa01.Text = Calendario.Value.ToLongDateString
O bien
podemos ejecutar
Informa01.Text = Calendario.Value.ToShortDateString
Disponemos de distintos formatos, que podemos elegir en función de las necesidades.
Si deseamos que visualice la fecha actual,
Calendario.Value=New System.DateTime(Date.Now.Year, Date.Now.Month,
Date.Now.Day)
Si deseamos que visualice una fecha determinada, por ejemplo el día 5 del mes siguiente.
Calendario.Value = New System.DateTime(Date.Now.Year, Date.Now.Month + 1,5)
Disponemos de otro objeto similar que es el MonthCalendar, que es muy similar en su utilización, pero
permite marcar que se visualice el número de las semanas, seleccionar un rango de fechas, que se marque cual es la
fecha actual.
Pág. 52.3
53.2. Introducción.
Uno de los objetos habituales en los programas es el Gris, es una matriz con la que podemos visualizar datos y que actualmente dispone
de una serie de posibilidades muy amplia.
Esa misma amplitud de posibilidades es la que provoca cierta complejidad en su uso y su configuración.
.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader)
' El formato de tamaño de las celdas, influye sobre las de
' AllowUserToResize...
.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None
' El usuario puede o no cambiar el tamaño
' en alto o ancho de las filas o columnas
.AllowUserToResizeColumns = True
.AllowUserToResizeRows = False
End With
With DataGrid.ColumnHeadersDefaultCellStyle
' Asignar la fila y columna de estilo de cabecera
.ForeColor = Color.Balck
.BackColor = Color.Turquoise
250
.Alignment = DataGridViewContentAlignment.MiddleCenter
' Color fila seleccionada
.SelectionForeColor = Color.SpringGreen
.WrapMode = DataGridViewTriState.NotSet
End With
With DataGrid
.ColumnHeadersHeightSizeMode =
DataGridViewColumnHeadersHeightSizeMode.DisableResizing
.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.None
' Asignar estilo de selección de fila de cabecera por defecto de forma que
' el valor no se superponga a los valores de estilo de las celdas.
.RowHeadersDefaultCellStyle.SelectionBackColor = Color.Tomato
.RowHeadersDefaultCellStyle.BackColor = Color.Blue
.RowHeadersWidthSizeMode =
DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader
' Asignar el color de fondo para todas las filas y para forma
alternativa
.AlternatingRowsDefaultCellStyle.BackColor = Color.SkyBlue
.RowsDefaultCellStyle.BackColor = Color.White
End With
Después de una primera fase de configuración, que podrá ser más o menos estándar y según las necesidades de cada momento.
Puede haber una segunda fase de ajuste en función de cada programa.
With DataGrid
' Ajuste de ubicación
.Top = CInt(Me.Height * 0.05)
.Left = CInt(Me.Width * 0.05)
.Width = CInt(Me.Width * 0.9)
.Height = CInt(Me.Height * 0.6)
.Columns(2).DefaultCellStyle.Alignment=DataGridViewContentAlignment.MiddleRight
End With
Y como hay un sin fin de posibilidades, lo mejor es probar y llegar así al modelo que mejor se acople a las necesidades.
Pág. 53.2
1 Ventana de propiedades.
Seleccionamos la propiedad Columns y pulsamos en el botón para activar la ventana de configuración de dicha
propiedad.
Para los objetos ComboBox, si se van a enlazar con una tabla de la base de datos, hay que indicar en la propiedad DataPropertyName,
cual es el nombre del campo en la tabla de la base de datos, con el que se va a enlazar, para que se refresque su contenido al añadir una fila en
el grid.
Así sucesivamente con cada tipo de columna que se vaya a añadir.
De tal forma que al final quedará una ventana con todas las columnas que posee el DataGrid.
Pág. 53.3
Columna.Name = "Codigo"
Columna.HeaderText = "Código"
DataGrid.Columns.Add(Columna)
DataGrid.Columns.Item(1).Name = "Codigo"
DataGrid.Columns.Item(1).HeaderText = "Código"
DataGrid.Columns.Item(2).Name = "Titulo"
DataGrid.Columns.Item(2).HeaderText = "Título"
DataGrid.Columns.Item(3).Name = "Cantidad"
DataGrid.Columns.Item(3).HeaderText = "Cantidad"
DataGrid.Columns.Item(3).DefaultCellStyle.Alignment =
DataGridViewContentAlignment.MiddleRight
ConfigDataGrid(Me, DataGrid)
254
Tipo = "01"
Cod = "0001"
Denom = "Visual Basic Net 2005"
Cant = 10
Dim Fila() As Object = {Tipo, Cod, Denom, Cant}
' Este formato es válido solo cuando no esta enlazada a datos, DataSource
DataGrid.AllowUserToAddRows = True
Try
DataGrid.Rows.Add(Fila)
Catch ex As ArgumentException
MsgBox(ex.Message, MsgBoxStyle.Information, NomProgram)
End Try
DataGrid.AllowUserToAddRows = False
255
If Valor <> "" Then
Valor = Format(CInt(Valor), "000")
End If
DataGrid.CurrentCell.Value = Valor
Case 2
Valor = DataGrid.CurrentCell.Value.ToString
If Valor <> "" Then
Valor = Format(CInt(Valor), "##0.00")
End If
DataGrid.CurrentCell.Value = Valor
End Select
End Sub
También podemos optar por esta otra solución.
Private Sub Datagrid_EditingControlShowing(ByVal sender As Object, _ ByVal
e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) _
Handles Datagrid.EditingControlShowing
' Evitamos la columna del combo
Select Case DataGrid.CurrentCell.ColumnIndex
Case 0
Case Else
Dim CeldasGrid As TextBox = CType(e.Control, TextBox)
' Agregar el controlador de eventos para el KeyPress
AddHandler CeldasGrid.KeyPress, AddressOf Validar_Celdas
AddHandler CeldasGrid.Validating, AddressOf Validando
End Select
End Sub
El primer paso es en este evento ejecutar el código que vemos.
De esa forma conseguimos
Dim CeldasGrid As TextBox = CType(e.Control, TextBox)
Crear un objeto del tipo TextBox, o lo que es lo mismo nos lo llevamos al terreno que nos interesa.
De esa forma podemos usar los siguientes procedimientos, que ya tendremos escritos.
Private Sub Validando(ByVal sender As Object, _ ByVal e As
System.ComponentModel.CancelEventArgs) Validacion(2, CType(sender, TextBox),
e.Cancel)
End Sub
256
Dim X As Integer
Dim Fila As DataGridViewRow
For X = 0 To DataGrid.Rows.Count – 1
Fila = DataGrid.Rows(X)
Next
Y si deseamos recorrer las columnas de una fila.
Digamos que de la forma más clásica sería como el ejemplo que sigue:
Dim X As Integer
Dim Y As Integer
Dim Fila As DataGridViewRow
Fila = DataGrid.Rows(X)
For Y = 0 To Fila.Cells.Count – 1
Next
Y utilizando el bucle del tipo para cada objeto en la Fila, como vemos a continuación:
Dim X As Integer
Dim Fila As DataGridViewRow
Dim Celda As DataGridViewCell
Fila = DataGrid.Rows(X)
Fila = Tabla.Rows.Find(Lista02.SelectedValue)
TablaGrid.ImportRow(Fila)
Campos(0) = Fila.Item("Numero").ToString
Campos(1) = Fila.Item("Vencimiento").ToString
Campos(2) = Fila.Item("NomSocio").ToString
Campos(3) = Fila.Item("Importe").ToString
DataGrid.Rows.Add(Campos)
Tabla.Rows.Remove(Fila)
End Sub
Y el complemento sería el paso inverso que sería:
Private Sub Quitar()
Dim Fila As DataRow
Try
Fila = TablaGrid.Rows.Find(DataGrid.Item(0,
DataGrid.CurrentCellAddress.Y).Value.ToString)
Tabla.ImportRow(Fila) ' Traspasamos del grid a la tabla de
listbox
DataGrid.Rows.Remove(DataGrid.CurrentRow)
TablaGrid.Rows.Remove(Fila)
Catch ex As NullReferenceException
End Try
End Sub
El sistema se basa en la existencia de un objeto DataTable, para cada objeto, y lo que hacemos es compatibilizarlos, por decirlo de alguna
manera.
Si añadimos en la TablaGrid, quitamos de la Tabla del ListBox.
257
TablaGrid.ImportRow(Fila)
Tabla.Rows.Remove(Fila)
Y al revés, si añadimos a la tabla del ListBox, quitamos de la tabla del DataGrid.
Tabla.ImportRow(Fila) ' Traspasamos del grid a la tabla de listbox
TablaGrid.Rows.Remove(Fila)
Las tablas se pueden igualar a partir de una de ellas
CargaLista(Lista, Adaptador, Tabla)
TablaGrid = Tabla.Clone
De forma que creamos una estructura idéntica en las dos.
En el procedimiento ya existe todo el código necesario para cargar la tabla y los datos en el ListBox.
Pág. 53.7
1 Cargar el Combo.
Lo normal es que poseamos una tabla en la base de datos con el significado de los códigos que se graban en una tabla y se pueda cargar
el contenido de la tabla en el Combo para su utilización.
Pero también podría darse el caso de que pudiera ser una enumeración.
La carga de una tabla ya se ha visto en varios ejemplos, vamos a ver el de una enumeración por lo tanto.
Public Function CargaTablaCombo() As DataTable
Dim A As Enumeracion
Dim Tabla As New DataTable
Dim Col(1) As String
Dim X As Integer
Tabla.Columns.Add("Codigo")
Tabla.Columns.Add("Denom")
For Each A In [Enumeracion].GetValues(GetType(Enumeracion))
X = A
Col(0) = Format(X, "0") ' Option strict no deja hace la asignación
Col(0) = A
Col(1) = A.ToString
Next
Return Tabla
End Function
Una vez que se ha cargado la tabla podemos ejecutar el siguiente procedimiento en nuestro programa
Private Sub AnyadirCombo()
Dim ComboColum As New DataGridViewComboBoxColumn()
Tabla = CargaTablaCombo()
ComboColum.DataSource = Tabla
ComboColum.DataPropertyName = "Tipo"
ComboColum.DisplayMember = "Denom"
ComboColum.ValueMember = "Codigo"
ComboColum.HeaderText = "Tipo de servicio"
ComboColum.Name = "Tipo"
DataGrid.Columns.Insert(3, ComboColum)
End Sub
Este se encarga de colocar en la posición tres de las columnas del DataGrid
DataGrid.Columns.Insert(3, ComboColum)
El objeto que se crea en el procedimiento, hay que ver que no es un ComboBox, sino un objeto DataGridViewComboBoxColumn, pero es
solo un matiz, se usan igual.
2 Funcionamiento.
Una vez que disponemos de los dos procedimientos ya se puede ejecutar desde la configuración del DataGrid, el procedimiento de
adición del Combo
La explicación es la siguiente.
Tabla = CargaTablaCombo()
Cargamos la tabla que
258
ComboColum.DataSource = Tabla
Vamos a enlazar al Combo.
El enlace se produce a través de
ComboColum.DataPropertyName = "Tipo"
Y el valor “Tipo” es la columna de la instrucción SQL que posee el código que deseamos se visualice como descripción en el DataGrid, en
lugar de cómo valor numérico nada más.
ComboColum.DisplayMember = "Denom"
Es el campo del Objeto Tabla que se visualiza en el Combo, la tabla que hemos cargado con
Tabla = CargaTablaCombo()
Después indicamos cual es el campo de la tabla que posee el código que estamos representando en el Combo,
ComboColum.ValueMember = "Codigo"
Después damos el valor del texto que vamos a visualizar en la columna.
ComboColum.HeaderText = "Tipo de servicio"
Y el nombre del objeto que vamos añadir en el DataGrid
ComboColum.Name = "Tipo"
Por último colonos queda colocarlo en el DataGrid, bien en una posición en concreto:
DataGrid.Columns.Insert(3, ComboColum)
O bien hacer un Add
DataGrid.Columns.Add(ComboColum)
Como posiblemente tendremos columnas con valores que no es necesario visualizar, por motivos de la instrucción SQL, podemos
ocultarlas.
DataGrid.Columns(5).Visible = False
Para un funcionamiento correcto del Combo en el DataGrid, es necesario que exista el siguiente evento, con o sin código según interese.
Private Sub DataGrid_DataError(ByVal sender As Object,¨_
ByVal e As System.Windows.Forms.DataGridViewDataErrorEventArgs)
_ Handles DataGrid.DataError
End Sub
Sin este evento no funcionará adecuadamente.
Pág. 53.8
259
Indicamos el contenido en la cabecera.
CheckColum.HeaderText = "Forma de Pago"
Y lo añadimos
DataGrid.Columns.Add(CheckColum)
Y cuando carguemos los datos en función del valor de la columna de forma de pago, su valor cambiara de activado a desactivado.
260
La secuencia de impresión se basa en tres pasos básicos, a los que le corresponden otros tantos eventos.
Inicialización BeginPrint
Parte cíclica del listado PrintPage
Fin del proceso EndPrint
La introducción de los parámetros del listado, no deja de ser una interface gráfica, la cual desarrollaremos como cualquier otra.
La indicación de conformidad es la pulsación de un button, con el texto Aceptar o similar, y si procede porque el proceso lo requiere una
segunda conformidad para evitar un inicio accidental.
El inicio del listado implica la asignación de un objeto PrintDocument al destino del listado que será una impresora o un objeto de vista
previa.
DialogoImpresora.AllowSelection = False
DialogoImpresora.AllowSomePages = False
DialogoImpresora.PrintToFile = False
DialogoImpresora.PrinterSettings.Copies = 1
DialogoImpresora.Document = Hoja
If DialogoImpresora.ShowDialog() = DialogResult.OK Then Hoja.Print
Esto podría ser el código a ejecutar para un destino en una impresora.
Esta fase es de definición.
DialogoImpresora.AllowSelection = False
DialogoImpresora.AllowSomePages = False
DialogoImpresora.PrintToFile = False
DialogoImpresora.PrinterSettings.Copies = 1
DialogoImpresora.Document = Hoja
La línea que realmente lanza el listado es esta:
If DialogoImpresora.ShowDialog() = DialogResult.OK Then Hoja.Print
Hemos visto como lanzar el listado a partir de la selección que realiza el usuario en la ventana de impresión.
Ahora se trata de comprender el proceso en sí.
Hay que recordar que cuando se ejecuta esa línea, el programa no se para ahí, si no que sigue por un lado la impresión y por otro lado el
programa, lo mejor para entenderlo, es colocar un punto de ruptura con F9, en la línea siguiente a la de inicio de listado.
Aquí es donde se van lanzando cada una de las líneas que componen el listado.
Los pasos que se han nombrado no tienen nada que ver con un lenguaje de programación.
Son el orden natural de un proceso de impresión.
261
Por lo que aunque cambie el lenguaje de programación, los pasos serán iguales.
Todos no intervienen siempre, pero son esos, por lo tanto lo lógico es crear un procedimiento para cada una de las distintas fases.
Asignemos ahora los eventos anteriormente expuestos a las fases del listado.
Inicialización BeginPrint
–Inicio de proceso.
Veamos primero los distintos procedimientos, para así ya después solo nombrarlos por su nombre.
Pág. 54.1
Vamos a ir describiendo cada uno de ellos de forma independiente, para luego verlos de forma conjunta.
Empecemos por el inicio de proceso.
Veamos ahora la línea de identificación.
Public Sub LineaIden(ByRef Cy As Single, _ ByRef ContPag As Integer, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs)
ContPag = ContPag + 1
Cy = CLng(Alto * 0.02) ' Avance de línea con respecto al borde superior
Cx = CLng(Ancho * 0.05)
Texto = NombreAplicacion & " Pag: " & ContPag & " " & Now
e.Graphics.DrawString(Texto, Fuente, Pincel, Cx, Cy)
Cy = Cy + Fuente.Height ' Avance de línea
End Sub
Esto creará una línea al inicio de cada hoja que permitirá saber fecha y hora de cuando se hizo el listado, que en muchas ocasiones es
importante.
Además podemos colocar el nombre de la aplicación, el número de hoja, etc.
Pág. 54.2
Fuente = Est_Cabecera
Cy = Cy + Fuente.Height ' Separación del título
While X < UBound(TextoCab)
e.Graphics.DrawString(TextoCab(X).Texto, Fuente, Pincel,
TextoCab(X).Cx, Cy)
X = X + 1
End While
Cy = Cy + Fuente.Height ' Avance de línea
Cy = Cy + 10 ' Línea de subrayado
e.Graphics.DrawLine(Lapiz, CInt(Ancho*0.05), Cy, CInt(Ancho*0.95), Cy)
End Sub
Observemos el siguiente fragmento de código:
While X < UBound(TextoCab)
263
e.Graphics.DrawString(TextoCab(X).Texto, Fuente, Pincel,
TextoCab(X).Cx, Cy)
X = X + 1
End While
En el bucle vemos como a partir del contenido del vector TextoCabecera, colocamos el contenido de la Cabecera de detalle.
TextoCab(X).Texto
Y utilizamos
TextoCab(X).Cx
Para colocar en el punto adecuado dicho texto.
Esta es la forma de asignar los datos al vector en el que creamos el contenido de los campos del listado:
' Campos del listado
TextoCabecera(0).Texto = "Num. "
TextoCabecera(1).Texto = "Servicio "
TextoCabecera(2).Texto = "Fecha "
TextoCabecera(3).Texto = "Hora "
TextoCabecera(4).Texto = ""
Después lo usamos para calcular la coordenada X de cada campo:
' Bucle de cálculo
While X < UBound(Textocabecera)
Textocabecera(X).Cx = Cx
' Ancho del texto
AnchoString =
Grafico.MeasureString(StrDup(Len(Textocabecera(X).Texto), "n"), Fuente)
Cx = CLng(Cx + AnchoString.Width)
X = X + 1
End While
Este cálculo se realiza en base a una fuente definida para la línea de detalle.
' Fuente a utilizar
Fuente = New Font("Arial", 12, FontStyle.Italic)
El valor inicial del lateral del listado será:
' Margen lateral
Cx = CLng(Hoja.DefaultPageSettings.Margins.Left)
De esta forma conseguimos tener un punto donde colocar cada uno de los campos en el objeto de listado.
Pág. 54.3
Unidad 54. Impresión (IV)
El procedimiento completo es el que sigue:
Private Sub ConfigCabeceraCodigo(ByRef Textocabecera() As CabecDetalle)
Dim Fuente As Font
Dim Lapiz As New System.Drawing.SolidBrush(System.Drawing.Color.Black)
Dim AnchoString As New SizeF
Dim Formato As New System.Drawing.StringFormat
Dim Cx As Long
Dim Grafico As Graphics = Me.CreateGraphics
Dim X As Integer
Fuente = Est_Lin_Det
Fuente = Est_Cabecera
D = Strings.Left(D, 2) & "-" & Strings.Mid(D, 3, 2) & "-" &
Strings.Right(D, 4)
H = Strings.Left(H, 2) & "-" & Strings.Mid(H, 3, 2) & "-" &
Strings.Right(H, 4)
Cx = CSng(e.PageBounds.Width * 0.07)
e.Graphics.DrawString("Nombre del sócio ", Fuente, Pincel, Cx, Cy)
Cx = CSng(e.PageBounds.Width * 0.25)
e.Graphics.DrawString(" : " & Texto, Fuente, Pincel, Cx, Cy)
Cy = Cy + Fuente.Height
Cx = CSng(e.PageBounds.Width * 0.07)
e.Graphics.DrawString("Desde ", Fuente, Pincel, Cx, Cy)
Cx = CSng(e.PageBounds.Width * 0.25)
e.Graphics.DrawString(" : " & D, Fuente, Pincel, Cx, Cy)
Cy = Cy + Fuente.Height
Cx = CSng(e.PageBounds.Width * 0.07)
e.Graphics.DrawString("Hasta ", Fuente, Pincel, Cx, Cy)
Cx = CSng(e.PageBounds.Width * 0.25)
e.Graphics.DrawString(" : " & H, Fuente, Pincel, Cx, Cy)
Cy = Cy + Fuente.Height
End Sub
Que llamaríamos desde el procedimiento de cabeceras.
Private Sub Cabeceras(ByRef Cy As Single, _
265
ByVal e As
System.Drawing.Printing.PrintPageEventArgs)
Pág. 54.4
Fec = Reg.Item("Fec").ToString
Fec=Strings.Right(Fec,2) & "-" & Strings.Mid(Fec,5,2) & "-" &
Strings.Left(Fec, 4)
With Reg
e.Graphics.DrawString(.Item("Reserva").ToString,Fuente,Pincel,TextoCabecera(0)
.Cx, Cy)
e.Graphics.DrawString(.Item("Denom").ToString,Fuente,Pincel,TextoCabecera(1).C
x, Cy)
e.Graphics.DrawString(Fec, Fuente, Pincel, TextoCabecera(2).Cx, Cy)
e.Graphics.DrawString(.Item("Hora").ToString,Fuente,Pincel,
TextoCabecera(3).Cx, Cy)
End With
End Select
Este es el código completo, queda por ver
Public Sub FinImpresion(ByRef Cy As Long, _
ByVal e As
System.Drawing.Printing.PrintPageEventArgs, _
ByVal Texto As String)
266
e.Graphics.DrawString(Texto, Fuente, Pincel, Cx, Cy)
Cy = Cy + Fuente.Height ' Avance de línea
End Sub
Y el de Inicio de listado, que puede ser igual o con los cambios que se necesiten.
Vistos todos los procedimientos por separado, necesitamos ver ahora como encaja todo esto ahora.
54.6. El conjunto.
Hemos visto anteriormente que el listado es
Inicialización BeginPrint
Parte cíclica del listado PrintPage
Fin del proceso EndPrint
Veamos ahora cada una de esas fases, con los procedimientos que hemos visto anteriormente.
1 Inicialización, BeginPrint.
En esta fase podemos colocar el siguiente código, dependerá todo evidentemente del tipo de programas que necesitemos enfocar.
Private Sub Hoja_BeginPrint(ByVal sender As Object, _
ByVal e As
System.Drawing.Printing.PrintEventArgs) _
Handles Hoja.BeginPrint
Hoja.DefaultPageSettings.Landscape = False
ConfigCabecera(TextoCabecera)
End Sub
Pág. 54.5
Codigo = Lista01.SelectedValue
CadenaSQL="SELECT
Reserva,Socio,Fecha,Servicio,Numero,Hora,Reservado,Estado,"& _
"Socios.Codigo, " & _
267
"CONCAT(Socios.Apellidos,' ',Socios.Nombre) AS NomSocio, " &
_
"Servicios.Codigo, Servicios.Denominacion " & _
"FROM Reservas " & _
"INNER JOIN Socios ON Socios.Codigo = Socio " & _
"INNER JOIN Servicios ON Servicios.Codigo = Servicio " & _
"WHERE ((Socio = '" & Codigo & "') AND " & _
"(Fecha >='" & FechaD & "') AND " & _
"(Fecha <='" & FechaH & "'))" & _
"ORDER BY Reserva "
Tabla = CargaTablas(Conexion, CadenaSQL, "Reserva")
Hoja.DefaultPageSettings.Landscape = False
ConfigCabecera(TextoCabecera)
End Sub
En pocas palabras, en BeginPrint se ha de ejecutar aquella parte del programa que solo ha de ejecutarse una vez al inicio del mismo.
Salvada la parte inicial del listado, el siguiente paso es la parte cíclica, repetitiva, del mismo, el evento PrintPage.
2 Parte cíclica del listado, PrintPage.
El siguiente ejemplo está basado sobre un archivo random, pero eso es anecdótico básicamente.
Private Sub Hoja_PrintPage(ByVal sender As Object, _
ByVal e As
System.Drawing.Printing.PrintPageEventArgs) _
Handles Hoja.PrintPage
269
Dim Cy As Single ' Coordenada vertical
Dim Cabec As Boolean = True
Posición, se ha conservado su nombre por motivos didácticos, además no está fuera de lugar tampoco, es el contador que nos permite
progresar en la colección de filas de la tabla.
Se define estático, para preservar su valor con respecto a las reentradas en el procedimiento después de generar páginas nuevas.
While Posicion < Tabla.Rows.Count
El control del bucle, mientras hayan filas, posición menor que el número de filas.
Reg = Tabla.Rows(Posicion)
Fila, registro a procesar.
If Cabec Then ' Cabeceras
Cabeceras(Cy, e)
Cabec = False
End If
El control de cabeceras, cuando se produce la reentrada, pero si no se entra en el bucle no se ejecutan.
LineaDetalle(Reg, e, Cy) ' Línea de detalle
Impresión propiamente dicha de la línea de detalle.
Posicion = Posicion + 1 ' Incremento del contador
270
Hay que tener presente un matiz, antiguamente las impresoras no eran “””direccionables”””, se imprimía línea a línea en la impresora
directamente, por lo tanto había que respetar ese orden secuencial de trabajo, que no se podía saltar.
Actualmente se imprime sobre un objeto, sea el que sea, y como se llame, que en realidad está en memoria, y trabajamos con las
coordenadas x, y, horizontal y verticalmente, de tal forma que como la impresión se realiza al enviar la hoja a la impresora, podemos imprimir
cualquier parte del listado en el momento que deseemos, otra cosa es que por lógica, lo hagamos de una manera más o menos ordenada.
Dicho de otra forma, podríamos dividir la hoja en zonas, y hacer cada paso en el orden que deseemos.
A partir de esta situación, cuando tengamos que realizar un impreso, en el que estará el membrete de la empresa, la zona de
identificación del documento, el cliente al que va dirigido etc., se pueden crear procedimientos independientes para cada una de estas tareas.
Lo único que hay que tener presente es que cada uno tendrá una zona de la hoja asignada, y ahí es donde habrá que posicionarse para
su impresión.
Por lo tanto podríamos encontrarnos en el evento BeginPrint con algo similar a esto.
Private Sub Hoja_BeginPrint(ByVal sender As Object, _
ByVal e As
System.Drawing.Printing.PrintEventArgs) _
Handles Hoja.BeginPrint
Configuracion()
Empresa(e, Cy, Reg)
Cliente(e, Cy)
IdentificacionAlbaran(e,Cy)
End Sub
A continuación disponemos de un ejemplo de dicho tipo de procedimientos.
Public Sub Empresa(ByVal e As System.Drawing.Printing.PrintPageEventArgs,
_
ByRef Cy As Single, _
ByVal RegParam As DataRow)
Cx = CLng(e.PageSettings.PaperSize.Width * 0.05)
LeerProvincia(Conexion, Mid(RegParam.Item("CodPos").ToString, 1,
2),Provinc, "")
With Reg
e.Graphics.DrawString(.Item("Descripcion").ToString, Fuente, Pincel,
Cx, Cy)
Cy = Cy + Fuente.Height
e.Graphics.DrawString(.Item("Domicilio").ToString, Fuente, Pincel, Cx,
Cy)
Cy = Cy + Fuente.Height
e.Graphics.DrawString(.Item("Poblacion").ToString, Fuente, Pincel, Cx,
Cy)
Cy = Cy + Fuente.Height
e.Graphics.DrawString(.Item("CodPos").ToString & " " & Provinc,
Fuente, Pincel, Cx, Cy)
Cy = Cy + Fuente.Height
e.Graphics.DrawString("N.I.F. " & .Item("NIF").ToString, Fuente,
Pincel, Cx, Cy)
Cy = Cy + Fuente.Height
e.Graphics.DrawString("Tel. " & .Item("Telefono").ToString, Fuente,
Pincel, Cx, Cy)
Cy = Cy + Fuente.Height
e.Graphics.DrawString("Fax " & .Item("Fax").ToString, Fuente, Pincel,
Cx, Cy)
Cy = Cy + Fuente.Height
271
e.Graphics.DrawString(" " & .Item("EMail").ToString, Fuente, Pincel,
Cx, Cy)
End With
Cy = Cy + Fuente.Height
End Sub
La ubicación en la hoja viene marcada por los valores que asignemos en estas variables al inicio del procedimiento.
Cy = CLng(e.PageSettings.PaperSize.Height * 0.05)
Cx = CLng(e.PageSettings.PaperSize.Width * 0.05)
En esta línea indicaremos donde empezamos a imprimir los datos, en este caso de la empresa.
Cy = CLng(e.PageSettings.PaperSize.Height * 0.05)
Cx = CLng(e.PageSettings.PaperSize.Width * 0.05)
Si deseamos que esta impresión fuera la los datos del cliente, podríamos iniciar con
Cy = CLng(e.PageSettings.PaperSize.Height * 0.08)
Cx = CLng(e.PageSettings.PaperSize.Width * 0.6)
Es decir más bajo y más a la derecha.
Así con cada bloque de datos que se envíen a imprimir.
Por ejemplo la identificación de un albarán podría ser
Cy = CLng(e.PageSettings.PaperSize.Height * 0.15)
Cx = CLng(e.PageSettings.PaperSize.Width * 0.08)
Empezaría siempre en un quince por ciento del alto, y a un ocho por ciento del ancho.
54.8. Acabando.
Los ejemplos aquí expuestos, son versiones didácticas, y que en algunos casos están reducidas.
Como último, el motivo de que exista en la estructura de datos, un elemento siempre con valor nulo, es para obtener en los casos que
fuera necesario, la coordenada X del extremo derecho del listado, que se podría hacer de cualquier otra forma, pero esta es una más.
Evidentemente el uso de Crystal Reports es muy cómodo, la ventaja de hacerlo de esta forma es la de controlar el sistema, y poderlo
personalizar como se desee, y además llegar donde de otra forma a lo mejor no sería posible hacerlo.
Pág. 54.8
55.2. Introducción.
El acceso a una base de datos en VB se ha diseñado mediante el uso de dos tipos de objetos.
Unos que son independientes del tipo de base de datos que se vaya a utilizar, como son las tablas de datos.
Otros que son propios de cada una de los distintos tipos de bases de datos que VB permite gestionar.
Además existe una clase que permite acceder a cualquier base de datos que contemple el acceso mediante ODBC.
55.3. Utilización.
Para acceder a una base de datos necesitaremos disponer de la clase que realice la gestión de la misma.
En el caso de Access esta sería OLEDB, que pertenece a la clase System.Data
En el caso de SQLServer esta clase sería SQLClient, que pertenece también a la clase System.Data.
Para MySQL, la clase es MySQL, MySQL.Data.
En cualquier caso, siempre hemos de asegurarnos que en la ventana de referencias a objetos disponemos de la clase en cuestión
instalada.
En la ventana siguiente podemos ver la referencia a la clase de MySQL.
272
55.4. Tipos de objetos.
Hay dos tipos de objetos en la gestión de la base de datos.
Los que tenemos albergados dentro de la clase System.Data, como son
Columnas.
Filas
Tablas
DataSet
Relaciones
Restricciones.
Y los que tendremos dentro de la clase correspondiente al tipo de base de datos utilizada.
Conector
Adaptador
Lector
Comando
CommandBuilder
En el primer bloque de objetos, si observamos son objetos que albergan la estructura de la base de datos.
En el segundo son objetos que permiten la gestión de la misma.
2 Almacenamiento.
Los objetos de almacenamiento son
DataReader System.Data.OleDb.OleDbDataReader
DataTable System.Data.DataTable
DataSet System.Data.DataSet
DataRow System.Data.DataRow
Como podemos observar el objeto DataReader pertenece al espacio de nombres OleDb mientras que los demás pertenecen a
System.Data.
El objeto DataReader es un objeto ágil y que esta especializado en almacenar datos para solo lectura, lo que le quita la gestión de las
actualizaciones y le permite ser más rápido en los accesos a los datos de la base de datos.
El objeto DataTable, es lo más parecido a una tabla de la base de datos, dispone de la posibilidad de definir clave primaria de uno o varios
campos.
El DataTable puede ser la imagen de una tabla de la base de datos, o puede ser el resultado de una SQL que combine varias tablas en la
SQL, o tabla virtual si queremos llamarla así.
Este objeto en el uso del DataSet es usado como parte del DataSet.
El objeto DataSet es lo que hemos dado en llamar antes un subconjunto de la base de datos de nuestra aplicación.
273
Al iniciar el programa se carga con aquellos datos que sean necesarios para el mismo, se cierra la conexión y luego se realiza la
actualización de los datos en la base de datos con los cambios que hayan habido en el programa.
El DataSet no puede formar parte de un DataTable.
El objeto DataRow, lo hemos incorporado como elemento de almacenamiento, aunque hace referencia a una fila, registro de la base de
datos, porque hemos comprobado lo útil que llega a ser el uso del mismo, y al fin y al cabo almacena datos, un registro, pero datos.
3 Visualización.
Los objetos de visualización puede ser cualquiera de los que tenemos disponibles en el entorno de programación.
Lo importante aquí es como utilizarlos a la hora de visualizar los datos de nuestra fuente de almacenamiento.
Podríamos hablar de dos posibilidades.
Asignación clásica de los datos, o enlazarlos a nuestra fuente de datos.
Las dos son válidas evidentemente, pero hay que ver la practicidad.
El enlazado de un DataDrid a nuestro DataTable es comodísimo, pues se encarga de representar los datos que vamos incluyendo en la
tabla, sea la origen o una virtual.
El enlazado de un TextBox a un objeto crea el mismo código que hacer una asignación manual o clásica, por lo que ...
4 Otros.
Estos objetos pueden ser
BindingSource BindingSource
CommandBuilder System.OleDb.OleDbCommandBuilder
Command System.OleDb.OleDbCommand
BindingSource, este objeto es el que hace de puente entre aquellos objetos que no disponen de la propiedad DataSource y el objeto
fuente de los datos.
CommandBuilder, este genera de forma automática código SQL para las opciones Insert, Update y Delete, tanto para el uso normal, como
para cuando se utiliza el DataAdapter en el entorno de un DataSet.
Command, sirve para indicar, almacenar y ejecutar cuando proceda, la instrucción SQl, sea almacenada o incrustada, para un objeto
DataReader o DataAdapter.
Tiene dos formatos de utilización,
ExecuteNonQuery se ejecuta y no devuelve datos, borrado por ejemplo.
ExecuteReader se ejecuta y devuelve una colección de datos que se asignan a un objeto.
Pág. 55.2
Se puede elegir entre descomprimir en la ruta que deseemos, o bien descargar una versión con instalador.
56.4. Utilización.
Instalar el gestor de MySQL, se compone de distintos elementos, que cumplen con las necesidades de administración desde la línea de
comandos.
El comando de inicio del gestor es
C:MySQL>mysqld –u root
Una vez que se ha lanzado el gestor de MySQL, el servidor de MySQL, la ventana de DOS, quedará abierta, y ejecutándose dicho
servidor.
Mientras estemos utilizando VB con MySQL deberá estar abierta dicha ventana.
274
Podemos crear un archivo de proceso por lotes, un escrip, para su inicio y otro para su posterior parada.
Este sería el de inicio.
ECHO OFF
CLS
ECHO INICIO DE MySQL
D:
Cd D:\Mysql\mysql-5.1.33-win32\bin
MySQLd -u root
Y el de parada
ECHO OFF
CLS
ECHO PARADA DE MySQL
D:
Cd D:\Mysql\mysql-5.1.33-win32\bin
MySQLAdmin -u root shutdown
Pause
Con estos dos archivos tenemos suficiente para probarlo.
MySQL es una base datos muy completa, esos parámetros son los mínimos imprescindibles, a medida que se domina la herramienta, se
deberán incluir más parámetros para su correcta utilización.
El uso se supone en modo local, ‘localhost’.
Pág. 56.1
Y en la ventana
Pinchar en examinar hasta llegar a su ubicación, que por defecto es la que vemos.
Una vez seleccionada ya veremos como esta incluida la referencia en la pestaña de .Net.
275
A partir de aquí ya podemos hacer referencia a los mismos objetos que en SQL o en Acces para el uso de la base de datos, salvando las
distancias claro está.
Pág. 56.2
Después vamos a necesitar un objeto del tipo Command que será el que realizará la tarea.
Private Sub CrearBaseDatos()
Dim Conexion As New MySql.Data.MySqlClient.MySqlConnection
Dim CadenaSQL As String = "CREATE DATABASE " & NombreBaseDatos & ";"
Dim CadenaConexion As String = "Data Source=localhost;User Id=root;"
Dim Comando As New MySql.Data.MySqlClient.MySqlCommand(CadenaSQL)
276
Case 1
MsgBox("Creada")
Case Else
MsgBox("A saber que ha pasado")
End Select
Catch ex As MySql.Data.MySqlClient.MySqlException
MsgBox("No se ha podido crear" & vbCrLf & _
"la base de datos.", MsgBoxStyle.Critical, Me.Text)
End Try
Catch ex As MySql.Data.MySqlClient.MySqlException
MsgBox("No se ha podido establecer la" & vbCrLf & _
"conexión con la base de datos.", MsgBoxStyle.Critical, Me.Text)
Finally
Select Case Conexion.State
Case ConnectionState.Open
Conexion.Close()
End Select
End Try
Conexion = Nothing
End Sub
Esta es la sintaxis mínima para crear una base de datos.
Dim CadenaSQL As String = "CREATE DATABASE " & NombreBaseDatos & ";"
Como no hay que esperar datos devueltos el objeto a utilizar para su creación es un objeto Command.
Conexion = New MySql.Data.MySqlClient.MySqlConnection(CadenaConexion)
Conexion.Open()
Comando.Connection = Conexion
Comando.CommandType = CommandType.Text
Select Case Comando.ExecuteNonQuery
La pregunta de control se basa en que haya un dato devuelto, que es la creación de la base de datos.
Select Case Comando.ExecuteNonQuery
Case 0
MsgBox("No se ha creado")
Case 1
MsgBox("Creada")
Case Else
MsgBox("A saber que ha pasado")
End Select
En el ejemplo se supone que forma parte de una utilidad y por eso el objeto conexión se configura en el mismo procedimiento.
También podemos hacerlo desde la herramienta gráfica de administración, pulsando en la zona de bases de datos y con el botón derecho
del ratón seleccionar Create New Schema.
277
Respondemos OK y la base quedará creada.
Pág. 56.3
279
La ventana de creación de una tabla es la que vemos y solo hay que ir añadiendo los campos e ir jugando con las pestañas de opciones
en función de las necesidades de cada campo.
Al finalizar pulsar Apply Changes veremos como aparece una ventana con el código SQL de la tabla, solo tenemos que pulsar Execute, y
la tabla se incorporará a la base de datos.
280
Podemos observar como el motor de la tabla está mal seleccionado con respecto al resto de las tablas de la base de datos.
Habría que seleccionar con el botón derecho en la tabla la opción de editar tabla, para volver a la misma ventana de antes y en la pestaña
de Table Options cambiar el motor de la tabla para que todo quede bien.
En esa ventana también podemos editar los datos de las tablas para comprobar el correcto funcionamiento de nuestros programas,
seleccionando la tabla con el botón derecho del ratón la opción de Edit Table Data.
Disponemos de más opciones es cuestión de documentarse.
Pág. 56.5
La utilización de los objetos de MySQL puede facilitarse si importamos en las propiedades del proyecto el espacio de nombres de
MySQL.Data.MySQLClient.
Proyecto à Propiedades de proyecto à Referencias.
De esa forma podemos escribir simplemente.
Dim ObjSQL As MySqlConnection
Que siempre es más cómodo.
Pág. 56.6
281