Sunteți pe pagina 1din 281

Curso de Visual Basic.

Índice del curso


19. La herencia en las clases 39. Archivos secuenciales, formatos
Introducción a la programación
20. La herencia en las clases en VB 40. Archivos secuenciales en VB
1. Programación 21. La sobrecarga en las clases 41. Archivos Random
2. Estructura y representación de un programa 22. La sobrecarga en las clases en VB 42. Archivos Random en VB
3. Los datos 23. Cómo programar una clase
Utilizando entorno gráfico
4. Las expresiones 24. Cómo programar una clase en VB
5. Las instrucciones 25. Utilizar clases 43. Programación en un entorno gráfico
6. Programa 26. Utilizar clases en VB 44. ¿Cómo se hace un programa?
7. Las clases 27. Utilizar y definir datos 45. Objetos, mostrar datos
8. VB Studio Net 2005 28. Utilizar y definir datos en VB 46. Objetos, el teclado
9. Procedimientos 29. Enumeraciones 47. Botones de órdenes
10. Primer programa en VB, procedimientos 30. Enumeraciones en VB 48. Seleccionar una opción
11. Funciones 31. Colecciones 49. Selección de datos
12. Funciones en VB 32. Colecciones en VB 50. Los menús
13. Las clases en los datos 33. Arrays 51. Cuadros de diálogo
14. Clases en VB 34. Arrays en VB 52. Otros objetos
15. Las clases en el código 35. Captura de errores 53. DataGrid
16. Clases, Código en VB 36. Captura de errores en VB 54. Impresión
17. Ciclo de vida de una clase 37. Archivos 55. Bases de datos
18. Ciclo de vida de una clase en VB 38. Archivos en VB 56. Enlazar VB y MySQL
Índice detallado

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.

Unidad 3. Los datos Unidad 32. Colecciones en VB


• 3.1. Objetivos del tema.
• 32.1. Objetivos del tema.
• 3.2. Introducción.
• 32.2. Introducción.
• 3.3. Los tipos de datos.
• 32.3. Creación.

Unidad 4. Las expresiones • 32.4. Recorrido.


• 32.5. Operaciones con una colección.
• 4.1. Objetivos del tema.
• 32.6. Propiedades.
• 4.2. Introducción.
• 4.3. Expresiones.
Unidad 33. Arrays
• 4.4. ¿Como se distinguen los tipos de variable?
• 33.1. Objetivos del tema.
• 4.5. Operadores.
• 33.2. Introducción.

Unidad 5. Las instrucciones • 33.3. Datos.

• 5.1. Objetivos del tema.


• 33.4. Definición.
• 33.5. Índice en un array.
• 5.2. Introducción.
• 33.6. Acceso.
• 5.3. Instrucciones.
• 33.7. Recorrido.
Unidad 6. Programa
• 33.8. Carga de datos.
• 6.1. Objetivos del tema.
• 33.9. Visualización.
• 6.2. Introducción.
• 33.10. Búsquedas.
• 6.3. Declaraciones.
• 33.11. Aplicación de los vectores.
• 6.4. Clases.
• 33.12. Aplicación de las matrices.
• 6.5. Procedimientos.
Unidad 34. Arrays en VB
• 6.6. Funciones.
• 34.1. Objetivos del tema.
• 6.7. Conclusiones.
• 34.2. Introducción.
Unidad 7. Las clases
• 34.3. Declaración
• 7.1. Objetivos del tema.
• 34.4. Recorrido.
• 7.2. Introducción.
• 34.5. Operaciones.
• 7.3. Clase.
• 34.6. Métodos.
• 7.4. Propiedades.
Unidad 35. Captura de errores
• 7.5. Método.
• 35.1. Objetivos del tema.
• 7.6. Eventos.
• 35.2. Introducción.
• 7.7. Polimorfismo.
• 35.3. Captura de errores.
• 7.8. Herencia.
• 35.4. Errores.
• 7.9. Ocultación.
• 35.5. Inhibición en la captura.
• 7.10. Aplicación.
• 35.6. Trazas.
• 7.11. Conclusiones.
• 35.7. Conclusiones.
Unidad 8. VB Studio Net 2005
Unidad 36. Captura de errores en VB
• 8.1. Objetivos del tema.
• 36.1. Objetivos del tema.
• 8.2. Introducción.
• 36.2. Introducción.
• 8.3. Características.
• 36.3. On Error.
• 8.4. Advertencias.
• 36.4. Try Catch.
• 8.5. Entorno utilizado.
• 36.5. Inhibición.
• 8.6. El entorno de programación VB2005.
• 8.7. Descarga.
• 36.6. Conclusiones.

• 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.

Contenidos del curso.

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.

Y sobre todo lo importante no es que empecemos, si no que lo podamos acabar.

¡¡¡¡¡ Animo !!!!!


Unidad 1. Programación (I)
1.1. Objetivos del tema.
Solo pretender que centremos un poco lo que es la tarea de la programación, y que sobre todo es un aspecto de lógica, lógica aplastante.
1.2. Introducción.
Intentar dar una definición de lo que es programar en la actualidad es muy atrevido, por lo que el que desee una de esas definiciones solo
tiene que acudir a Internet y encontrara seguro un sin fin de ellas.
Pero para escribir un programa, una aplicación, un paquete informático, hay que combinar varios elementos.

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.

1.4. Lo principal de un programador.


Tener las ideas claras, saber de forma exacta que es lo que tienes y a donde has de llegar.
Tener claro en que orden quieres hacerlo.
Lo mas importante en programación son los conceptos. Si se tienen claros, a continuación, podrás buscar las herramientas que necesitas
en el lenguaje que usas y realizarás correctamente tu labor.
Memorizar cosas no es importante, es más importante saber donde esta un manual y buscar ahí la información, que necesitemos.
El cambiar a otro lenguaje de programación, si los conceptos son sólidos, no supondrá ningún trauma, pues cambiarán las instrucciones
que usas, pero no el orden en que se tienen que realizar los pasos.
Dominar la herramienta de programación de que dispones.
Realizar las pruebas adecuadas de funcionamiento correcto del programa.
La fase de depuración y pruebas de un programa son importantísimas, porque eso nos lleva a un producto final fiable y de probada
eficacia, lo cual da fiabilidad al producto, y al programador que lo crea.
Un programa que no da confianza no se utiliza.
1.5. Características.
Se podrían añadir o quitar, pero estas son importantes.
1 Legibilidad.
Debe ser posible leerlo y entenderlo con facilidad, el uso de nombre de variables adecuados y comentarios, facilita este apartado.
2 Portabilidad.
Crear estructuras que permitan su codificación en distintos lenguajes.
3 Modificabilidad.
Ha de facilitar su mantenimiento, es decir, debe permitir que se modifique o actualice en función de las necesidades del problema a
resolver. Para ello es conveniente comentar adecuadamente el código.
Un programa debe quedar escrito y documentado de tal forma que otra persona que venga detrás pueda modificarlo o ampliarlo sin
excesiva dificultad.
4 Eficiencia.
Se debe aprovechar al máximo los recursos del ordenador, minimizando el empleo de memoria y el tiempo de ejecución. Además, como
es obvio, debe resolver el problema para el que ha sido planteado.
5 Modularidad.
Se debe procurar no tener que resolver el mismo problema varias veces. A igual problema, igual solución, lo que conlleva la elaboración
de módulos para resolver problemas concretos.
6 Estructuración.
Lo programas deben tener única y exclusivamente estructuras lineales, alternativas y cíclicas, exclusivamente, o dicho de otra forma, no
es conveniente utilizar instrucciones de salto, aunque estén disponibles en el lenguje de programación.
1.6. Problemas en los programas.
Cuando se tienen problemas con un programa, lo mejor es ir haciendo pruebas por zonas, visualizando contenidos mediante las
herramientas, opciones de depuración del entorno que utilizamos, de las variables que nos interesan y comprobando que se ejecutan las zonas
del programa que a nosotros nos interesan que se ejecute.
Cuando se diseña una rutina, función, procedimiento o método nuevo, esta debe probarse fuera del programa, para asegurarse de su
correcto diseño y que devuelve correctamente los resultados, asignándole en la prueba todos los valores posibles para verificar su correcto
funcionamiento.
En un programa pequeño eso es muy fácil de probar y de controlar su ejecución correcta.
Copiar un programa no es malo, no suele hacerse, suelen copiarse ideas, o mejorar cosas que se observan en otros paquetes, pero lo
importante si se hace, es saber como funciona y entenderlo, si no, no nos aportará nada.

Ejercicios unidad 1: Programación


No va a ser lo habitual, pero en este caso plantéense cualquier actividad de las que realizamos al final de un día y trate de desglosarla en
pasos.
Primero en dos o tres, pero luego esos dos o tres pasos, cada uno de ellos ha de dividirlos en dos o tres o más a su vez, y a ver hasta
donde es capaz de llegar.
Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.
Ayuda ejercicios unidad 1: Programación
8
Las actividades de un día podrían ser:

Levantarse
Asearse
Desayunar
Realizar las actividades matutinas
Almorzar ...

Levantarse se puede dividir en


Suena el despertador.
Levantar la ropa de la cama
Abrir la ventana.

Pero Levantar la ropa de la cama se puede dividir en


Sujeta la ropa
Desplázala hacia atrás
Suelta la ropa

En fin, por ahí va el tema.

Unidad 2. Estructura y representación de un programa (I)


2.1. Objetivos del tema.
Veamos lo que es un programa, en cuanto a sus elementos mínimos, y estructura mínima, poco a poco iremos ampliando e introduciendo
el resto de elementos.
2.2. Introducción.
Un ordenador tiene como misión la de realizar, o facilitar las tareas que de otra forma se realizarían en una forma tediosa e incomoda.
Los ordenadores son capaces de ejecutar programas.
Los programas están realizados por personas y los ejecutan los ordenadores.
Los programas utilizan información en su ejecución, y como resultado de su ejecución facilitan, o no, nuevos datos.
Los datos que se utilizan en los programas forman parte de las instrucciones que ejecuta el programa.
2.3. Escribir un programa.
Toda actividad necesita de un argot, jerga y convenios para poderse entender entre las personas que se dedican a una misma labor. No
es que se pretenda aislarse del resto de las personas, sino que es necesario ese convenio y un lenguaje específico que a cada cosa le asigne su
nombre característico y propio, y de esa forma facilite la comunicación entre las personas.
De esta forma surge en cada profesión una serie de símbolos y palabras para facilitar el trabajo.

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.

Lo que sigue es un pequeño ejemplo de un programa muy sencillo, en formato de seudocódigo.

Inicio
Escribir “Cálculo del área de un triángulo”

Leer “Introduzca la base del triángulo”, Base


Leer “Introduzca la altura del triángulo”, Altura

Area = (Base * Altura) / 2


Escribir “El área del triángulo es “, Area
Fin
Esta forma de escribir, o de describir dicho programa se denomina pseudocódigo.

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.

Para ello los símbolos utilizados básicamente son:

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

Unidad 2. Estructura y representación de un programa (II)


Expliquemos lo visto.

Escribir “Cálculo del área de un triángulo”


Esto es una instrucción que incorpora un texto que se llama literal, y en un programa de verdad en lugar de estar en castellano estará en
ingles.

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…

Leer “Base del triángulo”, Base


Esto es una instrucción que es capaz de visualizar un texto y esperar a que el usuario escriba un dato.

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.

Ejercicios propuestos de la Unidad

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.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.

Ayuda ejercicios unidad 2: Estructura y representación de un programa


Ofrecemos la versión en organigrama.

Unidad 3. Los datos (I)


3.1. Objetivos del tema.
Hemos visto en el tema anterior como un programa es algo muy fácil, claro el ejemplo era muy fácil, pero se trataba de dejar visto, que es
así.
Ahora vamos a ver que en el tema anterior hemos utilizado datos, pero que en realidad los datos son algo más.
3.2. Introducción.
Los datos en un programa es uno de los elementos vitales del mismo, pero en la vida cotidiana los utilizamos a diario también, si nos
fijamos en los datos que utilizamos, nos daremos cuenta que son letras y números, números solo o solo letras.
También, cuando a lo largo del día alguien nos da un dato pequeño, normalmente no memorizamos, pero si es largo o complejo, lo
apuntamos, ¿Por qué?, por que tenemos nuestras limitaciones, por la edad, por lo despistados que somos etc..
Los ordenadores también disponen de memoria, y también manejan información, datos, y en función de lo voluminosos que sean los
datos, los almacenarán en la memoria central del ordenador, o en un soporte, en el disco duro o lo grabaremos en un disquete o disco compacto,
etc..
3.3. Los tipos de datos.
Informáticamente los datos son de dos tipos básicos, números y letras, o numéricos y alfanuméricos.
Con los datos numéricos realizamos operaciones de cálculo y con los alfanuméricos representamos información y la almacenamos para el
uso en el programa.

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.

Estos bit se agrupan en grupos de

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.

Ejercicios propuestos de la Unidad


Pág. 3.2
Ejercicios unidad 3: Los datos
Con la tabla de referencia anterior,

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
responde a estas cuestiones.
1º Deseo contar los espectadores de un partido de fútbol, qué tipo de dato utilizarías en el programa.
2º Deseo saber cuántos espectadores entran a ver una obra de teatro, qué tipo de dato utilizarías en el programa.
3º Deseo saber cuántas botellas se llenan al final del día en una fábrica, que tiene una capacidad máxima de
fabricación de 1000 botellas por minuto.
4º Si deseo representar en un programa un texto con el cual informar de un error de ejecución al usuario, que tipo de
dato utilizaría.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.

Ayuda ejercicios unidad 3: Los datos


1º Se podrían utilizar, tipos de datos de tipo Byte, Integer o Long, dependerá de lo malo que sea el partido, pero lo
lógico sería utilizar un Long.

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.

Unidad 4. Las expresiones (I)


4.1. Objetivos del tema.
Hemos visto en el tema anterior que en un programa uno de los apartados a utilizar son los datos.
Los datos en si no son nada si no se utilizan, y la forma de utilizarlos es en expresiones, dentro de una instrucción, o de forma aislada,
vamos a ver que son las expresiones y su evaluación.
4.2. Introducción.
Las instrucciones es la forma de hacer que un programa haga la tarea para la cual lo estamos escribiendo, pero esas instrucciones tienen
que manejar datos, y al final lo que hacemos es escribir expresiones que se evalúan y que producen un resultado que permite resolver o tomar
una decisión.
Para utilizar los datos necesitamos crear esas expresiones, las expresiones las crearemos utilizando los datos y los operadores que me
permiten dar sentido a esa expresión para que produzca un resultado.
4.3. Expresiones.
Las expresiones están compuestas por datos, y los datos en un programa se almacenan en variables.
Las denominamos de esa forma porque su valor cambia a lo largo de la ejecución del programa, cuando un dato está almacenado en una
variable y su valor es estático, por ejemplo declaramos la variable Pi = 3,1415, entonces la denominamos constante.
Las variables, como ya se comentó antes, almacenan datos, y los datos hemos quedado que básicamente eran de dos tipos numéricos y
alfanuméricos.
Con las variables alfanuméricas almacenamos datos de texto, para el uso que sea pertinente en el programa.
Con las variables numéricas almacenamos datos de valor numérico, con las que podemos realizar operaciones de cálculo.
Si las variables son numéricas, en realidad, y recordando el cuadro de posibles valores del tema anterior, las variables numéricas en
realidad podrán ser:
Byte
Integer
Long
Real
Hay que tener presente que el nombre de los tipos cambiará en función del lenguaje utilizado, por ejemplo el Real también podemos
encontrarlo como simple y doble precisión.

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,

Paréntesis, de dentro a fuera.


Signo.
Potencia.
Productos y divisiones.
Suma y restas.
Concatenación.
Relacionales.
Negación.
Conjunción.
Disyunción.

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

Unidad 4. Las expresiones (II)


4.5. Operadores.
Indican que tipo de acción se ha de realizar con dos variables.
Hemos quedado que las variables contienen datos.
Los datos son para manejarlos y obtener otros datos a partir de ellos.
Para eso hay que realizar distintos tipos de operaciones y cada operación ha de estar representada por un operador.
Los operadores se dividen por el tipo de operación que realizan.

Las distintas operaciones que se pueden realizar en un programa son:

Aritméticas. Sumas restas ...


Lógicas. Condición And Condición, o Condición Or Condición.
Relacionales. Mayor o Igual, >=, <=, =, >, <

Que se corresponde con los tipos de operadores descritos anteriormente.


Luego para cada tipo de operación son necesarios unos símbolos que identifiquen la acción que se desea realizar.
A continuación exponemos los operadores en un formato que suele ser habitual, pero que después habrá que volver a ver en el lenguaje
correspondiente.

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

La sintaxis del operador And consta de las siguientes partes:

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:

La tabla de verdad es:


Expresión1 Expresión2 Resultado
True True True
True False False
False True False
15
False False False
El operador And ejecuta también 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 :
Bit Bit Resultado
0 0 0
0 1 0
1 0 0
1 1 1

2.2 Or.
Se utiliza para ejecutar una disyunción lógica sobre dos expresiones.

Sintaxis
resultado = expresión1 Or expresión2

La sintaxis del operador Or consta de las siguientes partes:

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

Unidad 4. Las expresiones (III)


2.3 Not.
Se utiliza para ejecutar una negación lógica sobre una expresión.

Sintaxis
resultado = Not expresión

La sintaxis del operador Not consta de las siguientes partes:

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

La sintaxis del operador Xor consta de las siguientes partes:

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

La sintaxis del operador Imp consta de las siguientes partes:

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

La sintaxis del operador Eqv consta de las siguientes partes:

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.…

Ejercicios propuestos de la Unidad


Pág. 4.4
Ejercicios unidad 4: Las expresiones
En la evaluación de las expresiones, se ha subrayado la parte de la expresión que se va a evaluar y después su resultado en negrita.

((3+2 )2 - 15) / 2 * 5 Evaluamos (3+2)


((5)2 - 15) / 2 * 5 El resultado es 5, ahora evaluamos (5)2.
(25 - 15) / 2 * 5 El resultado es 25, ahora evaluamos (25 - 15), etc…

El ejemplo completo.

Se escribe ((3+2 )2 - 15) / 2 * 5


Se interpreta ((3+2 )2 - 15) / 2 * 5
((5)2 - 15) / 2 * 5
(25 - 15) / 2 * 5
10 / 2 * 5
5*5
Resultado 25

Se escribe 5 - 2 > 4 AND NOT 0.5 = 1 / 2


Se interpreta 5 - 2 > 4 AND NOT 0.5 = 1 / 2
3 > 4 AND NOT 0.5 = 1 / 2
False AND NOT 0.5 = 1 / 2
False AND NOT True
False AND False
Resultado False

Siempre se llega a una expresión simple.

Dadas las siguientes variables y constantes.

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”

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.

Ayuda ejercicios unidad 4: Las expresiones


Se escribe 2 * X + 0.5 * Y - 1/5 * Z
Se evalúa 2 * X + 0.5 * Y - 1/5 * Z
2 + 0.5 * Y - 1/5 * Z
2 + 2 - 1/5 * Z
2 + 2 - 0,2 * Z
2+2-2
4-2
Resultado 2

Se escribe Pi * X^2 > Y OR 2 * Pi * x < = Z


Se evalúa Pi * X^2 > Y OR 2 * Pi * x < = Z
Pi * 1 > Y OR 2 * Pi * x < = Z
3,141592 > Y OR 2 * Pi * x < = Z
3,141592 > Y OR 6.283184 < = Z
False OR 6.283184 < = Z
False OR True
Resultado True
Se escribe E( X - 1 ) / ( X * Z ) / ( X / Z)
Se evalúa E( X - 1 ) / ( X * Z ) / ( X / Z)
E 0 / ( X * Z ) / ( X / Z)
E 0 / 10 / ( X / Z)
E 0 / 10 / 0,1
1 / 10 / 0,1
0,1 / 0,1
Resultado 1

Se escribe “Don ” + “Juan”= “Don Juan” Or “A”= “a”


Se evalúa “Don ” + “Juan”= “Don Juan” Or “A”= “a”
“Don Juan”= “Don Juan” Or “A”= “a”
True Or “A”= “a”
True Or False
Resultado True
Se escribe X - Y + Z + Pi - E + 2.576689
Se evalúa X - Y + Z + Pi - E + 2.576689
-3 + Z + Pi - E + 2.576689
+7 + Pi - E + 2.576689
10,141592 - E + 2.576689
7,423311 + 2.576689
Resultado 10

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

Se escribe X > 3 AND Y = 4 OR X + Y < = Z


Se evalúa X > 3 AND Y = 4 OR X + Y < = Z
X > 3 AND Y = 4 OR 5 < = Z
False AND Y = 4 OR 5 < = Z
False AND True OR 5 < = Z
False AND True OR True
False OR True
Resultado True
Se escribe X > 3 AND (Y= 4 OR X + Y > = Z)
Se evalúa X > 3 AND (Y= 4 OR X + Y > = Z)
X > 3 AND (Y= 4 OR 5 > = Z)
X > 3 AND (True OR 5 > = Z)
X > 3 AND (True OR False)
X > 3 AND True
False AND True
Resultado False

Se escribe NOT “METODO”+”LOGIA” = “LOGIA”+”METODO”


Se evalúa NOT “METODO”+”LOGIA” = “LOGIA”+”METODO”
NOT “METODOLOGIA” = “LOGIA”+”METODO”
NOT “METODOLOGIA” = “LOGIAMETODO”
NOT False
Resultado True
El símbolo +, se usa como concatenación.

Unidad 5. Las instrucciones (I)


5.1. Objetivos del tema.
Hemos visto lo que es la estructura de un programa, los datos, que esos datos en realidad se convierten en variables de distinto tipo
dentro de un programa, y que esas variables generan o creamos con ellas expresiones.
Ahora, una vez que tenemos expresiones, hay que utilizarlas para algo, las expresiones pueden ir de forma aislada o formar parte de las
instrucciones de un programa.
5.2. Introducción.
Un programa se construye a base de escribir una serie de instrucciones propias del lenguaje que utilizamos y con el fin de poder llegar a
que ese programa realice la labor para la cual se ha diseñado.
Las instrucciones de un lenguaje de programación son las que nos permiten crear la estructura del programa.
En los programas vamos creando bloques con las instrucciones, de forma que a base de ir sumando bloques llegamos a construir un
programa más o menos complejo.
El mejor ejemplo podríamos verlo en un edificio.
Un edificio se construye a base de ir añadiendo ladrillos, muchos ladrillos, que se apoyan unos en otros.
Un programa se puede ver como algo similar.
Pero un edificio se sustenta sobre una estructura.
A nivel de programación, esa estructura se basa en los procedimientos y funciones que escribimos en el programa, y esos
procedimientos, funciones y métodos, los llenamos de instrucciones.
5.3. Instrucciones.
La secuencia de instrucciones escritas en un orden lógico, que indican las operaciones a realizar para resolver un problema, es lo que
denominamos programa.
Las instrucciones sin las expresiones en la mayoría de los casos no tienen razón de ser.

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.

Inicio o final de programa, procedimiento, función o método.

Condición dentro de un programa, se convierte en un

If condición then acción else acción.


Si se cumple la condición entonces hacemos y sino se cumple hacemos esto otro.

Este rectángulo normalmente albergará operaciones de cálculo, expresiones.

A=A+B

Entrada de datos por teclado, es la forma de recabar información del usuario.

Visualizar datos en el monitor, de esa forma podemos ofrecer información al usuario.

Imprimir el dato en la impresora del sistema.

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.

Con las instrucciones podemos crear esos tres tipos de posibilidades,

Ejecución lineal o secuencial.


Ejecución alternativa, tomar una decisión.
Ejecución repetitiva.

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

Unidad 5. Las instrucciones (II)


21
4 Alternativas.
En la imagen de la izquierda podemos observar como hay una decisión y la posibilidad de que se ejecute una u
otra rama del programa, eso es una estructura alternativa.

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.

Estas instrucciones pueden estar anidadas, unas dentro de otras.

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”.

Y se podrían seguir anidando condiciones.

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.

Mientras se cumple una condición.


Repite hasta que se cumple una condición

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.

Ejercicios propuestos de la Unidad

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.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.


Ayuda ejercicios unidad 5: Las instrucciones
Más adelante codificaremos estos ejercicios en el lenguaje que cada uno de ustedes seleccione.

Introducir dos números A y B, e indicar cual es el mayor de ambos.

23
Los ejercicios del 1 al 7 son iguales en su estructura, distintos en la condición.

2º la condición será A< B


3º , 4º y 5º, la condición será A<> B o A = B, en función de si deseamos salir por afirmación o por negación.

Inicio Ejercicio Uno.


Declarar A y B como enteras.
Escribir “Introducir dos valores e indicar cual es el mayor”
Leer “Introduzca A”, A
Leer “introduzca B”, B
Si A > B Entonces
Escribir “El mayor es A”
Si no
Escribir “El mayor es B”
Fin de condición.
Final
Introducir dos números A y B, e indicar cual no es el mayor.

7º la estructura es igual cambiando la condición.

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.

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

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.

Se repite la estructura cambiando la condición y el contenido de las acciones.


Introducir dos números A y B y visualizarlos en orden creciente.

11º, se repite la estructura cambiando la condición.

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.

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.

Visualizar los números entre 10 y 20

Inicio Ejercicio Catorce.


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
Final

Inicio Ejercicio Catorce.


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
Visualizar los números entre 20 y 10.

Visualizar los números entre 10 y 20 y sumarlos.

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.

Inicio Ejercicio Diecisiete.


Declarar X como Entera.
Escribir “Visualizamos los números entre diez y veinte”
X = 21
Inicio de repite
X = X – 1
Si X Mod 2 = 0 Entonces
Escribir X
Fin de condición
Hasta que X = 10
Final

Unidad 6. Programa (I)


6.1. Objetivos del tema.
Hemos visto todos los componentes de un programa, veamos ahora un programa.
6.2. Introducción.
Un programa esta dividido en varios bloques.
Declaraciones.
Procedimientos y funciones de usuario.
Programa principal.

A su vez en el programa encontramos tres fases.


Entrada de datos.
Proceso de los mismos.
Obtención de resultados.

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”:

¿Cuántos metros cuadrados quiere que tenga la casa?


¿Cuántas habitaciones quiere?
¿Quiere terraza?
¿Cuántos baños desea?, etc..

Y después de estas preguntan viéramos los planos en función de esos parámetros.


En función de la respuesta la casa sería de una forma o de otra, sin embargo la clase “Casa” siempre sería la misma, cambiaría el
resultado en función de los parámetros que le hubiéramos facilitado.

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.

Una clase es única, sin embargo sus resultados diversos.


Para conseguir eso es necesario que disponga de los datos para poder desarrollar distintas casas.
De los distintos métodos para cada una de las características de la casa.
Los métodos son la parte ejecutiva de la clase, y se escriben mediante le uso de procedimientos y funciones en función
de su diseño.
La parte de captura de información, o la asignación de datos a la clase, es lo que denominamos propiedades.
La clase podrá o no responder a impulsos externos, esa capacidad se denomina evento.
6.5. Procedimientos.
En todo programa hay una parte del mismo que se repite, y que si no se inscribe en el ámbito de un procedimiento
debería estar escrito un sin fin de veces.
Por lo tanto en lugar de repetir el código a lo largo del programa lo que se hace es escribirlo en el interior de un
procedimiento y llamar a la ejecución del mismo cada vez que haga falta.
Eso facilita la escritura del programa, la modificación del mismo y su claridad.
Podemos ver en el ejemplo lateral como podría ser el organigrama de un programa cualquiera, sencillo, pero válido.
Como podemos ver el organigrama aunque claro es largo y pesado de leer, imagínense eso con un programa de verdad, no
sería práctico, de escribir ni de seguir.
Si nos fijamos en las acciones de se programa, podemos observar que hay cuatro pasos.

Carga.
Visualización.
Proceso.
Visualización.

Como podemos ver la visualización se repite.

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.

Los procedimientos pueden o no recibir datos para la ejecución del mismo.


Los procedimientos pueden o no devolver datos, tras la ejecución del mismo.

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

Unidad 6. Programa (II)


6.6. Funciones.
Un procedimiento se escribe para resolver la estructura de un programa, y podrá o no devolver o
recibir datos.
Una función es una parte de nuestro código que formará parte de una expresión especializada en
realizar algún tipo de operación, cálculo, comparación, dibujo, ...
Por lo tanto una función no suele utilizarse para resolver la estructura de un programa, sino para que
se pueda mejorar el mismo.
Si en un programa hay que verificar si un valor cumple una determinada condición y si es cierto
realizar una acción y sino otra, lo correcto es que se cree una función y se utilice como parte de la instrucción
condicional.

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.

Ejercicios propuestos de la Unidad


Pág. 6.2
Ejercicios unidad 6: Programa
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.
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.
4. - Introducir dos números A y B y visualizarlos en orden creciente.
5. - 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.
6. - 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.
7. - Visualizar los números entre 10 y 20
8. - Visualizar los números entre 10 y 20 y sumarlos.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.

Ayuda ejercicios unidad 6: Programa


Introducir dos números A y B, e indicar cual es el mayor de ambos.

Inicio Funcion Mayor(A,B)


Declarar Result como Alfanumérico
Si C > D Entonces
Result = “El mayor es A”
Si no
Result = “El mayor es B”
Fin de condición.
Mayor = Result
Final de Funcion

Inicio Ejercicio Uno.


Declarar A y B como enteras.
Escribir “Introducir dos valores e indicar cual es el mayor”
Leer “Introduzca A”, A
Leer “introduzca B”, B

Escribir “El mayor es “, Mayor(A,B)

Final

30
El ejercicio dos es igual, cambiando el valor de la pregunta en la función por menor, A < B

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.

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

Inicio Ejercicio Tres.


Declarar A y B como enteras.
Escribir “Introducir dos valores numéricos”
Leer “Introduzca A”, A
Leer “introduzca B”, B
Proceso(A,B)
Final
O la otra opción.

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

Inicio Ejercicio Tres.


Escribir “Introducir dos valores numéricos”
Proceso
Final
Introducir dos números A y B y visualizarlos en orden creciente.

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.

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.

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
Fin de procedimiento

Inicio Ejercicio Cinco.


32
Escribir “Introducir dos valores numéricos”
Proceso()
Final
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.

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.

Visualizar los números entre 10 y 20

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

Inicio Ejercicio Siete.


Proceso
Final

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

Inicio Ejercicio Ocho.


Proceso
Final

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

Inicio Ejercicio Ocho.


Escribir “Visualizamos los números entre diez y veinte y su suma”
Escribir “El Valor de la suma es “, Calcula
Final

Unidad 7. Las clases (I)


7.1. Objetivos del tema.
Hemos visto los componentes de un programa, hemos ido nombrándolos de dentro hacia fuera, es decir

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

Propiedades que al fin y al cabo son datos, vistos anteriormente.


Métodos que son procedimientos y funciones, en cuyo interior tenemos las estructuras básicas de programación vistos en
el tema cinco y en el tema anterior.
Eventos que se construyen también mediante código.
7.3. Clase.
En programación, un objeto es un ente que es capaz de realizar tareas y reaccionar ante aquello que tiene a su alrededor, ante los
eventos que lo rodean, sea un partido de fútbol, una película, una sensación, y al que dotamos de una serie de características, alto, bajo, grande
pequeño y que se definen cuando creamos el objeto y que podemos dejar que quien vaya a utilizarlo los pueda modificar, pero siempre bajo
nuestro control, claro, para eso el objeto lo hemos creado nosotros.

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

Por lo tanto las propiedades describen el objeto.


Podemos crear características internas, que no se podrán utilizar fuera del objeto, y otras que serán externas y que sí que se verán en el
objeto y podrán ser modificadas lo que permitirá crear objetos de distintos tipos.
Estas características externas son las que de verdad denominamos propiedades, pues es posible que sean modificadas por quien utiliza
la clase, quien de verdad genera después el objeto.
Las características internas, por llamarlas así, son en realidad variables de la clase, las propiedades también lo son, pero se ven por parte
del usuario.
7.5. Método.
Y como queremos que sea capaz de hacer cosas le enseñaremos métodos.

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.

Longitud del pelo.


35
Ancho de la cintura
Ancho del pecho
Longitud de las piernas.
Pág. 7.1
Unidad 7. Las clases (II)
7.7. Polimorfismo.
Pero las personas no son todas iguales, y cada una dispone de distintas habilidades, por lo que podremos dotar de más habilidades a
ésta clase, a ésta persona.
Pintar
Dibujar
Sumar
Bailar

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.

El bebe solo lo definiríamos por ejemplo con

Sexo
Altura
Color pelo
Color ojos
Color de la piel

Le enseñaremos solo a

Hablar
Leer
Escribir
Andar
Correr

Y le dotaremos de la posibilidad de reaccionar ante

Calor
Frío
Seco
Mojado

Y después crearíamos una nueva clase que heredara esas capacidades y le añadiríamos otras nuevas.

De esa forma podríamos entrenarlo para que fuera un gran cocinero.


Le potenciaríamos la posibilidad de percibir los olores y los sabores.
Mejoraríamos su habilidad en el manejo de las manos.

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.

Veamos un ejemplo un tanto irreal.


Desarrollamos una clase que denominamos Humano

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)

Mientras haya Hojas


Mientras haya Lineas
Mientras haya palabras
Leer palabra
Fin de mientras
CambiarDeLinea
Fin de mientras
CambiardePagina
Fin de mientras

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

Mientras haya Palabras


Leer Palabra
Si hay que leer en voz alta
Mujer.Hablar Palabra
Fin de condición
Fin de mientras
O podría ser también

Mientras haya Palabras Y NoEstoyCansado


Leer Palabra
Fin de mientras

O evidentemente todo junto.

Mientras haya Palabras y NoEstoyCansado


Leer Palabra
Si hay que leer en voz alta
Mujer.Hablar Palabra
Fin de condición
Fin de mientras

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)

Mientras haya Hojas Y NoEstoyCansado


Mientras haya Lineas Y NoEstoyCansado
Mientras haya Palabras Y NoEstoyCansado
Leer Palabra
Si hay que leer en voz alta
Mujer.Hablar Palabra
Fin de condición
Fin de mientras
CambiarDeLinea
Fin de mientras
CambiardePagina
Fin de mientras

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.

Eso se realiza ya dentro de nuestro programa.

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.

Ejercicios propuestos de la Unidad


Pág. 7.4
Ejercicios unidad 7: Las clases
Plantéese el crear una clase Casa, que sea capaz de crear una casa de cualquier tipo, en cuanto a número de habitaciones, baños, etc..
Añádale la posibilidad de tener varias casas en un mismo edificio, el número de plantas, el número de casas por planta.
Posteriormente, añádale la capacidad de que la casa pueda tener piscina, barbacoa, jardín, garaje.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.


Ayuda ejercicios unidad 7: Las clases
Clase Casa
Propiedad M2Cocina
Propiedad M2Baños
Propiedad M2Salon
Propiedad Habitaciones
Propiedad M2Habitacion
Propiedad Baños

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.

8.5. Entorno utilizado.


En ésta documentación se ha utilizado la versión y entorno de programación de Studio Net 2005.
En el siguiente link se puede acceder a información y descarga del producto gratuito si después deseas registrarte.

http://www.microsoft.com/spanish/msdn/vstudio/express/default.mspx

8.6. El entorno de programación VB2005.


La labor de programación es una tarea más, como otro de los trabajos que hay en la vida, el problema es cuando el trabajo se hace a
gusto o no.
Por lo tanto a la hora de realizar cualquier trabajo hay que intentar disponer de las mejores situaciones posibles.
Para programar disponer de un entorno de programación potente es importante, dado que te facilita en buena medida la labor.
EL entorno de Vb está preparado para facilitar toda una serie de tareas del día a día en la escritura de un programa.

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

Unidad 8. VB Studio Net 2005 (II)


8.8. Iniciar.
Finalizada la descarga y la instalación, podemos empezar nuestro primer proyecto en VB.

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.

Aquí vemos la pestaña de la caja de herramientas a la izquierda y a la derecha ya desplegada.


Se puede visualizar de varias formas, en función de las necesidades de diseño del formulario.

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

Unidad 8. VB Studio Net 2005 (III)


8.9. Crear un nuevo proyecto.
En visual cada aplicación que creamos necesita de un directorio donde se depositan todos los elementos que lo
componen, como en otras aplicaciones,
Cada uno de estas aplicaciones se denominan proyectos o soluciones.
El archivo que arranca cada solución posee la extensión .SLN y esta en el directorio que se crea para la aplicación.

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.

Esto es lo que veremos cuando finaliza el asistente.

El código que escribiremos lo ubicaremos dentro del Main.


Más adelante iremos mejorando nuestras estructuras.

En éste punto podríamos añadir unas líneas de código:

Dim dato1, dato2, resultado As Integer

dato1 = 20
dato2 = 10

resultado = dato1 + dato2

System.Console.WriteLine("dato1 + dato2 = " & resultado)

Por lo que nuestro programa quedaría:

Module Module1

Sub Main()
Dim dato1, dato2, resultado As Integer

dato1 = 20
dato2 = 10

resultado = dato1 + dato2

System.Console.WriteLine("dato1 + dato2 = " & resultado)


System.Console.ReadKey()
End Sub

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

resultado = dato1 + dato2

System.Console.WriteLine("dato1 + dato2 = " & resultado)


System.Console.ReadKey()
End Sub

End Module
Pero solo es cuestión de estilo.

Pág. 8.3

Unidad 8. VB Studio Net 2005 (IV)


8.10. Estructura de un programa VB.
Independientemente del lenguaje que utilicemos para programar, todos los programas tienen un punto de inicio, una fase de ejecución y
una finalización.

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.

Comentemos las líneas de nuestro ejemplo:

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.

Dim dato1 As Integer


Dim dato2 As Integer
Dim resultado As Integer
Declaramos las tres variables del ejemplo como enteras.

dato1 = 20
dato2 = 10
resultado = dato1 + dato2
Asignamos unos datos y realizamos la operación de suma.

System.Console.WriteLine("dato1 + dato2 = " & resultado)


El “&” lo que consigue es unir el texto entre comillas y el valor de la variable resultado en una sola frase.

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.

Para visualizar el resultado.

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.

8.11. Ejecutar el programa.


Si pulsamos en la barra de herramientas el símbolo del Play, , o pulsamos F5, veremos el
resultado de la ejecución del programa.

43
En la imagen vemos el resultado de la ejecución.
Pág. 8.4

Unidad 8. VB Studio Net 2005 (V)


8.12. Añadir una clase.
La resolución de los ejercicios deberíamos realizarla utilizando clases, de esa forma nos habituamos a un sistema de programación
adecuado y actual.

El ejemplo anterior se puede resolver como sigue, creando una clase.


Para ello en el menú seleccionamos Proyecto à Agregar clase y le asignamos el nombre que deseemos, en el ejemplo PrimeraClase.
Nos dejará un espacio en blanco creado, en el cual hemos de añadir nuestro código.

Public Class PrimeraClase

End Class
Resolvemos el ejemplo de antes.

Public Class PrimeraClase


Dim D1 As Integer
Dim D2 As Integer

Sub New(ByVal Dato1 As Integer, ByVal Dato2 As Integer)


Select Case Dato1 = 0 Or Dato2 = 0
Case True
System.Console.WriteLine("Valores del objeto incorrectos")
Case Else
D1 = Dato1
D2 = Dato2
End Select
End Sub

Public Sub Sumar()


Dim Resultado As Integer
Resultado = D1 + D2
System.Console.WriteLine("dato1 + dato2 = " & Resultado)
System.Console.ReadKey()
End Sub
End Class
En el siguiente tema se explica más a fondo la estructura de la clase.

8.13. Renombrar una clase.


Con modificar el nombre en el fuente del programa es suficiente.
Pero eso no modifica todas las apariciones de la clase en el programa, para ello hay que utilizar las
opciones del menú de edición.

Edición à Reemplazo rápido

Y actuar como pide el formulario que aparece en la imagen.


8.14. Eliminar una clase del proyecto.
Podemos hacerlo en el explorador de soluciones sin ningún problema

Pág. 8.5

Unidad 9. Procedimientos (I)


9.1. Objetivos del tema.
Visto y nombrado los elementos de un programa y sus estructuras, así como la forma de representar las soluciones, ahora hemos de
profundizar sobre el uso de los procedimientos, el paso de parámetros y sus características.
Los veremos desde el punto de vista genérico, sin entrar en lenguajes en concreto.
9.2. Introducción.
Un programa es una estructura más o menos compleja, en función del tamaño del mismo.
Pero el código que lo compone no puede estar todo en el Main del mismo, sería difícil de entender y de modificar, además de muy largo,
por lo tanto conviene trocear.
Si recordamos el ejercicio del primer tema, ese es el camino, pequeños trozos de programa, fáciles de escribir y de modificar.
9.3. ¿Procedimientos o funciones?

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.

Si creamos procedimientos sin dependencias del programa en el que se ubican,


podemos cambiarlo de aplicación para aprovecharlo sin necesidad de reescribirlo, porque
todos los datos que figuran en su interior tienen como origen su línea de parámetros, y no
existe otra forma de comunicación. Así no pueden haber sorpresas.

Un procedimiento es un elemento de nuestro programa, este elemento puede recibir o


no datos y devolver o no datos.
Pág. 9.1

Unidad 9. Procedimientos (II)


9.5. Ámbito de los procedimientos.
El ámbito de influencia de un procedimiento puede ser diverso, y su forma de utilizarse dependerá del lenguaje utilizado.
En éste ejemplo, el programa sabe que hay un procedimiento, A, pero desconoce lo que hay en su interior, eso es conocido solo por el
procedimiento A.

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.

9.6. Ambito de validez de las variables.


Con las variables sucede algo parecido, y además es muy importante que se usen adecuadamente, para evitar errores, aprovechar los
recursos al máximo, y también para facilitar el modificación y comprensión del programa.

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.

Si nosotros diseñamos un procedimiento, éste tendrá unas necesidades de datos.


Esos datos serán propios o externos, los propios no hay problema, pero los externos hemos de facilitárselos, para ello hay unas normas.
El envío y recepción han de realizarse en el mismo orden y con el mismo tipo de datos.
Si vemos el ejemplo, vemos que ambas coinciden en el color, digamos que sea el tipo, son del mismo tamaño, digamos que sea el dato que se
envía.

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.

Pero eso es una excepción.

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

Unidad 9. Procedimientos (III)


9.8. Formas de paso de datos a los procedimientos.
Hay dos formas de pasar los datos a los procedimientos y funciones, por valor y por referencia.

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.

9.9. Uso de variables en los procedimientos.


El uso de variables en los procedimientos y funciones no requiere de ningún requisito que se distinga
del que se haga en el programa principal, ni por nombres, ni por ningún otro apartado que no sea lo que ha
se ha expuesto en cuanto a tipos, ámbito y envío.
9.10. Públicos o privados.
No estamos hablando de empresas, si no de los procedimientos.
Los procedimientos pueden ser públicos o privados, dependerá del ámbito en el cual deseamos que
sean utilizados.
Cuando el procedimiento se desea utilizar solo en el programa actual, y que no sea llamado desde
otro programa, se declaran como privados, “Private”.
Cuando el procedimiento deseamos que sea algo de utilización genérica desde cualquier punto de la
aplicación entonces lo declaramos como público, “Public”.
Normalmente los procedimientos públicos suelen agruparse en módulos fuera del programa, y
agruparlos por temas, lo cual permite tener el código ordenado y fácilmente accesible.
Cuando desarrollamos una clase, el procedimiento o función que se declara como público, suele ser,
se convierte en un método que el usuario puede utilizar en su objeto.

Pág. 9.3

Unidad 10. Primer programa en VB, procedimientos (I)


10.1. Objetivos del tema.
Visto como se inicia en VB un programa, veamos ahora como resolver un ejercicio, basándonos en el uso de procedimientos.
10.2. Introducción.
A la hora de programar, podemos optar por varias soluciones, programación clásica o con objetos.
Actualmente lo adecuado es utilizar objetos, por lo tanto deberíamos elegir ese camino, pero es una decisión personal e intransferible.
Si nos aclaramos mejor con procedimientos y funciones, sin profundizar en clases, podemos plantearnos las clases como un segundo
nivel, al que intentar llegar después.
Pero el camino es el de empezar por los procedimientos, ya que como se ha comentado, un método es un procedimiento o una función.
10.3. Primer ejercicio.
Tomemos como punto de partida el del ejemplo del tema anterior, creemos un proyecto del tipo consola y démosle un nombre.

Archivo à Nuevo proyecto, de la barra de herramientas.

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.

Aparecerá la ventana vacía a la que añadimos el código.

Por lo que nuestro programa quedaría:

Module Module1

47
Sub Main()
Dim dato1 As Integer
Dim dato2 As Integer
Dim resultado As Integer

dato1 = 20
dato2 = 10

resultado = dato1 + dato2

System.Console.WriteLine("dato1 + dato2 = " & resultado)


System.Console.ReadKey()
End Sub
End Module
Tal cual lo vemos funciona, y el ejercicio quedaría resuelto, pero vamos un poco más allá.

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.

Apliquemos lo que hemos visto de los procedimientos.


Pág. 10.1

Unidad 10. Primer programa en VB, procedimientos (II)


10.4. Parámetros en los procedimientos.
El nombre que se le da a la línea de entrada en un procedimiento es de parámetros, línea de entrada, etc…

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.

Private Sub Procedimento(ByVal D1 As Integer, ByVal D2 As Integer)


Dim resultado As Integer

resultado = D1 + D2

System.Console.WriteLine("Dato1 + Dato2 = {0} " , resultado)


System.Console.ReadKey()
End Sub
Al procedimiento después hay que llamarlo para que se ejecute desde el programa principal, y por lo tanto también tiene que enviarse las
variables que se supone tiene que recibir en la línea de entrada al mismo.

Procedimiento(dato1,dato2)
En el programa principal, dichas variables deberán estar declaradas para poderse utilizar.

Dim dato1 As Integer


Dim dato2 As Integer

Ahora veamos la solución completa con los cambios.

Module Module1
Private Sub Procedimiento(ByVal D1 As Integer, ByVal D2 As Integer)
Dim resultado As Integer

resultado = D1 + D2

System.Console.WriteLine("dato1 + dato2 = {0} ", resultado)


System.Console.ReadKey()
End Sub

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

Unidad 10. Primer programa en VB, procedimientos (III)


10.5. Estructuras en los procedimientos.
Todas las estructuras que hemos visto, o sea las tres que hay, son de aplicación en el interior de un procedimiento, pero nos falta ver cual
es su sintaxis, así que empecemos por ahí.
1 Estructuras alternativas.
Una estructura alternativa es una instrucción en la que se puede ejecutar una de entre varias posibilidades, la más sencilla es del tipo If.

if (Expresión) Then dat1 = dato

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.

if (dato > 0) then


dat1 = dato
else
dat1 = 25
end if

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

Select case Mes


case 1: nombremes = "Enero"
case 2: nombremes = "Febrero"
case 3: nombremes = "Marzo"
.. / ..
case 12: nombremes = "Diciembre"
Case Else
NombreMes = "Incorreccto"

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.

Select Case valor


case -1
Console.writeline("No existe")
Case else
Console.writeline("Encontrado en la posición {0} " , valor)
End Select
Las estructuras alternativas pueden ir anidadas una en el interior de otra hasta alcanzar el nivel necesario para resolver la estructura que
se nos presenta.

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

Unidad 10. Primer programa en VB, procedimientos (IV)


2 Estructuras repetitivas.
Como mencionamos en su momento, disponemos de dos tipos de bucles, el de tipo Repite y el de tipo Mientras, vamos a
ver dichas instrucciones.
El bucle repite es una estructura en la que siempre se ejecutará un paso en el ciclo del bucle, dado que no existe ningún
impedimento que impida la entrada en el mismo.

El control de la estructura está al final del mismo.


Si observamos la imagen podemos observar como el símbolo en forma de rombo, que es el que indica el control del bucle
está situado al final de la estructura, y al principio solo hay instrucciones.

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.

While expresión de condición

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

Unidad 10. Primer programa en VB, procedimientos (V)


3 Estructuras secuenciales.
Vistas las dos anteriores, una estructura secuencial no es más que una ejecución lineal de un número indeterminado de instrucciones, sin
que medie una estructura alternativa o repetitiva, podría ser como ejemplo el siguiente.

instrucción
instrucción
instrucción

51
Como ejemplo podríamos poner:

Console.writeln(x) // Visualizar datos por pantalla


x = x + 1 // Incremento de un contador
s = s + x // Acumulador
10.6. Conclusiones.
Hemos visto como se inicia un programa en VB, las distintas estructuras que se utilizan en programación, como se escriben y su uso
dentro de los procedimientos, falta ver las funciones.

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.

Ejercicios propuestos de la Unidad


Pág. 10.5
Ejercicios unidad 10: Primer programa en VB, procedimientos
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º 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.
4º Visualizar los números entre 10 y 20.
5º Visualizar los números entre 10 y 20 y sumarlos.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.


Ayuda ejercicios unidad 10: Primer programa en VB, procedimientos
Dado que estructuralmente los ejercicios están resueltos, exponemos solo el código de los mismos.

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

System.Console.WriteLine("dato1 + dato2 = {0} ", resultado)


System.Console.ReadKey()
End Sub

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.

O bien por realizar el siguiente cambio, en la barra de Menú seleccionar la opción


Proyecto  Propiedades.
Y a continuación, seleccionar la pestaña de compilar y en la opción Option Strict que está en On, cambiarlo a Off.

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 .

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()

Console.Write(" ¿ Cual es el radio ? ")


Radio = CDbl(Console.ReadLine())

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.

Private Sub Tres(A As Long, B As Long)


Select Case A
Case Is > B
Console.WriteLine("{0} es mayor que {1} y la división es {2} ", A, B, A /
B)
Case Is < B
Console.WriteLine("{0} es menor que {1} y la multiplicación es {2} ", A,
B, A * B)
Case Is = B
Console.WriteLine("{0} es igual que {1} y la suma es {2} ", A, B, A + B)
End Select
Console.WriteLine()
Console.Write("Pulse cualquier tecla para finalizar ... ")
Console.Read()
End Sub
Y en el Main

Sub Main
Dim A As Long
Dim B As Long

Console.WriteLine("Calcular con dos números A y B")


Console.WriteLine()

Console.Write("Introduce un número A ")


A = CLng(Console.ReadLine())
Console.Write("Introduce un número B ")
B = CLng(Console.ReadLine())

Tres(A,B)
53
End Sub
4º Visualizar los números entre 10 y 20
Private Sub Cuatro()
Dim X As Integer

Console.WriteLine("Visualizar los números entre 10 y 20.")


Console.WriteLine()

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

Console.WriteLine("Visualizar los números entre 10 y 20 y sumarlos")


Console.WriteLine()
Suma = 0
X = 10
Do
Console.WriteLine(X)
Suma = Suma + X
X = X + 1
Loop Until X > 20

Console.WriteLine("El valor de la suma es {0} ", Suma)


Console.WriteLine()
Console.Write("Pulse cualquier tecla para continuar ... ")
Console.Read()
End Sub

CAMBIAR DE SITIO EL INCREMENTO, EL VALOR INICIAL DE X Y LA CONDICION

Private Sub Cinco()


Dim Suma As Long
Dim X As Integer

Console.WriteLine("Visualizar los números entre 10 y 20 y sumarlos")


Console.WriteLine()
Suma = 0
X = 9
Do
X = X + 1
Console.WriteLine(X)
Suma = Suma + X
Loop Until X = 20
54
Console.WriteLine("El valor de la suma es {0} ", Suma)
Console.WriteLine()
Console.Write("Pulse cualquier tecla para continuar ... ")
Console.Read()
End Sub
Y en el Main
Sub Main
Cinco()
End Sub
En éste ejercicio se ha optado por agrupar todo el código en el procedimiento.

Unidad 11. Funciones (I)


11.1. Objetivos del tema.
Visto y nombrado los elementos de un programa y sus estructuras, así como la forma de representar las soluciones y el uso de
procedimientos, ahora hemos de profundizar sobre el uso de las funciones, el paso de parámetros y sus características.
Las veremos desde el punto de vista genérico, sin entrar en lenguajes en concreto.
11.2. Introducción.
Un programa es una estructura más o menos compleja, en función del tamaño del mismo.
Pero el código que lo compone no puede estar todo en el Main del mismo, sería difícil de entender y de modificar, además de muy largo,
por lo tanto conviene trocear.
Si recordamos el ejercicio del primer tema, ese es el camino, pequeños “trozos” de programa, fáciles de escribir y de modificar.
Y la solución era el dividir el programa y crear procedimientos.
Ahora vamos a ver las funciones, pero las funciones a pesar de que en su interior pueden albergar el mismo tipo de estructuras que un
procedimiento, tienen un fin distinto dentro de un programa.
11.3. Creación.
Hay una máxima que sí podría servir, y es que en el momento en que en el programa aparece código repetido, ya podemos empezar a
pensar en la creación de una función o un procedimiento, según corresponda.
También hay que tener en cuenta que la llamada a una función o un procedimiento consume recursos y tiempo de ejecución, pero en la
actualidad se piensa poco en esos parámetros.
Resolver de forma recursiva el factorial de un número es “bonito”, pero ¿y si el número es algo grande?
Con un procedimiento resuelvo el programa y voy creando la estructura del mismo.
Una función es un “trozo” de código especializado en hacer algo en concreto, por ejemplo, el ejercicio del área de un triangulo o de una
circunferencia, se resolvió mediante un procedimiento, pero su solución correcta es la de una función, ¿por qué?, pues normalmente el área del
triangulo es un dato que voy a calcular y que puede aparecer hasta en una expresión habitualmente.

Si utilizo procedimientos, la solución puede ser algo así:

Altura = 5
Base = 10
AreaTriangulo(Base,Altura,Area)

Escribe “El área del triangulo es “, Area


Esta es la solución con un procedimiento, ejecutamos el procedimiento y nos devuelve un dato llamado Area, que lo usamos en el texto de
informe al usuario.

Escribe “El área del triangulo es “, AreaTriangulo(Base,Altura)


Como podemos ver con una función es mucho más “elegante” el código resultante.

¿Cuando escribir una función o un procedimiento?, en el ejemplo podemos ver un criterio.


Un procedimiento es una línea de mi programa, lo llamo y se ejecuta, resuelvo el problema estructural
del programa con ellos.
Una función forma parte de una instrucción, una función siempre devuelve un dato, un procedimiento
no tiene porque hacerlo.

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

Unidad 11. Funciones (II)


11.6. Ámbito de las funciones.
El ámbito de una función va ligado al punto en el cual se utiliza y como se declara, igual que con los procedimientos.

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.

Si nosotros diseñamos un procedimiento, éste tendrá unas necesidades de datos.


Esos datos serán propios o externos, los propios no hay problema, pero los externos hemos de facilitárselos, para ello hay unas normas.
El envío y recepción han de realizarse en el mismo orden y con el mismo tipo de datos.
Si vemos el ejemplo, vemos que ambas coinciden en el color, digamos que sea el tipo, son del mismo tamaño, digamos que sea el dato que se
envía.
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.

Pero eso es una excepción.


11.8. Formas de paso de datos a las funciones.
Hay dos formas de pasar los datos a los procedimientos y funciones, por valor y por referencia.

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

Unidad 11. Funciones (III)


11.9. Estructura de una función.
Al igual que en un procedimiento, podemos utilizar todas las estructuras que conocemos.
Pero hemos de añadir algo que en un procedimiento quizás no es tan riguroso.
Hay que asegurarse que los datos que vamos a utilizar son válidos, por lo tanto debemos comprobar
su validez antes de entrar en lo que es el cuerpo de la función.
Por otro lado en función del lenguaje utilizado, podremos utilizar o no el nombre de la función en la
misma varias veces.

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

Unidad 12. Funciones en VB (I)


12.1. Objetivos del tema.
Vamos a ver en este tema las funciones en el lenguaje Visual Basic 2005.
12.2. Introducción.
La programación está basada en las estructuras.
Estructuras de datos y estructuras de programas.
Los programas son a su vez contenedores de estructuras de elementos individuales que ejecutan código.
El elemento más pequeño es la instrucción.
Después nos encontramos con procedimientos y funciones.
El siguiente nivel es la clase y por último el programa.

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.

Console.Writeline(“Factorial de 3 es " ,FuncionFactorial(3))


Pero no toda la resolución de una clase se realiza mediante código que se pueda o se tenga que traducir en un método.
La programación además se basa en la división de un problema grande, en varios pequeños, aquello de divide y vencerás, por lo que por
esa misma filosofía es imposible, e ilógico, que todo se convierta en métodos.
Los métodos son la parte lógica visible de una clase, lógica en cuanto a que es aquello que cara al usuario le ayuda a resolver un
problema en pasos “ comprensibles “ para él.

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.

Para crear una función la sintaxis es la siguiente:

Private Function FuncionFactorial(ByVal n As Integer) As Integer


La función puede estar en el programa Private
o en un módulo distinto, Public
La palabra reservada que indica que es una función Function
Después lo que sigue es el nombre de la función, FuncionFactorial
Entre paréntesis los datos que se reciben, indicando el tipo de cada uno de ellos, (ByVal n as Integer)
El tipo de dato que se devuelve en la función, Integer
A continuación empieza el código de la función que acaba con la línea End Function.

Private Function FuncionFactorial(ByVal n As Integer) As Integer


If (n <= 1) Then
FuncionFactorial = 1
Else
FuncionFactorial = n * FuncionFactorial(n - 1)
End If
End Function
En el ejemplo vemos la función, esta función calcula el factorial de un número, otro tema es que sea la mejor solución, pero es una
función.

En el siguiente ejemplo se invierte el contenido de una variable de tipo string.

Public Function InvierteCadena(ByVal Cadena As String) As String


Dim Result As String = ""
Dim x As Integer

While x <> Len(Cadena)


x = x + 1
Result = Mid(Cadena, x, 1) & Result
End While
InvierteCadena = Result
End Function
El uso de la función anterior puede quedar :

Cadena = InvierteCadena(Cadena)
Pág. 12.1

Unidad 12. Funciones en VB (II)


12.3. Escribir la función.
Vemos el ejemplo de una función.
Como hemos comentado antes, primero se indica el ámbito de la función, público o privada, después la palabra que índica que es una
función, no un procedimiento.

Public Function InvierteCadena(ByVal Cadena As String) As String


Dim Result As String = ""
Dim x As Integer

While x <> Len(Cadena)


x = x + 1
Result = Mid(Cadena, x, 1) & Result
End While
InvierteCadena = Result
End Function
El nombre de la función “InvierteCadena” y los argumentos que va a recibir, Cadena como string, y se recibe por valor, en VB hay que
indicarlo, por defecto aparecerá siempre por valor, ByVal.

Después se inicia el código de la función

Dim Result As String = ""


Dim x As Integer

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.

Private Function FuncionFactorial(ByVal n As Integer) As Integer

Public Function InvierteCadena(ByVal Cadena As String) As String

12.4. Envío y recepción de los datos.


La creación de procedimientos y funciones, conlleva la necesidad de envío y recepción de variables, de datos. Hay dos formas de enviar
datos a un procedimiento,

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:

Private Function InvierteCadena(ByVal Cadena As String, ByRef R As String) As


String
Dim Result As String = ""
Dim x As Integer

While x <> Len(Cadena)


x = x + 1
Result = Mid(Cadena, x, 1) & Result
End While
InvierteCadena = Result
R = Result
End Function
En este ejemplo, se ha añadido a la función la variable

, 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))

Console.WriteLine("La cadena invertida {0} es {1} ", C, R)


Console.ReadKey()
End Sub
es el que sigue:

Valor por referencia en una función


La cadena invertida ARROZ es ZORRA
La cadena invertida ARROZ es ZORRA
Y como se puede comprobar, la función solo se ejecuta una vez.
Pero a pesar de eso, no debemos utilizar esta estrategia, una función debe devolver el dato en su nombre.
12.5. Conclusiones.
El paso de datos se puede hacer por valor y por referencia,
Los datos han de enviarse en el mismo orden en el que se reciben en la función.
Han de ser del mismo tipo.
No tienen porque llamarse de la misma forma.
No hay valores opcionales.

Ejercicios propuestos de la Unidad


Pág. 12.2
Ejercicios unidad 12: Funciones en VB
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

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.

Ayuda ejercicios unidad 12: Funciones en VB


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 .

Module Module1

Private Function AreaCirculo(ByVal Radio As Double) As Double


AreaCirculo = Radio * Radio * 3.1415
End Function
60
Private Function LongitudCirculo(ByVal Radio As Double) As Double
LongitudCirculo = Radio * 2 * 3.1415
End Function

Sub Main()
Dim Radio As Double

Console.WriteLine("Cálculo del área y longitud de un circulo")


Radio = Console.ReadLine
Console.WriteLine("Area de radio {0} es {1} ", Radio,
AreaCirculo(Radio))
Console.WriteLine("Longitud radio {0} es {1} ", Radio,
LongitudCirculo(Radio))
Console.ReadKey()
End Sub
End Module
2.- Hallar el área de un triángulo. Area = Base por Altura / 2.

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.WriteLine("Cálculo del área de un triángulo")


Console.WriteLine("Introducir Base")
Base = Console.ReadLine
Console.WriteLine("Introducir Altura")
Altura = Console.ReadLine
Console.WriteLine("Area triángulo de base {0} y altura {1} es {2} ", Base,
Altura, AreaTriangulo(Base, Altura))

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

Select Case Numero Mod 2 <> 0


Case True
Final = CLng(Numero / 2) + 1
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

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

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

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

Console.WriteLine("Convertir moneda ")


Console.WriteLine("Introducir pesetas")
Pesetas = Console.ReadLine
Console.WriteLine("Introducir moneda F/L/I/D/M/S/H/P")
Moneda = Console.ReadLine
Console.WriteLine("El importe de {0} pesetas en la moneda {1} es {2} ",
Pesetas, Moneda, ConversionMoneda(Pesetas, Moneda))
Console.ReadKey()
End Sub
End Module
Las soluciones por las que se ha optado son mejorables, y solo pretenden ilustrar como abordar una función.

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.

En función de cómo se tenga configurado VB, las líneas del tipo

Result = CSng(Pesetas / 101.755)


C = CSng(M / 1609.34)

64
Pueden funcionar también con esta sintaxis.

Result = Pesetas / 101.755


C = M / 1609.34
CSng, CDbl, Cint, etc, son funciones de conversión de un valor numérico a un valor determinado, Single, doble, entero etc..

Ello viene obligado por la definición del parámetro Option Strict, para acceder al mismo

Proyecto  Propiedades  Compilar

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.

Unidad 13. Las clases en los datos (I)


13.1. Objetivos del tema.
Vistos los procedimientos y las funciones, así como las estructuras dentro de los mismos, veremos ahora
las clases.

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

Unidad 13. Las clases en los datos (II)


13.4. Datos internos, variables.
Cuando los datos son nada más que datos internos, esos datos son variables y ahí queda el tema.

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

Metodo Nuevo(Inicio como entera, Final Como entera)


Si Inicio < Final Entonces
X = Inicio
Y = Final
Si no
X = 0
Y = 0
Fin condicion
Fin Metodo
Fin Clase

Inicio de Programa
Crear Objeto como Ejemplo
Objeto = Nueva instancia de Ejemplo(1,20)
Fin de Programa
Cuando ejecutamos …

Objeto = Nueva instancia de Ejemplo(1,20)


Lo que se está haciendo es crear una instancia de la clase y enviarle los datos que se piden en la creación de la misma, en este caso 1
para el valor de Inicio y 20 para el valor Final.

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

Metodo Cuenta(Inicio como entera, Final Como entera)


Si Inicio < Final Entonces
X = Inicio
Mientras X <> Final
...
...
X = X + 1
Fin Mientras
Fin condicion
Fin Metodo
Fin Clase
Con la versión que observamos en la versión del método Cuenta, lo que se hace es pedir los valores de Inicio y Final en el momento de su
ejecución.

Metodo Cuenta(Inicio como entera, Final Como entera)


En el uso del método, se observa como se cargan dichos valores en su utilización.

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

Unidad 13. Las clases en los datos (III)


13.5. Datos externos, propiedades.
Sin embargo cuando los datos son visibles desde el exterior de la clase, esos datos se convierten en propiedades, que a su vez podrán o
no ser modificadas por el usuario de la misma.
Estas variables pueden denominarse Públicas, Public, directamente, o bien Propiedad, Property, dependerá del lenguaje de programación
en cuestión.

Siguiendo con el ejemplo anterior, la clase podría tener este aspecto.

Clase Ejemplo
Crear X Entera
Crear Y Entera

Crear Z Entera

Propiedad Inicio Entera


Lectura
Y = Inicio
Escritura
Inicio = Y
Fin propiedad

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

Pero también podrían haberse declarado

Publica Crear Y Entera


Publica Crear Z Entera
Y en ese caso podrían utilizarse desde el objeto que se cree con la clase en cuestión.

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

Unidad 13. Las clases en los datos (IV)


13.6. Ambito de los datos.
Hemos indicado que los datos eran internos y externos, pero una vez dentro de lo que es la clase como tal, hay que tener presente que en
la misma se escriben métodos, compuestos por funciones y procedimientos, y que estos a su vez pueden tener variables en su interior, estas
variables que se declaran en el interior de un método, no son visibles por el resto de la clase.

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.

Variables clasificadas en dos bloques.

Las que se utilizan para consumo interno.


Las que representan datos que han de ser facilitados desde el programa.

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.

Las variables declaradas en el método, no son visibles desde la clase.


Las variables declaradas en la clase, si son visibles en el método.

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.

Elegimos Archivo à Nuevo proyecto y seleccionamos aplicación de consola.


Después Proyecto à Agregar Clase y seleccionamos el icono de clase como vemos en
la imagen.

La podemos dejar con el nombre que tiene, o cambiarlo, nosotros la llamaremos


ejemplo.
Y ahora a utilizarla.

14.4. El objeto.
Primero creemos el objeto.
Nuestra clase ahora es así.

Public Class Ejemplo

End Class
Ahora creamos un objeto de esa clase.

Dim Objeto As Ejemplo


Si ahora escribimos en nuestro programa

Objeto.
Si vemos la imagen, ese es el resultado, son los métodos estándar de cualquier objeto.

Pero como no hemos escrito nada nuestro, no vemos nada.


14.5. Los datos.
Hemos comentado que eran de dos tipos

Internos.
Externos.

Veamos como definir los datos internos en la clase, es decir los que no se ven en el exterior.

Public Class Ejemplo


Dim DatoInterno As String
Private OtroInterno As Integer
End Class
Si ahora escribimos en nuestro programa

Dim Objeto as Ejemplo


Objeto.
Si vemos la imagen, ese es el resultado, son los métodos estándar de cualquier objeto.

69
Exactamente lo mismo que antes, como los datos son internos no se ven fuera de la clase.
Ahora externos, o sea, propiedades.

Public Class Ejemplo


Dim DatoInterno As String
Private OtroInterno As Integer
Public DatoExterno As String
End Class
Si ahora escribimos en nuestro programa

Dim Objeto as Ejemplo


Objeto.
Si vemos la imagen, ese es el resultado, son los métodos estándar de cualquier objeto, pero ahora aparece nuestra propiedad, el dato
externo.

Pág. 14.1

Unidad 14. Clases en VB (II)


14.6. Inicializar el objeto.
Para poder utilizar el objeto que hemos creado, éste ha de inicializarse, para ello se utiliza el constructor de la clase.
Para ello existe en Vb el método New, que es el constructor de la clase.

Sub New(ByVal Dato As String) ‘ Constructor de la clase


DatoExterno = Dato
End Sub
La misión del constructor no es solo la de asumir los valores que se reciben en el momento de crear el objeto, si no que también se puede
hacer en ese momento el control de los mismos.

Public Sub New(ByVal Dato As String)


If dato <> “” Then DatoExterno = Dato
End Sub
En el ejemplo se obliga a que el dato recibido sea distinto de nulo para asignarlo a la variable de la clase.

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.

Private Sub New() ‘ impide la creación de instancias de la clase.


End Sub
En el ejemplo que hemos visto, si declaramos como private el constructor anterior, la declaración de un objeto de ésta clase obligaría a
que llevará los dos datos que se piden en la sobre carga.
Explicado de otra forma, así se impide que un objeto se cree sin pasar por el control del constructor correspondiente, ya que al declararse
como private, éste queda bloqueado, anulado o como deseemos decirlo, y siempre se ejecuta el declarado por nosotros como public.
14.7. Creemos un objeto.
El siguiente paso es crear un objeto de esta clase, aunque ya lo hemos hecho, pero de forma más avanzada.

Dim Objeto As Ejemplo


Y ahora asignemos algo al dato externo para probarlo.

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.

Dim Objeto As New Ejemplo


Probemos ahora, y ahora si que funciona, y este sería el resultado.

Contenido de la propiedad

14.8. Cómo gestionar las propiedades, los datos.


Disponemos de un dato, una propiedad que el usuario puede utilizar, y a nosotros nos permite obtener datos para el funcionamiento del
objeto.

Podemos gestionar la obtención de datos de varias formas, podemos:

Obtener datos en la creación del objeto.


Asignar controladamente los datos.
Asignar sin control previo los datos.

1 Obtener datos en la creación del objeto.


Cuando se crea una instancia de un objeto, se ejecuta de forma predeterminada el método new, tema a parte es que lo hayamos escrito o
no.
En ese método nosotros podemos reclamar la inclusión de aquellos datos que creamos oportunos, y en ese mismo momento validarlos.

Public Class Ejemplo


Dim DatoInterno As String
Private OtroInterno As Integer
Public DatoExterno As String

Sub New(ByVal Dato As String)


DatoExterno = Dato
End Sub
End Class
Si añadimos el método new a la clase, tal como esta en el ejemplo superior, en el programa habrá que hacer el siguiente cambio,

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.

Probemos ahora, el código modificado en el programa principal es el que sigue.

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.

Es decir el dato esta formado por dos componentes:

La propiedad que es la parte visible.

71
La variable interna de la clase, que está oculta.

La captura de los datos es como sigue:

La propiedad dispone de la sintaxis siguiente:

Property Propiedad() as String


Get ‘ Lectura
Return DatoInterno
End Get
Set(ByVal value as String) ‘ Asignación
If value <> "" Then DatoInterno = value
End Set
End Property
Podemos observar que dispone de dos partes, una de lectura, Get, y otra de asignación, Set.
En la de lectura se devuelve el dato de la variable que internamente la representa.
En la de asignación, podemos escribir código de control que comprueba que el valor recibido esté dentro de los márgenes que están
previstos.

Set(ByVal value as String) ‘ Asignación


If value <> "" Then DatoInterno = value
End Set
Como vemos, en el ejemplo, solo se admite el dato si es distinto de nulo.
De esta forma podemos admitir o no los datos según nos interese.
Es aconsejable que el valor de la variable esté asignado con un valor por defecto en la creación de la variable, de esa forma se cubre
cualquier posibilidad y siempre dispondremos de unos valores por defecto.

Dim DatoInterno As String = "Valor por defecto"


Y si la inicialización del objeto fuera

Dim Objeto As New Ejemplo("")


Al ejecutarse

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)

Objeto.Propiedad = "" ‘ Se rechaza


Console.WriteLine(Objeto.Propiedad)

Objeto.Propiedad = "Cambio de contenido" ‘ Se admite


Console.WriteLine(Objeto.Propiedad)

Console.ReadKey()
End Sub
Podemos seleccionar una de las dos opciones en la inicialización del objeto:

' Dim Objeto As New Ejemplo("Contenido de la propiedad")


Dim Objeto As New Ejemplo("")
Después podemos observar como se asigna un valor nulo a la propiedad, y que éste se rechaza por no cumplir los requisitos, se visualiza
su contenido que no ha sufrido cambios, y después se asigna un valor que sí es válido, y que sí que se visualiza correctamente.

El resultado de la ejecución sería:

Valor por defecto


72
Valor por defecto
Cambio de contenido
Y la clase completa sería:

Public Class Ejemplo


Dim DatoInterno As String = "Valor por defecto"
Private OtroInterno As Integer
Public DatoExterno As String

Property Propiedad() as String


Get
Return DatoInterno
End Get
Set(ByVal value as String)
If value <> "" Then DatoInterno = value
End Set
End Property

Sub New(ByVal Dato As String)


DatoInterno = Dato
End Sub
End Class
Pág. 14.3

Unidad 14. Clases en VB (IV)


3 Asignar sin control previo los datos.
La asignación sin control de los datos puede realizarse tanto en la propiedad, como en la variable.
En la propiedad podemos observar que hemos eliminado el código de validación, y que solo queda la asignación:

Set(ByVal value as String)


DatoInterno = value ‘ Asignación
End Set
La propiedad quedaría pues, de esta forma:

Property Propiedad() as String


Get
Return DatoInterno ‘ Lectura
End Get
Set(ByVal value as String)
DatoInterno = value ‘ Asignación
End Set
End Property
La otra posibilidad es la de declarar como variable pública el dato a utilizar y el usuario puede asignar valores de forma libre.

Public DatoExterno As String


Evidentemente sería adecuado que esa variable fuera inicializada, para de esa forma evitar o reducir problemas.

Public DatoExterno As String = “Valor por defecto”


Con éste programa

Sub Main()
Dim Objeto As New Ejemplo("Contenido de la propiedad")

Console.WriteLine(Objeto.DatoExterno)

Objeto.DatoExterno = ""
Console.WriteLine(Objeto.DatoExterno)

Objeto.DatoExterno = "Nuevo valor"


Console.WriteLine(Objeto.DatoExterno)

73
Console.ReadKey()
End Sub
La ejecución quedaría como sigue:

Valor por defecto

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:

Public Class Ejemplo


Dim DatoInterno As String = "Valor por defecto"
Private OtroInterno As Integer
Public DatoExterno As String = "Valor por defecto"

Property Propiedad() as String


Get
Return DatoInterno ' Lectura
End Get
Set(ByVal value as String)
DatoInterno = value ' Asignación
End Set
End Property

Sub New(ByVal Dato As String)


If Dato <> "" Then DatoInterno = Dato
End Sub
End Class

14.9. Propiedades solo lectura.


Se trata con ésta opción de disponer solo de la posibilidad de utilizar los valores de una propiedad pero no permitir su modificación por
parte del usuario de la clase, del objeto.
Para ello utilizamos la siguiente sintaxis.

ReadOnly Property Propiedad()


Get
Return DatoInterno ' Lectura
End Get
End Property
Podemos comprobar como desaparece la parte de asignación, Set, y además si intentamos escribirla nos dará error de sintaxis.
14.10. Propiedades solo escritura.
Se trata del caso contrario, permitir que solo pueda asignarse datos pero no su visualización, su lectura.

WriteOnly Property Propiedad() as String


Set(ByVal value as String)
DatoInterno = value ' Asignación
End Set
End Property
14.11. Utilizar los datos, las propiedades.
El uso de la propiedad es como en el resto de casos en los que utilizamos una variable, con las restricciones expuestas de lectura y
escritura, pero no hay cambios, se pueden usar como una variable más.
Precauciones a tomar, tener presente que los cambios en una propiedad, afectan al objeto del cual depende, y si tenemos varios objetos
de la misma clase, estar seguros sobre cual hacemos los cambios, o cual es el que estamos utilizando.
14.12. Clase como estructura de datos.
Es posible crear una clase de la que se deriven objetos que únicamente contienen datos, información y también la de crear una estructura
válida con la misma.
14.13. Conclusiones.
Hemos visto el uso de los datos en una clase, propiedades, variables públicas, sus condiciones de uso y la forma de controlar los datos.
Lo principal es tener presente que es muy útil declarar las variables inicializadas a valores que sean prácticos para el uso por defecto del
objeto.
Pero, además exigir en el método new, el constructor, la inserción de los datos que sean necesarios para la inicialización del objeto.
74
Ejercicios propuestos de la Unidad
Pág. 14.4
Ejercicios unidad 14: Clases en VB
1º Crear una clase en la que dispongamos de:
Una variable privada,
Una variable pública.
Una propiedad y su variable interna.
Una propiedad solo lectura, y su variable interna.
Una propiedad solo asignación, y su variable interna.

2º A la clase anterior asignar datos a las variables en su declaración.


Modificar los contenidos de esas variables a través de sus propiedades, realizando un control en función del tipo de dato a
introducir.
Visualizar los contenidos antes y después de los cambios.

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.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.

Ayuda ejercicios unidad 14: Clases en VB


1º Crear una clase en la que dispongamos de:
Una variable privada,
Una variable pública.
Una propiedad y su variable interna.
Una propiedad solo lectura, y su variable interna.
Una propiedad solo asignación, y su variable interna.

Public Class Ejercicio


Dim Variable As String = "Valor por defecto"
Public DatoExterno As String = "Valor por defecto"
Dim Propie As String
Dim PropieLectura As Integer
Dim PropieAsignac As String

Property Propiedad() as String


Get
Return Propie ' Lectura
End Get
Set(ByVal value as String)
Propie = value ' Asignación
End Set
End Property

WriteOnly Property PropiedadAsignacion() as String


Set(ByVal value as String)
PropieAsignac = value ' Asignación
End Set
End Property

ReadOnly Property PropiedadLectura() as Integer


Get
Return PropieLectura ' Lectura
End Get
End Property
End Class
2º A la clase anterior asignar datos a las variables en su declaración.
Modificar los contenidos de esas variables a través de sus propiedades, realizando un control en función del tipo de dato a
introducir.
Visualizar los contenidos antes y después de los cambios.

Public Class Ejercicio


Dim Variable As String = "Valor por defecto"
Public DatoExterno As String = "Valor por defecto"

75
Dim Propie As String = "Valor por defecto"
Dim PropieLectura As Integer = 3
Dim PropieAsignac As String = "Valor por defecto"

Property Propiedad() As String


Get
Return Propie ' Lectura
End Get
Set(ByVal value As String)
If value <> "" Then Propie = value ' Asignación
End Set
End Property

WriteOnly Property PropiedadAsignacion() As String


Set(ByVal value As String)
If value <> "" Then PropieAsignac = value ' Asignación
End Set
End Property

ReadOnly Property PropiedadLectura() As Integer


Get
Return PropieLectura ' Lectura
End Get
End Property
End Class

Module Module1
Sub Main()
Dim Objeto As New Ejercicio ' ("Nuevo")

Console.WriteLine("Antes {0} ", Objeto.DatoExterno)


Objeto.DatoExterno = "Nuevo dato"
Console.WriteLine("Después {0} ", Objeto.DatoExterno)

Console.WriteLine("Antes {0} ", Objeto.Propiedad)


Objeto.Propiedad = "Nuevo valor"
Console.WriteLine("Después {0} ", Objeto.Propiedad)

Console.WriteLine("Antes {0} ", Objeto.PropiedadLectura)


' no se puede asignar es read only, solo lectura
' Objeto.PropiedadLectura = 25
Console.WriteLine("Después {0} ", Objeto.PropiedadLectura)

' no se puede leer es write Only


' Console.WriteLine("Antes {0} ", Objeto.PropiedadAsignacion)
Objeto.PropiedadAsignacion = "Nuevo valor"
' no se puede leer es write Only
' Console.WriteLine("Después {0} ", Objeto.PropiedadAsignacion)
Console.ReadKey()
End Sub
End Module
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.

Public Class Ejercicio


Dim Variable As String = "Valor por defecto"
Public DatoExterno As String = "Valor por defecto"
Dim Propie As String = "Valor por defecto"
Dim PropieLectura As Integer = 3
Dim PropieAsignac As String = "Valor por defecto"

Property Propiedad() As String

76
Get
Return Propie ' Lectura
End Get
Set(ByVal value As String)
If value <> "" Then Propie = value ' Asignación
End Set
End Property

WriteOnly Property PropiedadAsignacion() As String


Set(ByVal value As String)
If value <> "" Then PropieAsignac = value ' Asignación
End Set
End Property

ReadOnly Property PropiedadLectura() As Integer


Get
Return PropieLectura ' Lectura
End Get
End Property

Sub New(ByVal Prop As String, _


ByVal PropLec As Integer, _
ByVal PropAsig As String)

If Prop <> "" Then Propie = Prop


If PropLec <> 0 Then PropieLectura = PropLec
If PropAsig <> "" Then PropieAsignac = PropAsig

End Sub
End Class

Module Module1
Sub Main()
Dim Objeto As New Ejercicio("Valor prop en new", 23, "Valor PropAsig en
New")

Console.WriteLine("Antes {0} ", Objeto.DatoExterno)


Objeto.DatoExterno = "Nuevo dato"
Console.WriteLine("Después {0} ", Objeto.DatoExterno)

Console.WriteLine("Antes {0} ", Objeto.Propiedad)


Objeto.Propiedad = "Nuevo valor"
Console.WriteLine("Después {0} ", Objeto.Propiedad)

Console.WriteLine("Antes {0} ", Objeto.PropiedadLectura)


' no se puede asignar es read only, solo lectura
' Objeto.PropiedadLectura = 25
Console.WriteLine("Después {0} ", Objeto.PropiedadLectura)

' no se puede leer es write Only


' Console.WriteLine("Antes {0} ", Objeto.PropiedadAsignacion)
Objeto.PropiedadAsignacion = "Nuevo valor"
' no se puede leer es write Only
' Console.WriteLine("Después {0} ", Objeto.PropiedadAsignacion)
Console.ReadKey()
End Sub
End Module
Observar como en la ejecución no se modifica el valor de la propiedad solo lectura.

Unidad 15. Las clases en el código (I)

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.

15.3. Código en la clase.


El código en la clase se distribuye entre las propiedades, los procedimientos, las funciones, los eventos
y los métodos.
En las propiedades, para realizar el control y la validación de los datos que se asignan a las variables
internas de la clase.
En los procedimientos y funciones, para resolver la estructura que debemos crear para que funcione la
clase y cumpla con su cometido.
En los métodos, porque desde ahí se distribuirá la ejecución de los procedimientos y funciones de la clase en función del diseño del
mismo.
En los eventos también dispondremos de código, para que de esa forma se pueda reaccionar en función de lo que sucede a su alrededor.

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.

Las variables disponían de dos posibilidades, podían ser internas y externas.

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.

15.4. En las Propiedades.


Porque en las propiedades en muchas ocasiones hay que filtrar los valores que recibimos, con el fin de que sean coherentes con el
conjunto de datos de la clase, y evitar que se asignen a las variables internas de la clase.
15.5. En las Funciones, Procedimientos.
Para desarrollar una clase es necesario escribir un “pequeño programa”, y ese pequeño programa se compone de una parte pública que
son los métodos.
Estos métodos, podemos decir que son el punto de inicio de una acción, una acción que inicia el programa cuando reclama su presencia,
es decir podríamos decir que una clase tiene un sin fin de puntos de inicio, cada uno de los métodos, - si descartamos el código de las
propiedades -, por lo tanto, como deseamos crear un código sencillo, estructurado y ordenado, es necesario que el código en el método sea
breve.
Para ello el código de un método se compone de llamadas a procedimientos y funciones que se llaman desde el mismo.
Además de esa forma un procedimiento puede compartirse por varios métodos, lo que reduce el volumen de código de la clase.
Así que, en el interior de la clase escribiremos todos los procedimientos y funciones que se necesiten para poder desarrollar todas las
acciones que sean necesarias en los métodos.
15.6. En los Métodos.
En los métodos, porque los procedimientos no se activan solos, y de alguna manera han de activarse, y eso se consigue mediante la
ejecución ordenada del código que hay en cada uno de los métodos.
Hemos dicho que cada método es como un punto de inicio de un programa, pues en ese punto es donde empieza la acción, y ahí es
donde a medida que se van ejecutando las líneas de código, se van escribiendo las llamadas a cada procedimiento.
En el ejemplo de clase que sigue, se ha creado un método que visualiza los números pares entre dos valores determinados.
En ella vemos como el método llama a una función que devolverá cierto o falso en función de que el número sea par o no.

Clase Ejemplo
78
Funcion EsPar(Numero como Entera) Como Booleana
EsPar = Numero Modulo 2 = 0
Fin de Funcion

Metodo NumerosPares(Inicio como entera, Final Como entera)


Crear X Entera = 0
Si Inicio < Final Entonces
X = Inicio
Mientras X <> Final
Si EsPar(X) Entonces
Escribir(“El número “,X,“ es par ”)
Fin de Condicion
X = X + 1
Fin Mientras
Fin Condicion
Fin Metodo
Fin Clase

Inicio Programa
Crear Objeto como Ejemplo
Objeto.NumerosPares(10,50)
Fin programa
Pág. 15.1

Unidad 15. Las clases en el código (II)


15.7. Creamos un método.
Los métodos pueden ser de dos tipos, los que ejecutan una acción y no devuelven ningún dato, o los que como consecuencia de su
ejecución obtenemos una información.
Si tenemos un método que nos escribe los números primos entre uno y cien, este método no devuelve información, si no que lo que hace
es visualizar unos datos.
Sin embargo si tenemos un método que nos devuelve si un número es primo, si que tendrá que devolvernos cierto o falso como
consecuencia de la ejecución.
En el primer caso podemos escribir un procedimiento que visualice en pantalla todos los números primos entre uno y cien, pero en el
segundo caso escribiremos una función que recibirá como argumento un valor numérico entero y que nos devolverá el valor booleano cierto o
falso.
Como ya hemos dicho, los métodos los resolveremos empleando funciones o procedimientos, por lo tanto en su interior escribiremos
código, y el código que se emplea debe ser un código estructurado.
Esto no significa que todos los procedimientos o funciones que se escriben en la clase sean métodos, si no que todos los métodos son
procedimientos o funciones, y cuando los procedimientos o funciones son públicos se convierten en métodos, y si no, se quedan en lo que son,
procedimientos o funciones.
15.8. Métodos, procedimientos.
En el ejemplo vemos como el método Cuenta es utilizado dentro del programa tras declarar una instancia de la clase Ejemplo.

Clase Ejemplo
Crear X Entera = 0
Crear Y Entera = 0
Crear Z Entera = 0

Metodo Cuenta(Inicio como entera, Final Como entera)


Si Inicio < Final Entonces
X = Inicio
Mientras X <> Final
...
...
X = X + 1
Fin Mientras
Fin Condicion
Fin Metodo
Fin Clase

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.

15.9. Métodos, funciones.


Pero si deseamos saber si un número es par, el método nos debe devolver un dato, que puede ser cierto o falso, que nos indicaría que el
número es par o no.

Metodo NumeroPar(Numero como entero, EsPar como booleano)


EsPar = Numero modulo 2 = 0
Fin Metodo
La variable Par tendrá que ser pasada por referencia para poder devolver el valor que toma en el procedimiento.
Si se cumple la expresión, EsPar = Resto de la división de numero entre dos igual a cero, es que el número es par y la variable devolverá
cierto.

El uso en el programa podría ser:

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.

Metodo EsPar(Numero como entero) como Booleano


EsPar = Numero modulo 2 = 0
Fin Metodo
Y así en nuestro programa podremos escribir:

Inicio Programa
Crear Objeto como Ejemplo

Si Objeto.EsPar(10) = Cierto Entonces


Escribir (“El número es par”)
Si no
Escribir (“El número es par”)
Fin de Condicion
Fin programa
Que queda mucho más bonito que la versión anterior, y permite una legibilidad más clara del programa.
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.
15.10. 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.
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.

Los métodos, son programas pequeños.

Pág. 15.2

Unidad 16. Clases, Código en VB (I)


16.1. Objetivos del tema.
Hemos visto los datos en el tema anterior, veamos ahora los métodos.
Veamos ahora los métodos desde VB, y como enfocarlos.
16.2. Introducción.
Los métodos es la zona donde se alberga el código ejecutivo de la clase, código ejecutivo de la clase porque en la captura de datos de las
propiedades también hay código, pero es el dedicado a la validación de dicha captura de datos, y en el constructor, new, también hay código pero
es el encargado de la fase de inicialización de marcar los valores iniciales requeridos en la clase para el objeto.
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.
16.3. Código en las Funciones, Procedimientos.
Para desarrollar una clase es necesario escribir un “pequeño programa”, y ese pequeño programa se compone de una parte pública que
son los métodos.
Estos métodos, podemos decir que son el punto de inicio de una acción, una acción que inicia el programa cuando reclama su presencia,
es decir podríamos decir que una clase tiene un sin fin de puntos de inicio, cada uno de los métodos, además del principal que es el constructor,
en VB new - si descartamos el código de las propiedades -, por lo tanto, como deseamos crear un código sencillo, estructurado y ordenado, es
necesario que el código en el método sea breve.
Para ello el código de un método se compone, o se puede componer, de llamadas a procedimientos y funciones que se llaman desde el
mismo.
Además de esa forma un procedimiento puede compartirse por varios métodos, lo que reduce el volumen de código de la clase.
Así que, en el interior de la clase escribiremos todos los procedimientos y funciones que se necesiten para poder desarrollar todas las
acciones que sean necesarias en los métodos.
Como esos procedimientos y funciones se quedan en eso, no en métodos, se declararan como privadas, los métodos son públicos.
16.4. Código en los Métodos.
En los métodos, porque los procedimientos no se activan solos, y de alguna manera han de activarse, y eso se consigue mediante la
ejecución ordenada del código que hay en cada uno de los métodos.
Hemos dicho que cada método es como un punto de inicio de un programa, pues en ese punto es donde empieza la acción, y ahí es
donde a medida que se van ejecutando las líneas de código, se van escribiendo las llamadas a cada procedimiento.

En el ejemplo de clase que sigue, se ha creado un método que visualiza los números primos entre dos valores determinados.

Public Class Ejemplo


Public Sub NumerosPrimos(ByVal Desde As Integer, ByVal Hasta As Integer)
Dim x As Integer = Desde
While x <= Hasta
Select Case Primos(x)
Case True
Console.WriteLine("El número {0} es primo", x)
End Select
x = x + 1
End While
End Sub

Private Function Primos(ByVal Numero As Long) As Boolean


Dim X As Integer = 3
Dim Final As Long
Dim Result As Boolean = True

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.

Public Sub NumerosPrimos(ByVal Desde As Integer,


ByVal Hasta As Integer)
Dim x As Integer = Desde
While x <= Hasta
Select Case Primos(x)
Case True
Console.WriteLine("El número {0} es primo", x)
End Select
x = x + 1
End While
End Sub
Si observamos el contenido del método, veremos como no encontramos nada que nos pueda resultar extraño, el código no incorpora
nada raro, y no es nada más que un bucle mientras

While x <= Hasta


con una estructura condicional en su interior

Select Case Primos(x)


para visualizar solo aquellos números que sean primos

Console.WriteLine("El número {0} es primo", x)


con su correspondiente incremento al final.

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 …

Dim Objeto As Ejemplo = New Ejemplo


Declaramos el objeto y se instancia.

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.

Public Class Ejemplo


Que esta declarado dentro de una clase que se llama Ejemplo.

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

Unidad 16. Clases, Código en VB (II)


16.5. Métodos, procedimientos.
En el ejemplo anterior lo que hemos visto es un método en el formato de procedimiento.

Public Sub NumerosPrimos(ByVal Desde As Integer, ByVal Hasta As Integer)


Dim x As Integer = Desde
While x <= Hasta
Select Case Primos(x)
Case True
Console.WriteLine("El número {0} es primo", x)
End Select
x = x + 1
End While
End Sub
Es uno de los formatos de escritura de un método.
Si observamos el interior, como ya se ha comentado anteriormente, lo que encontramos es una estructura de
las ya vistas anteriormente, programación estructurada.
16.6. Métodos, funciones.
Pero si deseamos saber si un número es primo, o es par, el método nos debe devolver un dato, que puede
ser cierto o falso, o cualquier otro tipo de dato, que nos indicaría en éste caso, que el número es primo o es par.

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:

Public Function Primos(ByVal Numero As Long) As Boolean


Dim X As Integer = 3
Dim Final As Long
Dim Result As Boolean = True

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)

Select Case Objeto.Primos(Numero)


Case True
Console.WriteLine("El {0} es primo", Numero)
Case Else
Console.WriteLine("El {0} no es primo", Numero)
End Select

83
End Sub
Primos nos devolverá un valor cierto o falso.

Select Case Objeto.Primos(Numero)


Que se usará en el Select Case, para emitir un mensaje u otro.
Esto permite una legibilidad más clara del programa.

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.

Los métodos, son programas pequeños.

Ejercicios propuestos de la Unidad


Pág. 16.2
Ejercicios unidad 16: Clases, Código en VB
Mediante el uso de una clase en la que se contemplen métodos adecuados para resolver los siguientes enunciados.
Todos los ejercicios han de resolverse incorporando los métodos adecuados a la misma clase.

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.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.


Ayuda ejercicios unidad 16: Clases, Código en VB
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.
El contenido de la clase es;

Public Class Ejercicios

84
Public Sub New()
End Sub

Public Function AreaCirculo(ByVal Radio As Double) As Double


AreaCirculo = Radio * Radio * 3.1415
End Function

Public Function LongitudCirculo(ByVal Radio As Double) As Double


LongitudCirculo = Radio * 2 * 3.1415
End Function
End Class
El programa principal:

Module Module1
Sub Main()
Dim Objeto As New Ejercicios
Dim Radio As Double

Console.WriteLine("Cálculo del área y longitud de un circulo")


Radio = Console.ReadLine
Console.WriteLine("Area de radio {0} es {1} ", Radio,
Objeto.AreaCirculo(Radio))
Console.WriteLine("Longitud radio {0} es {1} ", Radio,
Objeto.LongitudCirculo(Radio))
Console.ReadKey()
End Sub
End Module
El resultado de la ejecución:

2. Hallar el área de un triángulo. Area = Base por Altura / 2.


El contenido de la clase es;

Public Class Ejercicios


Public Sub New()
End Sub

Public Function AreaTriangulo(ByVal Base As Double, ByVal Altura As


Double) As Double
AreaTriangulo = Base * Altura / 2
End Function
End Class
El programa principal:

Sub Main()
Dim Base As Double
Dim Altura As Double
Dim Objeto as New Ejercicios

Console.WriteLine("Cálculo del área de un triángulo")


Console.WriteLine("Introducir Base")
Base = Console.ReadLine
Console.WriteLine("Introducir Altura")
Altura = Console.ReadLine
Console.WriteLine("Area triángulo de base {0} y altura {1} es {2} ", Base,
Altura, Objeto.AreaTriangulo(Base, Altura))

Console.ReadKey()
End Sub

85
El resultado de la ejecución:

3. Introducir un número A y visualizar si es o no primo.


El contenido de la clase es;

Public Class Ejercicios


Public Sub New()
End Sub

Public Function Primos(ByVal Numero As Long) As Boolean


Dim X As Integer = 3
Dim Final As Long
Dim Result As Boolean = True

Select Case Numero Mod 2 <> 0


Case True
Final = CLng(Numero / 2) + 1
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
End Class
El programa principal:

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

Public 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
End Class
El programa principal:
Sub Main()
Dim Objeto as new Ejercicios
Dim Nota As Single
Console.WriteLine("Introducir nota ")
Nota = Console.ReadLine
Console.WriteLine(Objeto.Calificacion(Nota))
Console.ReadKey()
End Sub
El resultado de la ejecución:

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.

El contenido de la clase es;

Public Class Ejercicios


Public Sub New()
End Sub

Public 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)
Case "M"
C = CSng(M / 1852)
Case "L"
C = CSng(M / 4190)
Case "Y"
C = CSng(M / 0.9144)
End Select

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;

Public Class Ejercicios


Public Sub New()
End Sub

Function Fecha(ByVal D As Integer, _


ByVal M As Integer, _
ByVal A As Integer) _
As Boolean

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
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

El contenido de la clase es:

Public Class Ejercicios


Public Sub New()
End Sub

Public 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
End Class

89
El programa principal:

Sub Main()
Dim Objeto as New Ejercicios
Dim Pesetas As Integer
Dim Moneda As Char

Console.WriteLine("Convertir moneda ")


Console.WriteLine("Introducir pesetas")
Pesetas = Console.ReadLine
Console.WriteLine("Introducir moneda F/L/I/D/M/S/H/P")
Moneda = Console.ReadLine
Console.WriteLine("El importe de {0} pesetas en la moneda {1} es {2} ",
Pesetas, Moneda, Objeto.ConversionMoneda(Pesetas, Moneda))
Console.ReadKey()

End Sub
El resultado de la ejecución:

Si observamos al escribir Objeto. En el entorno de VB, aparece lo siguiente:

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.

8. Visualizar los números primos entre 10 y 200.


El contenido de la clase es:

Public Class Ejercicios


Public Sub New()
End Sub

Public Sub NumerosPrimos(ByVal Desde As Integer, ByVal Hasta As Integer)


Dim x As Integer = Desde
While x <= Hasta
Select Case Primos(x)
Case True
Console.WriteLine("El número {0} es primo", x)
End Select
x = x + 1
End While
End Sub
End Class
El programa principal

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.

Public Sub NumerosPrimos(ByVal Desde As Integer, ByVal Hasta As Integer)

Unidad 17. Ciclo de vida de una clase (I)


17.1. Objetivos del tema.
Desarrollar y comprender las distintas fases por las que pasa un objeto desde que se inicializa hasta que se borra o se elimina del
programa.
17.2. Introducción.
Sabemos como crear código en nuestra clase, en las dos caras del mismo, como control de los datos que se asignan a la misma, y como
parte de los métodos de la misma.
Pero también tenemos que saber que la vida de una clase pasa por distintas etapas, conociéndolas podremos diseñar mejor y obtener el
mejor rendimiento de la misma.
Hay que tener presente que cuando se crea un objeto a partir de la clase que hemos escrito, ese objeto va a pasar por varias fases.

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

Metodo Cuenta(Inicio como entera, Final Como entera)


.. / ..
Fin Metodo
Fin Clase
En esa fase disponemos de la posibilidad de reclamar datos necesarios para la correcta ejecución de la clase, y es donde debemos o
podemos realizar el control de los mismos.

Metodo Constructor(Incremento como entera)


Si Incremento es distinto de 0
VariableInterna = Incremento
Fin Condicion
Fin Metodo
También podemos optar por no reclamar ninguna información y arrancar con los datos de nuestra clase inicializados a los valores que
nosotros consideremos oportunos.

Clase Ejemplo
Crear VariableInterna Entera = 1

Metodo Constructor()
Fin Metodo

Metodo Cuenta(Inicio como entera, Final Como entera)


.. / ..
Fin Metodo
Fin Clase
Cualquiera de las dos soluciones es correcta, cual utilizar vendrá marcado por las circunstancias en las que se tenga que utilizar el objeto.

Clase Ejemplo
Crear VariableInterna Entera

Metodo PrimeraInstanciaSolamente()
VariableInterna = 1

91
Fin Metodo

Metodo Constructor()
Fin Metodo

Metodo Cuenta(Inicio como entera, Final Como entera)


.. / ..
Fin Metodo
Fin Clase
Pág. 17.1

Unidad 17. Ciclo de vida de una clase (II)


17.4. Proteger nuestra clase.
Se trata de bloquear el constructor sin argumentos convirtiéndolo en private.
Es en muchas ocasiones 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.

Clase Ejemplo
Crear VariableInterna Entera

Metodo PrimeraInstanciaSolamente()
VariableInterna = 1
Fin Metodo

Privado Metodo Constructor()

Fin Metodo

Metodo Cuenta(Inicio como entera, Final Como entera)


.. / ..
Fin Metodo
Fin Clase
De esa forma no es visible y no se puede utilizar, y es imposible que se use accidentalmente.

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

Privado Metodo Constructor(EscenarioUno como String)


Fin Metodo

Privado Metodo Constructor(EscenarioDos como Entera)


Fin Metodo
Fin Clase
Pero también se puede crear con distintas variables en cada uno de ellos.

Clase Ejemplo
Privado Metodo Constructor(EscenarioUno como String)
Fin Metodo

Privado Metodo Constructor(EscenarioUno como String, OtraVariable como


Entera)
Fin Metodo
Fin Clase

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.

El método de finalización puede pertenecer a la misma clase, o bien al sistema.


El “recolector de basura”, normalmente pertenece al sistema en uso, no a la clase que se diseña, al objeto que está en uso.

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

Unidad 18. Ciclo de vida de una clase en VB (I)


18.1. Objetivos del tema.
Ver las distintas fases por las que pasa un objeto en Visual Basic, desde que se realiza la instancia del mismo en su clase hasta, que
finaliza la existencia del mismo.
18.2. Introducción.
Es importante tener presente en que momento, cuando y como se van desarrollando las distintas etapas de la vida de un objeto, de esa
forma no estaremos consumiendo recursos del sistema de forma innecesaria.
Un objeto es igual que un ser vivo, nace, crece y desaparece, lo que hay que hacer es ajustar esos pasos a las necesidades de nuestro
programa.

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.

Ese método en Visual se denomina “new”.

Public Class Clase


Public UnDato As Integer
' Constructor sin captura de datos
Public Sub New()

End Sub

Public Sub New(ByVal AlgunDato As Integer)


UnDato = AlgunDato
End Sub
End Class
En esa fase disponemos de la posibilidad de reclamar datos necesarios para la correcta ejecución de la clase, y es donde debemos o
podemos realizar el control de los mismos.

93
Public Class Clase
Public UnDato As Integer
' Constructor sin captura de datos
Public Sub New()
End Sub

' Constructor que obliga a introducir un dato en la inicialización


Public Sub New(ByVal AlgunDato As Integer)
UnDato = AlgunDato
End Sub
End Class
También podemos optar por no reclamar ninguna información y arrancar con los datos de nuestra clase inicializados a los valores que
nosotros consideremos oportunos.

Public Class Clase


Public UnDato As Integer = 10
' Constructor sin captura de datos
Public Sub New()
End Sub
End Class
Cualquiera de las dos soluciones es correcta, cual utilizar vendrá marcado por las circunstancias en las que se tenga que utilizar el objeto.

Public Class Clase


Public UnDato As Integer
' Constructor sin captura de datos
Public Sub New()
End Sub

' Constructor que obliga a introducir un dato en la inicialización


Public Sub New(ByVal AlgunDato As Integer)
UnDato = AlgunDato
End Sub
End Class
Pág. 18.1

Unidad 18. Ciclo de vida de una clase en VB (II)


18.4. Proteger nuestra clase.
Se trata de bloquear el constructor sin argumentos convirtiéndolo en private.

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.

Public Class Clase


Public UnDato As Integer
' Constructor sin captura de datos
Private Sub New()
End Sub

' Constructor que obliga a introducir un dato en la inicialización


Public Sub New(ByVal AlgunDato As Integer)
UnDato = AlgunDato
End Sub
End Class
De esa forma no es visible y no se puede utilizar, y es imposible que se use accidentalmente.

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.

Public Class Clase


Public UnDato As Integer
' Constructor sin captura de datos
Private Sub New()
End Sub

' Constructor que obliga a introducir un dato en la inicialización


Public Sub New(ByVal AlgunDato As Integer)
UnDato = AlgunDato
End Sub

' Constructor que obliga a introducir un dato en la inicialización


Public Sub New(ByVal AlgunDato As String)
End Sub
End Class
Pero también se puede crear con distintas variables en cada uno de ellos.

Public Class Clase


Public UnDato As Integer
' Constructor sin captura de datos
Private Sub New()
End Sub

' Constructor que obliga a introducir un dato en la inicialización


Public Sub New(ByVal AlgunDato As Integer)
UnDato = AlgunDato
End Sub

' Constructor que obliga a introducir un dato en la inicialización


Public Sub New(ByVal AlgunDato As Integer, ByVal OtroDato as Integer)

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.

' Constructor que obliga a introducir un dato en la inicialización


Public Sub New(ByVal AlgunDato As Integer)
End Sub
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.
18.6. Finalización de la clase.
Finalize está protegido y, por lo tanto, sólo se puede obtener acceso a él a través de esta clase o de una clase derivada.
Este método se invoca de forma automática, después de que un objeto pase a ser inaccesible, salvo que haya sido excluido del proceso
de finalización mediante una llamada a SuppressFinalize. Durante el cierre de un dominio de aplicación, se realiza una llamada automática a
Finalize para los objetos que no están exentos de finalización, incluso para aquellos objetos que a los que aún se puede obtener acceso. Sólo se
realiza una llamada a Finalize para una instancia especificada, a menos que el objeto vuelva a registrarse mediante un mecanismo como
ReRegisterForFinalize y no se haya llamado posteriormente a GC.SuppressFinalize.
Todas las implementaciones de Finalize en un tipo derivado deben llamar a la correspondiente implementación de tipo base de Finalize.
Este es el único caso en el que se permite al código de la aplicación llamar a Finalize.

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.

Ejercicios propuestos de la Unidad


Pág. 18.2
Ejercicios unidad 18: Ciclo de vida de una clase en VB
1. Crear una clase en la que no se pida ningún requisito para crear un objeto con la misma.
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.
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.
4. 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, comprobar los mensajes utilizar los métodos que siguen para probar los distintos resultados.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.


Ayuda ejercicios unidad 18: Ciclo de vida de una clase en VB
1. Crear una clase en la que no se pida ningún requisito para crear un objeto con la misma.
Public Class Ejercicios
Public Sub New()

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

Public Sub New(ByVal Dato As Integer)


Select Case Dato
Case 1 To 9
Case Else
Console.WriteLine("El dato es incorrecto")
End Select
End Sub
End Class
En el programa principal.
Module Module1

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

Public Sub New(ByVal UnValor As Integer)


Select Case UnValor
Case 1 To 9
Dato = UnValor
Console.WriteLine("El valor de dato es {0} ", Dato)
Case Else
Console.WriteLine("El valor de dato es {0} ", Dato)
Console.WriteLine("El dato es incorrecto")
End Select
End Sub
End Class
El programa principal.
Module Module1

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

Public Sub New()


End Sub

Public Sub New(ByVal UnValor As Integer)


Select Case UnValor
Case 1 To 9
Dato = UnValor
Console.WriteLine("El valor de dato es {0} ", Dato)
Case Else
Console.WriteLine("El valor de dato es {0} ", Dato)
Console.WriteLine("El dato es incorrecto")
End Select
End Sub

Public Sub Finalizar()


Console.WriteLine("Ejecución de finalize")
Me.Finalize()
End Sub
End Class
El programa principal sería:

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.

Unidad 19. La herencia en las clases (I)


19.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.
19.2. Introducción.
El concepto de herencia en una clase es tal cual la palabra nos lo índica, no es necesario ampliar el significado de la misma.
La filosofía es sencilla, yo creo una clase que puede ser el punto de partida para un concepto y que posteriormente puede ir
especializándose o mejorándose, pero en lugar de copiar y pegar lo que ya tenemos escrito, lo que hacemos es indicar en el código de la clase
que escribo, que tome todas las características de la clase que se índica.
No siempre las clases se pueden heredar, cuando escribimos una clase podemos indicar de forma explicita que no se pueda usar en otras
clases, pero también podemos escribirla como plantilla, y obligar a que sea heredada y no pueda ser utilizada para declarar con ella un objeto.
19.3. Clase base, origen.
Cuando hablamos de herencia, hay que pensar que hablamos de una clase que es la origen y de otra que es la
que la contiene.
En la imagen podemos ver como la clase Tres, se inicia a partir de los contenidos de las clases Uno y Dos, que
se heredan en su inicio, y que serán la clase de referencia o de origen en parte de los contenidos de la misma.
Por lo tanto la clase tres tendrá todas las capacidades y características de las clases Uno y Dos más las que se
desarrollen en ella misma.
En la clase origen se pueden definir métodos que no se hereden, esos no serán reutilizados en las clases que se obtengan a partir de la
de origen.
En la clase resultante, la clase tres, tendrá entonces el código del que se dispone en las clases uno y dos, más
el código que se genera propio en la clase tres.

19.4. Clase derivada.


La clase derivada es la clase resultante al heredar las clases Uno y Dos, y asumirá todas las características de
las clases origen.
Además en esta clase podemos le añadiremos las características necesarias para que cumpla la función para
la cual se diseña.

19.5. Tipos de herencia.


La herencia puede arrancar a partir de una o de varias clases, pero eso dependerá de las características del lenguaje utilizado, ya que no
todos permiten que se hereden en una clase varias clases origen.

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

AlumnoDePrimero = nuevo Alumno,

el objeto AlumnoDePrimero tendrá disponibles,

Los datos personales y académicos.


Los métodos de visualizar datos personales y datos académicos.

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

heredadas, cualquier clase, Inherits


deben ser heredadas obligatoriamente MustInherit, no se pueden crear objetos con ella.
o no pueden ser heredadas NotInheritable

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,

Public Class Ejemplos


' La variable se hace pública
Public Shared Contador As Int16 = 0

Public Sub Incrementa()


Contador += 1
End Sub

Public Sub Resta()


Contador -= 1
End Sub

Public Sub Visualiza()


99
Console.WriteLine("Contador vale {0} ", Contador)
End Sub
End Class
El ejemplo anterior de clase contiene una serie de métodos.

Public Class Nueva


' herencia de la clase anterior
Inherits Ejemplos
End Class
En la clase que se describe no hay ni una sola línea de código pero adquiere todas las capacidades de la clase Ejemplos.

Y si nos fijamos en el programa principal.

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

Overridable Puede ser reemplazado.


Overrides Está reemplazando a un método Overrides.
NotOverridable Impide que se reemplace.
MustOverride Indica que debe escribirse éste método en la clase derivada de forma obligatoria. Esto implica que la
clase debe declararse de forma obligatoria como MustInherit, ya que es obligatorio
desarrollar dicho método.

Cuando se hereda una clase MustInherit automáticamente VB escribe los métodos declarados en la clase base como MustOverride.

MustInherit Class ClaseBase


Public MustOverride Sub MetodoQueDebeSerEscrito()

Public Overridable Sub MiMetodo()


Console.WriteLine("Método que se puede reescribir")
End Sub

Public Sub UsandoMyClass()


MyClass.MiMetodo() ' con MyClass
End Sub
End Class
Esta es la clase Base, podemos observar como tenemos estos dos métodos

100
Public MustOverride Sub MetodoQueDebeSerEscrito()
Public Overridable Sub MiMetodo()
La clase derivada podría ser:

Class ClaseDerivada
Inherits ClaseBase

Public Overrides Sub MetodoQueDebeSerEscrito()


Console.WriteLine("Este es el metodo que debía ser escrito")
End Sub

Public Overrides Sub MiMetodo()


Console.WriteLine("Método que ha sido reescrito")
MyBase.MiMetodo() ' Con MyBase
End Sub
End Class
Observar como se desarrolla el método Overrides.

Public Overrides Sub MetodoQueDebeSerEscrito()


Que se corresponde con

Public MustOverride Sub MetodoQueDebeSerEscrito()


De la clase base.
El resultado de la ejecución sería:
Pág. 20.2

Unidad 20. La herencia en las clases en VB (III)


20.6. Referencias en el código de una clase, MyClass, MyBase, Me.
¿Qué es esto.?
Ya hemos visto parte en el ejemplo anterior.
Si creamos clases, es para crear objetos con ellas.
Sí las clases tienen como característica que se puedan heredar en otra clase, ¿qué pasa, si a mí me interesa usar el método de la clase
heredada en lugar del método que estoy escribiendo para ésta clase en un momento dado?.

Class ClaseBase
Public Sub Sombreado()
Console.WriteLine("Texto desde sombreado")
End Sub

Public Overridable Sub MiMetodo()


Console.WriteLine("Cadena en clase base")
End Sub

Public Sub UsandoMe()


Me.MiMetodo()
End Sub

Public Sub UsandoMyClass()


MyClass.MiMetodo()
End Sub
End Class
Esta sería una clase base, en la que estamos haciendo uso de MyClass y de Me.

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

Public Overrides Sub MiMetodo()


Console.WriteLine("Cadena en clase derivada")
End Sub

Public Shadows Sub Sombreado()


MyBase.Sombreado() ' llama al de clasebase
Console.WriteLine("Texto desde sombreado derivada")
End Sub
End Class
MyBase, se utiliza para llamar desde la clase derivada a un método de la clase base que ha sido reemplazado en la clase derivada, pero
que sin embargo posee código que nos interesa se ejecute, porque lo que estamos haciendo en realidad es una ampliación del código de la clase
base.

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.

20.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

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.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.

Ayuda 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.

Public MustInherit Class Ejercicio

102
Public Sub New()
End Sub

Public MustOverride Sub VisualizarAbecedario()


End Class
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.
Public Class Nueva
Inherits Ejercicio

Public Overrides Sub VisualizarAbecedario()


Dim X As Integer
X = 65
While X < 91
Console.WriteLine(Chr(X))
X = X + 1
End While
End Sub
End Class
Su utilización es:

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

Metodo Suma(Real A, Entero B, Largo C)


Suma = A + B + C
Final Metodo
Final Clase
Podemos observar como en el ejemplo tenemos el método Suma en dos ocasiones, pero disponen de distintas líneas de argumentos, en
un caso son dos y en el segundo dispone de tres argumentos en la línea de entrada.
Pero no tiene porque ser distintas las líneas de entrada, veamos el siguiente caso.

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

Metodo Suma(Simple A, Doble B, Corto C)


Suma = A + B + C
Final Metodo
Final Clase
Si vemos el ejemplo, podemos observar que el método Suma está escrito tres veces, pero a pesar de que tiene tres argumentos en cada
uno de ellos, los argumentos son de distinto tipo, por lo que en realidad son tres versiones distintas, bajo el mismo nombre.

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

// Son iguales en nombre, argumentos y tipo

Metodo Suma(Entero A, Entero B, Entero C)


Suma = A + B + C
Final Metodo

Metodo Suma(Entero A, Entero B, Entero C)


Suma = A + B + C
Final Metodo

// Son iguales en nombre, argumentos y tipo

Metodo Suma(Real A, Entero B, Largo C)


Suma = A + B + C
Final Metodo

Metodo Suma(Real A, Entero B, Largo C)


Suma = A + B + C
Final Metodo
Final Clase
21.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.

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.

Public Class Ejemplos


Private Sub New()
End Sub

Public Sub New(ByVal Euros As Double)


End Sub

Public Sub New(ByVal Dolares As Double)


End Sub

104
End Class
Para este caso la solución podría pasar por :

Public Class Ejemplos


Enum Monedas
Euro = 1
Dolar = 2
Libra = 3
Yen = 4
End Enum

Private Sub New()


End Sub

Public Sub New(ByVal Importe As Double, ByVal Cual As Monedas)


End Sub
End Class
En la solución se utiliza una enumeración, no vista todavía, pero como se puede observar es una definición de opciones posibles para un
valor.

La utilización de dicha clase podría quedar como sigue:

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.

Public Function Convertir(ByVal Cual As Monedas) As Double


Select Case Moneda
Case Monedas.Euro
Select Case Cual
Case Monedas.Dolar
Convertir = Import * 1.22
Case Monedas.Libra
Case Monedas.Yen
End Select
Case Monedas.Dolar

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

Unidad 22. La sobrecarga en las clases en VB (II)


105
No siempre es necesario realizar una sobrecarga.

En el siguiente ejemplo podemos ver repetido el mismo método en tres ocasiones, serían tres sobrecargas.

Public Sub Sobrecarga(ByVal Version1 As Integer)


End Sub

Public Sub Sobrecarga(ByVal Version2 As Integer, ByVal Otro As Boolean)


End Sub

Public Sub Sobrecarga(ByVal Version3 As Integer, ByVal Otro As Single)


End Sub
En el programa principal quedaría reflejado como sigue:

Podemos ver en la siguiente imagen que la línea de argumentos ha cambiado.

Solo es cuestión de elegir la que necesitemos.


Como hemos comentado, el realizar una sobrecarga no implica que haya que reescribir el método completo.

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.

Public Class Ejemplos

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

Public Sub EscribirTexto()


Escribe("hola", ConsoleColor.White, ConsoleColor.Black)
End Sub

Public Sub EscribirTexto(ByVal Texto As String)


Escribe(Texto, ConsoleColor.White, ConsoleColor.Black)
End Sub

Public Sub EscribirTexto(ByVal Texto As String, _


ByVal ColorTexto As ConsoleColor, _
ByVal ColorFondo As ConsoleColor)
Escribe(Texto, ColorTexto, ColorFondo)
End Sub
End Class
En el principal su uso quedaría así.

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.

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
Este procedimiento es llamado desde los tres métodos, solo habría que modificarlo una vez, y quedaría actualizado para los tres.

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

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.

Ayuda 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.
El código en la clase puede ser:

Public Class Ejercicios


Public Sub New()
End Sub

Public Function Importe(ByVal Cantidad As Integer, _


ByVal Precio As Double) As Double
Importe = Cantidad * Precio
End Function

Public Function Importe(ByVal Cantidad As Integer, _


ByVal Precio As Double, _
ByVal Descuento As Single) As Double
Precio = Precio - (Precio * Descuento / 100)
Importe = Cantidad * Precio
End Function

Public Function Importe(ByVal Cantidad As Integer, _


ByVal Precio As Double, _
ByVal Descuento As Single, _
ByVal Recargo As Single) As Double
Precio = Precio - (Precio * Descuento / 100)
Precio = Precio + (Precio * Recargo / 100)

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

Console.WriteLine("El importe es de {0} ", _


Objeto.Importe(Cantidad, Precio))

Console.WriteLine("El importe con un descuento del {0} % es de {1} ", _


Descuento, Objeto.Importe(Cantidad, Precio,
Descuento))

Console.WriteLine("El importe con un descuento del {0} % y un recargo


del {1} % es de {2} ", _
Descuento, Recargo, Objeto.Importe(Cantidad, Precio, Descuento,
Recargo))
Console.ReadLine()
End Sub
End Module
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.

Public Class Ejercicios


Public Sub New()
End Sub

Public Function Nota(ByVal Nota_1 As Single, ByVal Nota_2 As Single) as


single
Nota = (Nota_1 + Nota_2) / 2
End Function

Public Function Nota(ByVal Nota_1 As Single, ByVal Hora_1 As Integer, _


ByVal Nota_2 As Single, ByVal Hora_2 As Integer) as
single
Nota = ((Nota_1 * Hora_1) + (Nota_2 * Hora_2)) / (Hora_1 + Hora_2)
End Function
End Class
El principal del programa

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

Public Sub EscribirTexto()


Escribe("hola", ConsoleColor.White, ConsoleColor.Black)
End Sub

Public Sub EscribirTexto(ByVal Texto As String)


Escribe(Texto, ConsoleColor.White, ConsoleColor.Black)
End Sub

Public Sub EscribirTexto(ByVal Texto As String, _


ByVal ColorTexto As ConsoleColor, _
ByVal ColorFondo As ConsoleColor)
Escribe(Texto, ColorTexto, ColorFondo)
End Sub
End Class
El programa principal.

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

Unidad 23. Cómo programar una clase (I)


23.1. Objetivos del tema.
Se han visto los distintos elementos de una clase y sus características, ahora conviene intentar sentar criterios o formas de abordar la
programación de una clase.
23.2. Introducción.
No se puede negar que las clases son una evolución natural de la forma de programar, o sea que negar la evidencia es del todo inútil
En principio es muy atrevido escribir un capitulo con éste tema, pero no se pretende decir a nadie como tiene que hacer las cosas, sino
simplemente indicar cuales son los criterios que se pueden seguir, o en que orden se ejecutan los métodos y se usan las variables, propiedades,
para a partir de ahí crear lo que podría ser un orden más o menos adecuado, evidentemente desde lo que llevamos visto, el tiempo muchas veces
te desdice, o te reafirma.
23.3. Utilización de las clases.
La utilización de las clases con los pequeños ejemplos que hemos visto quizás no queda muy claro, pero hay que resaltar que su destino
es el de crear objetos con las mismas, y que esos objetos son autónomos unos con respecto a otros.

¿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.

Declarar un objeto de esa clase.


Eso implica que se ejecute por defecto un método New, Constructor.

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.

En base a esos pasos debemos programar el contenido de nuestra clase.


23.5. Declarar un objeto de nuestra clase.
Este paso es el más sencillo de todos.

Crear Objeto como nuevo ClaseDefinidaExistente


O bien se puede escribir

Crear Objeto como ClaseDefinidaExistente


Objeto = nuevo ClaseDefinidaExistente
Cualquiera de las dos sintaxis es válida, aunque la más utilizada es la primera.
Ahora hay que escribir la clase, y hemos de escribir una clase eficiente y robusta contra el mal uso de la misma.
Si por el motivo que fuese deseamos que no se pueda declarar un objeto de la clase que nosotros escribimos sin que se ejecute el control
adecuado en su creación hay que proteger o bloquear el método constructor.
Para ello lo declaramos Private sin argumentos y solo podrá ejecutarse en la versión que nosotros escribamos.
El ejemplo que sigue no permite declarar un objeto de la clase, sin que se le pase como argumento un valor de tipo string en el momento
de la definición de dicho objeto.
Por lo tanto es imposible crear un objeto de esa clase sin más.

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

Public Constructor(Valor Como String)


VariablePropiedad = Valor
Fin procedimiento
End Class
Este ejemplo nos obliga a declarar el objeto con la siguiente sintaxis.

Crear Objeto como nuevo Clase("Inicialización")


Impide que se pueda utilizar

Crear Objeto como nuevo Clase


Por lo que si nosotros añadimos en el método Constructor de la clase el siguiente código

Private Constructor()
Fin procedimiento

Public Constructor(Valor como String)


Si Valor <> Nulo Entonces VariablePropiedad = Valor
Fin procedimiento
Si al inicializar la clase no se recibe un valor adecuado la clase quedaría inicializada con el valor por defecto de la propiedad, sin asumir el
valor recibido.
Si la clase es heredada desde otra clase la condición se mantiene, vemos un ejemplo.

Public Clase Heredera


Heredar Clase // Heredar la clase del ejemplo anterior

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.

El siguiente paso es la declaración de las variables.


En el momento de declarar las variables de la clase nos encontraremos con dos tipos de variables.

Las que actúan como variables.


Las que representan internamente a una propiedad, que es la parte visible.

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

Unidad 23. Cómo programar una clase (II)


23.6. Asignar valores a las propiedades de la clase.
Como hemos comentado, a la hora de inicializar la clase, las variables que se emparejan con las propiedades las vamos a inicializar, pero
evidentemente el usuario puede querer personalizar o necesitar ajustar los valores del objeto, por lo tanto necesitará cambiar los valores de las
propiedades.
Debemos intentar disponer de un sistema para poder asignar datos a las propiedades de forma controlada.
Esta es la forma de hacerse en VB.

Public Class Primera


Dim DatoInterno As Integer = 32

Public Property DatoExterno() As Integer


' validación
Get ' al devolverse
Return DatoInterno
End Get
Set(ByVal Value As Integer)
Select Case Value ‘ al asignarse
Case -32767 To 32767
DatoInterno = Value
Case Else
DatoInterno = 0
End Select
End Set
End Property
End Class
Podemos observar como la variable DatoInterno esta representada en el exterior con la propiedad DatoExterno.
Al asignar datos a la propiedad desde el programa se ejecutará esta zona del código
Set(ByVal Value As Integer)
Select Case Value ‘ al asignarse
Case -32767 To 32767
DatoInterno = Value
Case Else
DatoInterno = 0
End Select
End Set
Donde nosotros podemos validar, controlar o bloquear, como deseemos, los datos que se intentan asignar.
Cuando se reclame desde el exterior el valor de la propiedad DatoExterno se ejecutará
Get ' al devolverse
Return DatoInterno
End Get
Las propiedades normalmente vamos a utilizarlas en ambos sentidos, es decir devolver su valor y recoger nuevos valores.
Pero en algún momento puede darse la circunstancia o la necesidad de impedir el uso en alguno de los dos sentidos.
El plantearse este tipo de actuación nos va a garantizar o reducir el porcentaje de errores en la ejecución de nuestro programa.
23.7. Variables públicas.
La otra forma de asignar datos a la clase es la utilización de variables públicas, pero ahí perdemos el control de los datos a recibir, por lo
tanto es un camino tortuoso y peligroso, a utilizar en contadas ocasiones.

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.

Por lo tanto, tenemos otro tema resuelto.


La siguiente cuestión que nos aparece, es cuando un método puede resolver un problema desde distintos puntos de partida.
Eso nos va a llevar a que seguramente tengamos también distintos juegos de datos iniciales, con lo cual la solución es evidente, utilizar la
sobrecarga.
Creamos distintos métodos con el mismo nombre y con las líneas de entrada de argumentos adecuada a cada situación prevista.
En cuanto al orden en el que se pueden escribir pero para eso es difícil dar criterios.
23.9. Utilización de los objetos de una clase.
La utilización de los objetos declarados de una clase, dependerá de la implementación de la clase en cuestión, que es la que le
proporciona los recursos a los objetos.

La utilización del objeto, una vez declarado, será

Asignar valores a las propiedades, si estas lo requieren o lo necesita el código, y si no se ha hecho ya en la


declaración del objeto.
Hacer uso de los métodos disponibles de la clase en el momento adecuado.
Finalizar el objeto, si procede, o dejar que la salida del procedimiento acabe con el mismo.

El uso dependerá evidentemente del tipo de clase que se haya implementado.


La codificación del uso de la clase puede hacerse bajo dos estilos de código.
El primero podría decirse que es el habitual.
Definir
Usar
Y no realizar acciones especificas de finalización, o asignar nulo y utilizar el recolector de cada lenguaje.

Crear Objeto como nuevo Clase


Objeto = Nada
Recolector.Limpia()
Con el método Limpia de la clase recolector, se obliga a la recuperación de los recursos libres del sistema.
La clase Recolector, controla el recolector de elementos no utilizados del sistema, es un servicio que reclama de forma automática la
memoria que no se utiliza.
Los métodos de esta clase influyen en el momento en que se realiza la recolección de elementos no utilizados de un objeto y en el
momento en que se liberan los recursos asignados por un objeto.

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.

Dim Objeto as New ClaseDefinidaExistente


Ahora hay que escribir la clase, y hay que escribirla en función de esos parámetros que hemos comentado que se han de dar en el inicio
del objeto.

Decidir que tipo de inicialización nos interesa.


Estudiar cuantas posibilidades de inicio nos puede interesar para escribir las sobre cargas adecuadas.
Recepción y control de los datos necesarios en la inicialización.
Valores iniciales de variables y propiedades adecuados.

Public Class Ejemplo


Dim Variable As String = "Variable inicializada"
Dim Propiedad As String = "Propiedad inicializada"

Private Sub New()


‘ esto impide la creación de un objeto .
End Sub

Public Sub New(ByVal Valor As String)


Propiedad = Valor
End Sub
End Class
Este ejemplo nos obliga a declarar el objeto con la siguiente sintaxis.
Dim Objeto As New Ejemplo("Inicialización")
Impide que se pueda utilizar
Dim Objeto As New Ejemplo
Por lo que si nosotros añadimos en el método New de la clase el siguiente código

113
Private Sub New()
End Sub

Public Sub New(ByVal Valor As String)


If Valor <> "" Then Propiedad = Valor
End Sub
Si al inicializar la clase no se recibe un valor adecuado la clase quedaría inicializada con el valor por defecto de la propiedad, sin asumir el
valor recibido.

Si la clase es heredada desde otra clase la condición se mantiene, vemos un ejemplo.

Public Class Heredera


Inherits Ejemplo ‘ Heredar la clase del ejemplo anterior

Public Sub New()


‘ El primer paso es llamar al New de la clase origen, y proporcionar
‘ un valor de inicialización.
MyBase.New("Valor desde la clase heredera")
End Sub
End Class
Todo lo anterior se puede probar desde el código siguiente.
Module Tema_24
Sub Main()
Dim Objeto As New Ejemplo("Valor de inicialización")
Console.WriteLine(Objeto.Propiedad)
Dim Otro As New Heredera
Console.WriteLine(Otro.Propiedad)
Console.Read()
End Sub
End Module

Que produce el siguiente resultado


Como vemos en los ejemplos, la adecuada utilización del método New es importante.

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

Unidad 24. Cómo programar una clase en VB (II)


24.4. Asignar valores a las variables de la clase.
En el momento de declarar las variables de la clase nos encontraremos con dos tipos de variables.
Aquellas que se refieren a datos de la clase, y a las que se refieren a las propiedades que se ven desde el exterior de la clase.
A las variables normales, les podemos dar el tratamiento que habitualmente le damos a las variables de cualquier programa, pero las que
se emparejan con las propiedades lo lógico es inicializarlas al valor que nos interese, con el fin de que la clase a la hora de inicializarse no 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.
En el ejemplo anterior podemos observar los dos tipos de variables.
24.5. Asignar valores a las propiedades de la clase.
Un objeto deriva de una clase, y ese objeto debe tener unas características, para que las tenga podemos:

Asignar los valores de sus propiedades en el momento de inicializar el objeto.


Asignar a posteriori vía métodos o propiedades.
Inicializar todas las variables en el momento de su declaración.
Utilizar las propiedades para asignar valores.

Asignar los valores de sus propiedades en el momento de inicializar el objeto equivale a recibir sus valores en el constructor.

Public Sub New(ByVal Valor As String)


VariablePropiedad = Valor
End Sub
Asignar los valores en la declaración equivale a:

Dim VariablePropiedad As String = "Propiedad inicializada"

114
Asignar a posteriori implica recibir valores en la línea de argumentos de un método.

Public Sub Metodo(ByVal VariablePropiedad As String)


VariablePropiedad = Valor
End Sub
La última alternativa es utilizar el camino de las propiedades.
Public Property Propiedad() As String
Get
Return VariablePropiedad
End Get

Set(ByVal value As String)


Select Case value <> ""
Case True
VariablePropiedad = value
End Select
End Set
End Property
Los valores de las propiedades se asignan en el apartado Set de la propiedad en cuestión y es ahí donde hay que escribir el código
adecuado para su validación, como de costumbre es un apartado que nunca hay que olvidar, no solo se ha de asignar el dato, sino que también
hay que validarlo previamente.
Public Class Ejemplo
Dim Variable As String = "Variable inicializada"
Dim VariablePropiedad As String = "Propiedad inicializada"

Private Sub New() ' esto impide la creación de un objeto .


End Sub

Public Sub New(ByVal Valor As String)


Console.WriteLine("Valor antes de recibir la inicialización {0} ",
VariablePropiedad)
VariablePropiedad = Valor
End Sub

Public Property Propiedad() As String


Get
Return VariablePropiedad
End Get

Set(ByVal value As String)


Select Case value <> ""
Case True
VariablePropiedad = value
End Select
End Set
End Property

Public Sub Metodo(ByVal Valor As String)


VariablePropiedad = Valor
End Sub
End Class
El resultado de la ejecución es el siguiente:

Los valores de la propiedad se devuelven en el apartado del Get.


El último caso es la posibilidad de bloquear una propiedad en uno de los dos sentidos, para ello solo hay que declararla ReadOnly o
WriteOnly.
Vemos en el ejemplo como se recibe o se trata una propiedad, esa propiedad es de lectura y escritura, pero podemos declararlas como
ReadOnly o WriteOnly.
ReadOnly Property SoloLectura() As String
115
Get
Return VariablePropiedad
End Get
End Property
Cuando declaramos una propiedad de solo lectura, la parte de escritura se elimina, y al revés cuando es de solo escritura.

WriteOnly Property SoloEscritura() As String


Set(ByVal value As String)
Select Case value <> ""
Case True
VariablePropiedad = value
End Select
End Set
End Property
Pág. 24.2
Unidad 24. Cómo programar una clase en VB (III)
24.6. Utilización de los objetos de una clase.
La utilización de los objetos declarados de una clase, dependerá de la implementación de la clase en cuestión, que es la que le
proporciona los recursos a los objetos.
La utilización del objeto, una vez declarado, será

Asignar valores a las propiedades, si estas lo requieren o lo necesita el código, y si no se ha hecho ya en la


declaración del objeto.
Hacer uso de los métodos disponibles de la clase en el momento adecuado.
Finalizar el objeto, si procede, o dejar que la salida del procedimiento acabe con el mismo.

El uso dependerá evidentemente del tipo de clase que se haya implementado.


La codificación del uso de la clase puede hacerse bajo dos estilos de código.
El primero podría decirse que es el habitual.
Definir
Usar
Y no realizar acciones especificas de finalización, o utilizar la clase GC.

Dim Objeto As New Clase(6)


Objeto = Nothing
GC.Collect()
Con el método Collet de la clase GC, se obliga a la recuperación de los resursos libres del sistema.
La clase GC, controla el recolector de elementos no utilizados del sistema, es un servicio que reclama de forma automática la memoria
que no se utiliza.
Los métodos de esta clase influyen en el momento en que se realiza la recolección de elementos no utilizados de un objeto y en el
momento en que se liberan los recursos asignados por un objeto.
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.

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.

Using Objeto As New Clase(7)


MsgBox("El valor de la propiedad es " & Objeto.Propiedad & ".")
End Using
24.7. Secuencia de uso de un objeto.
El objeto creado como instancia de una clase, cuando se libera ejecuta el método finalize de la clase.
Este método existe por defecto.
Ese método se ejecuta siempre de forma predeterminada antes de liberar el objeto.
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.
Para finalizar el uso de un objeto se establece a Nothing, y a partir de ahí la referencia al mismo no es posible.

Objeto = Nothing
También podemos preguntar por

If Objeto IsNot Nothing Then ...


Lo que nos permite saber si un objeto sigue haciendo referencia a algún recurso.

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

MsgBox("Punto intermedio entre demos.", MsgBoxStyle.Information)

' Demostración de como el Recolector de objetos


' del CLR, Common Lenguage Runtime, llama al método finalize.

Dim OtroObjeto As New ClaseHeredera(6)


OtroObjeto = Nothing
GC.Collect()
End Sub
End Module
Y este es el módulo con el código de las clases del ejemplo.

Module ClaseDos
Public Class ClaseBase
Sub New()
MsgBox("ClaseBase inicializándose con el método New.")
End Sub

Protected Overrides Sub Finalize()


MsgBox("ClaseBase haciendo shutdown con el método Finalize.")
MyBase.Finalize()
End Sub
End Class

Public Class ClaseHeredera


Inherits ClaseBase
Implements IDisposable
Private ValorPropiedad As Integer

Sub New(ByVal Valor As Integer)


' La llamada al método New de la clase base ess obligado.
MyBase.New()
MsgBox("Clase heredera se inicializa con el método New.")

ValorPropiedad = Valor
End Sub

Property Propiedad() As Integer


Get ' Entrada
CheckIfDisposed()
Propiedad = ValorPropiedad
End Get
Set(ByVal Value As Integer) ' Salida
CheckIfDisposed()
ValorPropiedad = Value
End Set
End Property

Protected Overrides Sub Finalize()


MsgBox("Clase heredera haciendo shuttdown con el método Finalize.")
Dispose(False)
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

Private disposed As Boolean = False


Public Sub CheckIfDisposed()
If Me.disposed Then
Throw New ObjectDisposedException(Me.GetType().ToString, _
"Este objeto ha sido liberado.")
End If
End Sub
Protected Overridable Overloads Sub Dispose( _
ByVal disposing As Boolean)
MsgBox("Clase heredera haciendo shuttdown con el ” & _
“método Dispose sobrecargado, OverLoad")

' Código de tareas finales


If Not Me.disposed Then
If disposing Then
' Dispose de cualquier recurso utilizado.
End If
' Dispose de cualquier recurso.

' Llamar a MyBase.Finalize si es una clase derivada ,


' y la clase base no ejecuta Dispose.
MyBase.Finalize()
End If
Me.disposed = True
End Sub
End Class
End Module
Pág. 24.3

Unidad 24. Cómo programar una clase en VB (IV)


24.8. Recuperar los recursos utilizados que están libres, clase GC.
La clase GC está diseñada para la gestión de los recursos liberados en memoria sin utilizarse, 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 consta 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.
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

Unidad 25. Utilizar clases (I)


25.1. Objetivos del tema.
Hasta ahora lo que hemos estado viendo ha sido la forma de crear una clase, sus distintos componentes, queda ahora dar unas pautas de
cuando utilizar, o para que utilizar una clase.
25.2. Introducción.
La utilización de una clase como siempre es una potestad de quien escribe el programa.
Las clases sustituyen a lo que anteriormente se conocía como librerías.

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.

25.4. Para que utilizar las clases.


Por lo tanto las clases pueden usarse para …, lo que queramos evidentemente, pero es una forma de ordenar código y de gestionarlo
cómodamente de una a otra aplicación y saber que no lo pueden modificar, disponer de una colección de clases para utilizar a medida que va
surgiendo la necesidad de su uso.
El código de la clase no es accesible por el usuario, por lo tanto ganamos en seguridad, y tranquilidad de que el fuente no puede
modificarse.
25.5. Las clases como estructuras de datos.
Las clases no solo pueden albergar código, también pueden gestionarse como una estructura de datos, que incluidas en una estructura
más amplia mediante un enlace entre uno y otro objeto permite la gestión de las mismas.
Por lo tanto en este caso, una clase no alberga código sino solo información.
Incluso podemos gestionar los datos de forma dinámica, lo más parecido a una lista.

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

Posteriormente como no pertenece al proyecto, lo hemos añadido,


Proyecto à Agregar Elemento existente.

De tal forma que ya aparece en la ventana del explorador de soluciones.

Y podemos ver también todo su contenido.

El siguiente paso es ya compilar la clase.


Generar à Generar Tema_24.

Si acudimos al directorio del proyecto en


C:\Apuntes\Tema_24\Tema_24\bin\Release

Encontraremos el archivo Tema_24.dll


Cerramos el proyecto de la clase.
Pág. 26.1
Unidad 26. Utilizar clases en VB (II)
26.4. Como incluir una clase en nuestra aplicación.
Si ahora creamos un proyecto nuevo, podremos incluir dicha librería.

Para ello una vez creado el nuevo proyecto, iremos a


C:\Apuntes\Tema_24\Tema_24\bin\Release

Y allí encontraremos nuestra clase.

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.

Dim Objeto As Ejercicios = New Ejercicios


No aparece Tema_24.

Ejercicios propuestos de la Unidad


Pág. 26.2
Ejercicios unidad 26: Utilizar clases en VB
1. Utilizar la clase del tema dieciséis y realizar todo el proceso de inserción explicado en un proyecto nuevo.
2. Repetir unos cuantos ejercicios del tema dieciséis, pero ahora usando la clase compilada.
Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.
Ayuda ejercicios unidad 26: Utilizar clases en VB
1. Utilizar la clase del tema dieciséis y realizar todo el proceso de inserción explicado en un proyecto nuevo.

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

Public Function AreaCirculo(ByVal Radio As Double) As Double


AreaCirculo = Radio * Radio * 3.1415
End Function

Public Function LongitudCirculo(ByVal Radio As Double) As Double


LongitudCirculo = Radio * 2 * 3.1415
End Function

Public Function AreaTriangulo(ByVal Base As Double, ByVal Altura As Double) As Double


AreaTriangulo = Base * Altura / 2
End Function

Public Function Primos(ByVal Numero As Long) As Boolean


Dim X As Integer = 3
Dim Final As Long
Dim Result As Boolean = True

Select Case Numero Mod 2 <> 0


Case True
Final = CLng(Numero / 2) + 1
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

Public 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

Public 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)
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

Public Function Fecha(ByVal D As Integer, _


ByVal M As Integer, _
ByVal A As Integer) _
As Boolean

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

Public 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

Public Sub NumerosPrimos(ByVal Desde As Integer, ByVal Hasta As Integer)


Dim x As Integer = Desde
While x <= Hasta
Select Case Primos(x)
Case True
Console.WriteLine("El número {0} es primo", x)
End Select
x=x+1
End While
End Sub
End Class

El siguiente paso es generar la clase, Generar  Generar Tema_26.


Esto dará como resultado un archivo en el directorio bin\release del archivo tema_26.dll.
Ese archivo es el que después deberá utilizarse en agregar referencia, cuando se desee utilizar está clase.
Utilización de la clase del Tema_26.
Creamos un proyecto nuevo, Tema_26_Utilizacion.

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

Escribimos Imports Tema_26, y ya podemos utilizar la clase que hemos escrito.

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.WriteLine("Cálculo del área y longitud de un circulo")


Radio = Console.ReadLine

Console.WriteLine("Area de radio {0} es {1} ", Radio, Objeto.AreaCirculo(Radio))


Console.WriteLine("Longitud radio {0} es {1} ", Radio, Objeto.LongitudCirculo(Radio))
Console.ReadKey()
End Sub
End Module

2. Hallar el área de un triángulo. Area = Base por Altura / 2.


Imports Tema_26
Module Module1
Sub Main()
Dim Objeto As New Tema_26.Ejercicios
Dim Base As Double
Dim Altura As Double

Console.WriteLine("Cálculo del área de un triángulo")


Console.WriteLine("Introducir Base")
Base = Console.ReadLine
Console.WriteLine("Introducir Altura")
Altura = Console.ReadLine
Console.WriteLine("Area triángulo de base {0} y altura {1} es {2} ", Base, Altura, Objeto.AreaTriangulo(Base, Altura))

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

Console.WriteLine("Convertir moneda ")


Console.WriteLine("Introducir pesetas")
Pesetas = Console.ReadLine
Console.WriteLine("Introducir moneda F/L/I/D/M/S/H/P")
Moneda = Console.ReadLine
Console.WriteLine("El importe de {0} pesetas en la moneda {1} es {2} ", Pesetas, Moneda, Objeto.ConversionMoneda(Pesetas, Moneda))
Console.ReadKey()
End Sub
End Module

Unidad 27. Utilizar y definir datos (I)


27.1. Objetivos del tema.
Hasta ahora lo que hemos estado viendo han sido distintas herramientas para el desarrollo de un programa.

Estructuras básicas de programación.


Secuencial
Repetitiva
Alternativa.
Funciones.
Procedimientos.
Clases.

Hemos dejado de lado la parte de los datos.


El apartado de datos abarca las estructuras, las formas de almacenamiento y de acceso.
Este es el apartado que vamos a iniciar con éste tema.
27.2. Introducción.
La existencia de un programa tiene como fin el de cumplir con un objetivo, sea lúdico o profesional.
En cualquiera de los ámbitos en los que podamos clasificar un programa, este casi es imposible crearlo si en él no se tiene en cuenta
como gestionar los datos que se utilicen en el mismo.
Evidentemente, habrá programas en los que la utilización de datos será exhaustiva, y otros en los que será mínimo.
Pero es imprescindible el conocer las distintas formas de utilizar datos en un programa para obtener el mejor rendimiento del mismo.
Su gestión en memoria se realiza mediante unas estructuras denominadas:
Variables.
Array.
Listas.

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.

En un programa se utiliza información para:


La ubicación en el ordenador de la instalación del programa.
La configuración de la interface con el usuario.
Los datos que el usuario genera como consecuencia de la utilización de un paquete en cuestión, contabilidad,
nominas, etc...

Esta información puede ser almacenada en distintos tipos de soporte


Disquetes,
Disco duro,
Memorias de distinto tipo.

Los soportes donde se almacenan los datos pueden ser o no direccionables.


Los soportes antes mencionados son direccionables.
125
Una cinta en cualquiera de sus distintas versiones no lo es.

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.

Los datos a utilizar en un programa pueden ser


Volátiles, desaparecen al finalizar el programa.
Duraderos, se conservan en algún tipo de soporte y pueden ser recuperados en cualquier momento o por otro
programa.

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

Unidad 27. Utilizar y definir datos (II)


27.3. Tipos de datos.
Al principio de esta colección de temas, vimos como los tipos de datos a utilizar en un programa son de los
dos tipos antes mencionados.
En los datos numéricos, en función del lenguaje utilizado, encontraremos una mayor o menor gama de
variaciones, pero básicamente serán de dos tipos, los que tienen decimales, -single, double, real -, y los que no
admiten decimales, integer.
Pero esto es lo que podríamos llamar tipos de datos estándar o del lenguaje.

27.4. Tipos de usuario.


A partir de estos datos se pueden crear lo que se denomina tipos de datos de usuario.
En realidad lo que se denomina un tipo de dato de usuario es un tipo de dato que lo que alberga en su interior es una estructura de datos.
En Vb actualmente se denomina structure, antes eran tipos de usuario.
En la imagen podemos ver como el dato que se almacenara en la estructura fecha, en realidad contiene tres informaciones, que son día
mes y año.

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.

Lo que sigue es un ejemplo de un tipo 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

Unidad 27. Utilizar y definir datos (III)


27.6. Anidamiento de los tipos de usuario.
A la hora de crear las estructuras de datos, estos no tienen porque ser de la forma que hemos visto antes, que
es totalmente válida por supuesto.
Los tipos de usuario pueden permitir que se creen estructuras de datos algo más complejas, pero que siguen
siendo a su vez igual o más cómodas.
Un sencillo ejemplo.
Podemos crear un tipo color
Tipo Colores
Descripción del tipo alfanumérico
Rojo del tipo numérico
Verde del tipo numérico
Azul del tipo numérico
Fin del tipo

Ahora podemos crear un tipo de los datos de una fuente de texto.


Tipo Texto
Descripción del tipo alfanumérico
Nombre del tipo alfanumérico
Tamaño del tipo numérico
Subrayado del tipo boolean
Negrita del tipo boolean
Cursiva del tipo bolean
Fin del tipo

Ahora podemos crear un tipo de datos de estilo de un párrafo.


Tipo Parrafo
Descripción del tipo alfanumérico
Fuente del tipo Texto
Color del tipo Colores
Fin del tipo

Y ahora podemos declarar una variable llamada


Estilo del tipo Parrafo

En esa variable podemos acceder a los datos de la siguiente forma, normalmente.


Parrafo.Fuente.Tamaño = 20
Parrafo.Fuente.Negrita = True
Parrafo.Color.Rojo = 10
Parrafo.Color.Azul = 10
Parrafo.Color.Verde = 10
Lo cual es sobre todo práctico a la hora de tener los datos convenientemente agrupados.
127
Aunque también hubiéramos podido declarar lo siguiente.
Tipo Texto
Descripción del tipo alfanumérico
Nombre del tipo alfanumérico
Tamaño del tipo numérico
Subrayado del tipo boolean
Negrita del tipo boolean
Cursiva del tipo bolean
Color del tipo Colores
Fin del tipo

Tipo Parrafo
Descripción del tipo Alfanumérico
Fuente del tipo Texto
Fin del tipo

Y ahora podríamos declarar una variable llamada


Crear Estilo del tipo Parrafo
Y su uso sería.

Estilo.Descripcion = “Nombre del estilo”


Estilo.Fuente.Tamaño = 20
Estilo.Fuente.Negrita = True
Estilo.Fuente.Color.Rojo = 10
Estilo.Fuente.Color.Azul = 10
Estilo.Fuente.Color.Verde = 10

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

Crear Registro del Tipo Persona

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

Crear Dato Como Silla


Ejercicios propuestos de la Unidad
Pág. 27.4
Ejercicios unidad 27: Utilizar y definir datos
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.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.


Ayuda ejercicios unidad 27: Utilizar y definir datos
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
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
129
Fin de Tipo

Crear Dato Como Silla

Unidad 28. Utilizar y definir datos en VB (I)


28.1. Objetivos del tema.
Veamos los datos ahora desde el punto de vista de VB.
Entrar en los tipos de usuario, ahora estructuras en VB, y sus características.
28.2. Introducción.
Hecha la introducción a nivel general en el tema anterior, ahora tenemos que profundizar sobre los datos en VB, los tipos básicos están ya
comentados a principio del curso, toca ahora ampliar el uso de los mismos y de sus estructuras, formas de almacenamiento y su acceso desde
VB.
28.3. Tipos de datos.
Ya hemos mencionado en un sin fin de ocasiones que arrancamos de dos tipos básicos, y que estos después se amplían en cada uno de
los lenguajes de programación existentes.
En los datos numéricos, en función del lenguaje utilizado, encontraremos una mayor o menor gama de variaciones, pero básicamente
serán de dos tipos, los que tienen decimales, -single, double, real -, y los que no admiten decimales, integer.
Byte Máximo Mínimo
s
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 (positivos) 4 3.402823E+38 1.401298E-45
Single precisión 4 -1.401298E-45 -3.402823E+38
números(negativos)
Double precisión números(positivos) 8 1.797693134862315D+308 4.940656458412465D-324
Double precisión números 8 -4.940656458412465D- -
(negativos) 324 1.797693134862315D+308
Pero esto es lo que podríamos llamar tipos de datos estándar o del lenguaje.

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.

Las constantes y las variables han de declararse antes de utilizarse.


La declaración de una constante es como sigue:

Const PI As Double = 3.1416


Para declarar constantes se utiliza el calificador Const nombre tipo y valor

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.

Public Ruta As String = “C:\Archivo.Ext”


Como public tiene sentido a nivel de programa o en un módulo disponible así para toda la aplicación.
Como private tiene sentido solo a nivel de procedimiento o función.

En caso de declarar un objeto en lugar de una variable, podemos hacer


Dim Objeto as Clase
En cuyo caso el objeto queda con un valor nulo.
O bien podemos declarar e inicializar el objeto directamente.
Hay que tener presente que la inicialización dependerá siempre de cómo esté diseñada la clase.
Dim Objeto As Clase = New Clase (50,60)
Pág. 28.1

Unidad 28. Utilizar y definir datos en VB (II)


130
28.5. Conversión de tipos.
En algunos casos, es necesario convertir una variable de un tipo en otro. Por ejemplo, puede que se necesite pasar una variable int a un
método que acepte solamente variables single. Este proceso se denomina conversión de tipo.
Para convertir el tipo de una variable, basta utilizar la función adecuada de conversión. El siguiente ejemplo muestra cómo el valor
devuelto por un método, de tipo int, puede convertirse en single:
Dim A As Single
Dim B As Integer
B = CSng(A)
Debe tenerse cuidado cuando se conviertan tipos, ya que es posible que se produzca una pérdida de información.
Por ejemplo, cuando se convierte una variable long de 64 bits en una variable int de 32 bits, el compilador omite los 32 bits de orden
superior de la variable long .
Si, en el momento de realizar la conversión de tipo, el valor de la variable long ocupase más de 32 bits, en el proceso de conversión se
asignaría un valor incorrecto a la variable int .

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

28.7. Tipos de estructuras.


En un programa los datos pueden tener distintas formas.
Constante. Un dato que permanece invariable a lo largo del programa.
Variable. Un dato que cambia de valor a lo largo del programa.
Array. Es una estructura estática de datos, una agrupación de datos, del mismo tipo, los cuales es posible referenciar con un único
nombre y diferenciarlos a través de un índice.
Colecciones Es una estructura dinámica de datos, similar a un array. Collections.
Listas Existe una clase especializada en su gestión, List.

28.8. Ambito de las variables.


En términos generales las variables se consideran locales y globales, o públicas y privadas, después aparece las características de cada
lenguaje de programación.
En VB las variables se consideran privadas o locales, y se definen dentro de un método, procedimiento o función, por lo que al finalizar el
método desaparece la variable, se destruye.
Dim dato1, dato2, resultado As Double
Se pueden declarar a nivel de la clase, módulo o formulario acompañadas de la palabra public.
Public Class Clase
Public Dat1 As Integer = 1000
Y entonces podrá ser utilizada por el objeto que se cree de dicha clase.
.. / ..
Dim Objeto As Clase = New Clase()
Objeto.Dat1 = 23
.. / ..
Se pueden declarar a nivel de la clase, acompañadas de la palabra private.
Public Objeto As Clase
private Double dat1 = 1000;
Se pueden declarar dentro de una sentencia If, y al finalizar ésta sentencia finaliza su posibilidad de usarse.
if (condición) Then
Dim variable = 5
instrucción;
... / ...
instrucción;
End if
En general se pueden declarar dentro de un bloque de código, entendiendo por bloque lo comprendido el contenido entre un inicio y final
de estructura que lo pueda permitir como es un sentencia If.
28.9. Tipos de usuario, estructuras.
El motivo de llamarlos estructuras actualmente no deja de tener algo de sentido, peo conviene que sepamos también que los dos términos
son equivalentes.
La declaración de los mismos en la versión actual de VB es
Structure Monitor

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

Unidad 28. Utilizar y definir datos en VB (III)


28.10. Tipos de usuario anidados.
Pero habitualmente en las estructuras de datos es normal que un tipo de usuario albergue a otros tipos de usuario, o que los tipos se
aniden unos a otros.
Structure Mueble
Dim Color As String
Dim Construido as string
Dim Uso as string
Dim Fabricante as string
End Structure

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.

Ejercicios propuestos de la Unidad


Pág. 28.3
Ejercicios unidad 28: Utilizar y definir datos en VB
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.
Se trata traducir la solución de los ejercicios del tema anterior a VB.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.


Ayuda ejercicios unidad 28: Utilizar y definir datos en VB
1. Defina un tipo de usuario que le permita utilizar todos los datos relacionados con las características de un monitor.
Structure Monitor
Dim Marca As String
Dim Pulgadas As Integer
Dim Resolución As String
Dim Velocidad As String
End Structure
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.
Structure Mueble
Dim Color As String
Dim Construido as string
Dim Uso as string
Dim Fabricante as string
End Structure

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

Dim Dato As Silla

Unidad 29. Enumeraciones (I)


29.1. Objetivos del tema.
Ver el uso de las enumeraciones dentro de un programa y sus ventajas.
29.2. Introducción.
Las enumeraciones es una gran comodidad dentro de la creación de un programa.

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.

Por ejemplo a la variable Curso, le asignamos los siguientes posibles valores.


Valor Significado
1 Primero
2 Segundo
3 Tercero

Lo cual implica que en el programa crearemos el siguiente código


Si Curso = 1 Entonces …..
Si Curso = 2 Entonces ….
Y así sucesivamente

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

Lo cual permite después escribir lo siguiente


Si Curso = Cursos.Primero Entonces ...
Si Curso = Cursos.Segundo Entonces ...
Que resulta mucho más cómodo, y sobre todo seguro al evitar errores de uso del valor adecuado en el código, ya que todos sus valores
posibles se suponen declarados.
En la ampliación de VB, se ilustra de forma más clara el uso de las enumeraciones.

Pág. 29.1

Unidad 30. Enumeraciones en VB (I)


30.1. Objetivos del tema.
Ilustrar el uso de las enumeraciones en VB.
30.2. Introducción.
El uso de las enumeraciones en VB está muy logrado, pues el entorno de programación las integra de una manera muy cómoda para el
programador, utilizándola como ayuda en las llamadas a los procedimientos y funciones.
30.3. Creación.
La sintaxis a usar es la que vemos a continuación
Enum Monedas
Euro = 1
Dolar = 2
Libra = 3
Yen = 4
End Enum

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.

Es la definición del nombre de la enumeración.


Enum Monedas

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.

Public Function Convertir(ByVal Cual As Monedas) As Double


Select Case Moneda
Case Monedas.Euro
Select Case Cual
Case Monedas.Dolar
Convertir = Import * 1.22
Case Monedas.Libra
Case Monedas.Yen
End Select
Case Monedas.Dolar
Case Monedas.Libra
Case Monedas.Yen
End Select
End Function
Lo mismo sucede con la escritura de un Select Case, por ejemplo, en la que en el momento de escribir la palabra case se despliega
automáticamente la enumeración para poder ver los valores disponibles y su valor.

Su uso 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. 30.1

Unidad 30. Enumeraciones en VB (II)


30.4. Recorrido
El contenido de una enumeración se puede recorrer capturando primero el contenido mediante la siguiente línea.
' Se captura los códigos
Valores = System.Enum.GetValues(GetType(Monedas))
' Se captura los nombres
Nombres = System.Enum.GetNames(GetType(Monedas))
Para ello hay que declarar las variables Valores y Nombres del tipo Array
Dim Valores As Array
Dim Nombres As Array
Como el recorrido se hará basándose en un bucle del tipo

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.

Ejercicios propuestos de la Unidad


Pág. 30.2
Ejercicios unidad 30: Enumeraciones en VB
1. Declarar una enumeración para los posibles valores del estado de un semáforo.
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.
3. Realizar la carga de los valores de una de las enumeraciones anteriores y visualizarlas por pantalla.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.


Ayuda ejercicios unidad 30: Enumeraciones en VB
1. Declarar una enumeración para los posibles valores del estado de un semáforo.
Enum Semaforo
Abierto = 1
Cambia = 2
Cerrado = 3
End Enum

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

' Se captura los códigos


Valores = System.Enum.GetValues(GetType(Seguridad))
' Se captura los nombres
Nombres = System.Enum.GetNames(GetType(Seguridad))
' Se captura el número de elementos de la enumeración
X = Valores.Length - 1
' Se defina el vector con el valor de X,
Dim V(X) As Enumeracion

' Se pasa al vector los códigos


X = 0
For Each item In Valores
V(X).Codigo = CInt(item)
X = X + 1
Next
' Se pasa al vector los nombres
X = 0
For Each item In Nombres
V(X).Denom = item
X = X + 1
Next
' Se visualiza el contenido
X = 0
Do
Console.WriteLine("Código es {0} y su valor {1} ", V(X).Codigo,
V(X).Denom)
X = X + 1
Loop Until X = V.Length
Console.ReadLine()
End Sub
End Module

Unidad 31. Colecciones (I)


31.1. Objetivos del tema.
Una de las estructuras de datos, aunque no tenga porque albergar exclusivamente datos una colección, son las colecciones, que es el
tema que vamos a abordar.
31.2. Introducción.
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.
Desde el momento en que podemos declarar un array del tipo de un objeto determinado, un array es muy similar a una colección.
Dado que una colección esta gestionada por una clase dentro del lenguaje que estamos utilizando, y en cierta forma no se tiene un control
total de su estructura, la clase dispone de una serie de métodos que nos permiten realizar la mencionada gestión, y dado que no disponemos de
un índice propiamente dicho, la gestión se basa en su recorrido, adición y eliminación.
31.3. Motivos para el uso de una colección.
Cuando en un programa estamos utilizando una clase de la cual se tienen que realizar un indeterminado número de instancias, que
posteriormente hay que gestionar, la forma ideal de hacerlo es la de utilizar una colección, ya que hay que tener presente que cada instancia de
una clase deriva en un objeto, el cual de alguna forma tiene que tener algo que lo referencie y ese algo es muy cómodo que lo sea como miembro
de una colección de elementos, de elementos del mismo tipo, y el tipo no es otro que la clase de la que se deriva.
Dado que la colección nos permite crear un número indeterminado de elementos, pues es la estructura ideal.
Con los datos puede suceder algo similar, si desconocemos cuantos elementos vamos a tener podemos utilizar una colección, si el
direccionamiento no es imprescindible, ya que la colección es una estructura dinámica.
Las colecciones disponen de una serie de métodos que ya están escritos y que facilitan su gestión.
Son dinámicas, se puede añadir elementos sin tener que ampliar su capacidad, ya que ésta no está definida en un principio como sucede
en un vector.
El contenido de una colección puede ser de cualquier tipo, incluso indefinido, aunque eso provoca habitualmente un descenso en el
rendimiento en el acceso a los elementos de la misma.
31.4. Direccionamiento en una colección.
Las colecciones son como un vector con una serie de elementos similares o relacionados entre si y
que están organizados en una estructura ordenada.

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.

Tipos de gestión de los datos.


Lista.
Pila.
Cola.
Emparejamiento de datos, clave y valor.

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

La clase array para la gestión con matrices.


La clase Collections dispone de dos clases a su vez:
Generic
Specialized

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.

Las clases System Collections pueden dividirse en tres tipos:

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.

Los tipos de colecciones a utilizar se basan en la forma en la que se realiza el acceso.


Lista Secuencial en la que se descarta el miembro tras su recuperación, Lifo, Fifo.

138
Snack, Pilas
Queue, Colas
LinkedList

Si se desea acceder por un índice


StringCollection ArrayList
List HashTable
SortedList ListDictionary
StringDictionary
A su vez cada una de ellas en casos concretos son mejores que otras, por ejemplo ListDictionary es más rápida que HashTable en
colecciones pequeñas.
32.3. Creación.
La definición de una colección es como sigue.
Dim Coleccion As System.Collections.SortedList
La forma de añadir elementos
Coleccion.add(123,"Mesas")
Conviene que realice la creación de la colección con distintos tipos de colección y observe el cambio de los métodos disponibles en la
misma en función del tipo elegido.
Dim Coleccion As System.Collections.Queue
En este tipo de colección el insertar un elemento tiene una sintaxis distinta.
Dim Algo as New Object
Dim Objetos As New System.Collections.Queue
Objetos.Enqueue(Algo)
Se está utilizando una cola, una lista.
Todo esto va englobado después en una estructura repetitiva en la cual se crea la colección para tratarla posteriormente.

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:

Creamos una clase de la que instanciar luego objetos.


Public Class Datos
Public Nombre As String

Public Sub New()


End Sub
End Class
Para después realizar algo parecido a lo siguiente:
Module Module1
Sub Main()
Console.WriteLine("Carga colección de objetos.")

Dim Coleccion As System.Collections.Generic.List(Of Datos)


Dim Item As New Datos

Item.Nombre = "Silla"
Coleccion.Add(Item)

Item = New Datos()


Item.Nombre = "Naranja"
Coleccion.Add(Item)
End Sub
End Module
El ejemplo anterior funciona correctamente tal como se describe, sin embargo como prueba de lo que a veces la lógica te puede llevar a
hacer, conviene probarlo comentando la siguiente línea.
Item = new Datos()
El resultado es que al recorrer la colección, se muestra solo el último valor introducido en la misma.
Pág. 32.1
Unidad 32. Colecciones en VB (II)
32.4. Recorrido.
La forma de recorrerla es creando una estructura repetitiva, esta estructura va a depender en cierta medida del tipo de colección creada,
pero veamos dos formas de hacerlo.

139
Sub Main()
Dim Coleccion As New System.Collections.Generic.List(Of Datos)
Dim Item As New Datos

Item.Nombre = "Silla”
Coleccion.Add(Item)

Item = New Datos()


Item.Nombre = "Naranja”
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")

' PV es una Pareja de Valores


' PV es del tipo KeyValuePair(Of Integer, String)
For Each PV As KeyValuePair(Of Integer, String) In Coleccion
Console.WriteLine("Clave = {0}, Valor = {1}", PV.Key, PV.Value)
Next
Hay que ser consecuente con la declaración de la colección.
Dim Coleccion As New System.Collections.Generic.SortedList(Of Integer,
String)
Para después utilizar el objeto PV con la declaración adecuada, (Of Integer, String)

32.5. Operaciones con una colección.


Una vez que disponemos de una colección, además de la acción de añadir elementos y recuperar elementos de la colección, podemos
quitar elementos , comparar elementos.
1 Métodos principales.
Add Añade un elemento a la colección
Clear Limpia, vacía el contenido de la colección.
Clone Obtiene una copia de la colección actual.
Contains Determina si el elemento de referencia existe en la colección
CopyTo Realiza una copia del contenido de la matriz sobre un array.
Equals Determina si el objeto de referencia es igual al objeto actual.
Find Busca un elemento en la colección.
GetRange Devuelve un array que es un subconjunto de la colección
IndexOf Devuelve la posición de la primera aparición del objeto de referencia en la colección.
Insert Inserta un elemento en la colección
InsertRange Inserta los elementos especificados en la posición indicada.
LastIndexOf Devuelve la última posición de la primera aparición del objeto de referencia en la colección.
Remove Quita la primera aparición del elemento especificado.
RemoveAt Quita el elemento de la posición especificada.
RemoveRange Quita los elementos del rango especificado
SetRange Copia el rango especificado en un array

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.

Borra el elemento con el índice indicado.


Coleccion.RemoveAt(1)
Borra los elementos que se indican, Cuantos, desde la posición indicada PosiciónInicial.

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()

4 Posición de un elemento, indexOf.


Si deseamos saber la posición de un elemento, podemos utilizar el método indexOf.
Este método nos devuelve la posición del elemento en la colección, o el valor -1 si no lo encuentra.

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)

Item = New Datos()


Item.Nombre = "Mesa"
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

Dim Dato As Datos


For Each Dato In Coleccion
Console.WriteLine(Dato.Nombre)
Console.WriteLine(Dato.Nombre.GetHashCode)
Next
Item = New Datos
Item.Nombre = "Silla"
Console.WriteLine(Item.GetHashCode)
Console.WriteLine(Coleccion.IndexOf(Item))
Y en este otro ejemplo
Console.WriteLine("Antes")
Dim Dato As Datos
For Each Dato In Coleccion
Console.WriteLine("Valor {0} ",
Dato.Nombre)
Console.WriteLine("HashCode {0} ",
Dato.Nombre.GetHashCode)
Next
Console.WriteLine("Creación de item")
Item = New Datos
Item.Nombre = "Silla"

Console.WriteLine("HashCode {0} ",


Item.GetHashCode)
Console.WriteLine("IndexOf {0} ",
Coleccion.IndexOf(Item))
142
Console.WriteLine("Contains {0} ", Coleccion.Contains(Item))

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.

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 Tres

El valor de la segunda posición se sustituye por el nuevo valor.


El método insertRange inserta los elementos indicados a partir de la posición indicada.
Dim Otra As New System.Collections.Generic.List(Of Datos)

Item = New Datos()


Item.Nombre = "Tres"
Item.Longitud = 21
Otra.Add(Item)

Item = New Datos()


Item.Nombre = "Cuatro"
Item.Longitud = 42
Otra.Add(Item)

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

6 Copiado de la colección, CopyTo, ToArray.


El método CopyTo nos permite obtener un array del contenido de la colección.
El método ToArray también, cambia la sintaxis, por ser una función.
La sintaxis para la declaración del vector V, puede ser así:

Dim V(Coleccion.Count - 1) As Datos

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

Dim V(Coleccion.Count - 1) As Datos


Usamos Colección.count –1 para que el array quede bien declarado en su número de elementos.
La colección se inicia en el elemento uno y el vector en el elemento cero.
La colección si tiene tres elementos son el 1,2 y 3.
El vector sería el 0,1 y 2.
7 Clone.
Realiza una copia superficial de una colección, sólo copia los elementos de dicha colección, tanto si son tipos de referencia como si son
tipos de valor, pero no copia los objetos a los que hacen referencia las referencias.
Las referencias de la nueva colección apuntan a los mismos objetos que las referencias de la colección original.

La sintaxis para utilizar el método Clone es:


Otra = CType(Coleccion.Clone(), SortedList)
Ctype es para permitir el cambio de una colección a otra.

Y la clonación se realiza en realidad así:


Coleccion.Clone()
Un ejemplo completo para el uso de Clone.
Dim Coleccion As New System.Collections.SortedList
Dim Otra As New System.Collections.SortedList

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

Otra = CType(Coleccion.Clone(), SortedList)

For x = 0 To Otra.Count - 1
Console.WriteLine(" Clave {0} Valor {1} ", Otra.GetKey(x),
Otra.GetByIndex(x))
Next

8 Comparar, Contains, ContainsKey, ContainsValue.


Podemos comprobar si determinada información existe o no en una colección.
El método que lo realiza es contains, que devuelve true o false.
La sintaxis del mismo es
Coleccion.Contains(Item))
Siendo Item
Item = New Datos
Item.Nombre = "Silla"
Y su utilización por ejemplo:
Console.WriteLine("Contains {0} ", Coleccion.Contains(Item))
Donde “Silla” es el dato que deseamos comprobar, pero recordemos que no buscamos “Silla”, si no un elemento en esa colección, que
está representado por Item, y que es este caso contiene “Silla”
En las colecciones en las que se dispone de clave y valor el uso es el que sigue.
Console.WriteLine(Coleccion.ContainsValue("Silla"))

144
Console.WriteLine(Coleccion.ContainsKey("2"))
Pág. 32.4

Unidad 32. Colecciones en VB (V)


9 Comparar dos objetos, Equals.
Realiza una comparación y devuelve true si ambos objetos son iguales.
La sintaxis es
Coleccion.Item(1).Equals(Otra.Item(2))
Un ejemplo de su utilización
Console.WriteLine(Coleccion.Item(1).Equals(Otra.Item(2)))
10 Obtener un subconjunto de la colección, GetRange.
Devuelve un array que es un subconjunto de la colección origen.
Realiza la copia del contenido de la colección pero no de los enlaces de sus miembros.
La sintaxis es la que sigue.
Coleccion.GetRange(Desde, Cuantos)
Donde desde es la primera posición desde la que se inicia la copia
Cuantos es el número de elementos que se van a copiar.
Un ejemplo:
V = Coleccion.GetRange(1, 2).ToArray()
En el que V es un vector del mismo tipo que los objetos de la colección.
V = Coleccion.GetRange(1, 2).ToArray()
For Each Dato In V
Console.WriteLine("Valor {0} ", Dato.Nombre)
Next

11 Búsqueda, Find, FindAll, FindIndex, FindLastIndex.


Disponemos de varias posibilidades a la hora de realizar búsquedas.

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)

Primero hemos de crear una colección que recoja el resultado


Dim Nueva As New System.Collections.Generic.List(Of Datos)
Después solo queda utilizar el método.
Para ello se recurre a una función que analiza el valor del elemento de la colección que se le envía devolviendo true o false e
incorporándolo a la nueva colección.

La función la hemos llamado Resultado


Public Function Resultado(ByVal Item As Datos) As Boolean
Resultado = Item.Nombre = "Silla"
End Function
Y en este caso devolverá todos los elementos que sean una “Silla”
Dim Nueva As New System.Collections.Generic.List(Of Datos)
Nueva = Coleccion.FindAll(AddressOf Resultado)

For Each Dato In Nueva


Console.WriteLine("Valor {0} ", Dato.Nombre)
Next
Para saber el índice de un elemento
Console.WriteLine(Coleccion.FindIndex(AddressOf Resultado))

Siguiendo la misma filosofía que en el ejemplo anterior.


En éste caso nos devolverá el índice que ocupa en la colección el elemento buscado.

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()

For Each D In Coleccion


Console.WriteLine("Valor {0} ", D)
Next

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.

Ejercicios propuestos de la Unidad


Pág. 32.5
Ejercicios unidad 32: Colecciones en VB
1.- Crear una colección que nos permita la gestión de los valores del tipo
Código
Denominación

2.- Introducir diez números y luego visualizarlos en orden inverso, al de entrada.

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

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.


Ayuda ejercicios unidad 32: Colecciones en VB
1.- Crear una colección que nos permita la gestión de los valores del tipo
Código
Denominación
Module Ejercicios
Public Sub Uno()
Dim Coleccion As New System.Collections.Generic.SortedList(Of Integer,
String)
Coleccion.Add(1, "Silla")
Coleccion.Add(25, "Mesa")
Coleccion.Add(3, "Puerta")
' PV es una Pareja de Valores
' PV es del tipo KeyValuePair(Of Integer, String)
For Each PV As KeyValuePair(Of Integer, String) In Coleccion
Console.WriteLine("Clave = {0}, Valor = {1}", PV.Key, PV.Value)
Next
End Sub
End Module

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

Dato = New Ejercicio


Dato.Codigo = 1
Dato.Nombre = "Uno"
Pila.Push(Dato)

Dato = New Ejercicio


Dato.Codigo = 2
Dato.Nombre = "Dos"
Pila.Push(Dato)

Dato = New Ejercicio


Dato.Codigo = 3
Dato.Nombre = "Tres"
Pila.Push(Dato)

For Each Dato In Pila


Console.WriteLine("código {0} nombre {1} ", Dato.Codigo,
Dato.Nombre)
Next
Console.WriteLine("Quitado un elemento.")
Dato = CType(Pila.Pop, Ejercicio)
Console.WriteLine("código {0} nombre {1} ", Dato.Codigo, Dato.Nombre)
Console.WriteLine("Añadido un elemento, cuatro.")
Dato = New Ejercicio
Dato.Codigo = 4
Dato.Nombre = "Cuatro"
Pila.Push(Dato)

Console.WriteLine("Inicio de nuevo bucle.")


For Each Dato In Pila
Console.WriteLine("código {0} nombre {1} ", Dato.Codigo,
Dato.Nombre)
Next

Console.WriteLine("Quitado un elemento.")
Dato = CType(Pila.Pop, Ejercicio)
Console.WriteLine("código {0} nombre {1} ", Dato.Codigo, Dato.Nombre)

Console.WriteLine("Inicio de nuevo bucle.")


For Each Dato In Pila
Console.WriteLine("código {0} nombre {1} ", Dato.Codigo,
Dato.Nombre)
Next
End Sub
End Module

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

Private Sub Tres()


Dim Cola As New Collections.Queue
Dim Dato As Ejercicio

Dato = New Ejercicio


Dato.Codigo = 1
Dato.Nombre = "Uno"
Cola.Enqueue(Dato)

Dato = New Ejercicio


Dato.Codigo = 2
Dato.Nombre = "Dos"
Cola.Enqueue(Dato)

For Each Dato In Cola


Console.WriteLine("código {0} nombre {1} ", Dato.Codigo,
Dato.Nombre)
Next

Dato = CType(Cola.Dequeue, Ejercicio)


Console.WriteLine("código {0} nombre {1} ", Dato.Codigo, Dato.Nombre)

Dato = New Ejercicio


Dato.Codigo = 3
Dato.Nombre = "Tres"
Cola.Enqueue(Dato)
Console.WriteLine("Quitado y añadido un elemento, Inicio de nuevo
bucle.")

For Each Dato In Cola


Console.WriteLine("código {0} nombre {1} ", Dato.Codigo,
Dato.Nombre)
Next

Dato = CType(Cola.Dequeue, Ejercicio)


Console.WriteLine("código {0} nombre {1} ", Dato.Codigo, Dato.Nombre)

Console.WriteLine("Quitado un elemento, Inicio de nuevo bucle.")

For Each Dato In Cola


Console.WriteLine("código {0} nombre {1} ", Dato.Codigo,
Dato.Nombre)
Next
End Sub
End Module

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

Private Function Resultado(ByVal Item As Ejercicio) As Boolean


Resultado = Item.Tipo = "P"
End Function

Public Sub Cuatro()


Dim Evento As New System.Collections.Generic.List(Of Ejercicio)
Dim Persona As Ejercicio
Persona = New Ejercicio
With Persona
.Codigo = 1
.Nombre = "Pedro"
.Tipo = "P"
End With
Evento.Add(Persona)

Persona = New Ejercicio


With Persona
.Codigo = 2
.Nombre = "Luisa"
.Tipo = "P"
End With
Evento.Add(Persona)

Persona = New Ejercicio


With Persona
.Codigo = 1
.Nombre = "Imma"
.Tipo = "I"
End With
Evento.Add(Persona)

Persona = New Ejercicio


With Persona
.Codigo = 2
.Nombre = "Javier"
.Tipo = "I"
End With
Evento.Add(Persona)

Persona = New Ejercicio


With Persona
.Codigo = 1
.Nombre = "Carlos"
.Tipo = "O"
End With
Evento.Add(Persona)

Persona = New Ejercicio


With Persona
.Codigo = 2
.Nombre = "Cristina"
.Tipo = "O"
End With
Evento.Add(Persona)

For Each Persona In Evento


With Persona
149
Console.WriteLine("Tipo {0} código {1} nombre {2}
",.Tipo,.Codigo,.Nombre)
End With
Next

Dim Ponentes As New System.Collections.Generic.List(Of Ejercicio)


Ponentes = Evento.FindAll(AddressOf Resultado)

For Each Persona In Ponentes


Console.WriteLine("Ponentes {0} ", Persona.Nombre)
Next
End Sub
End Module

Unidad 33. Arrays (I)


33.1. Objetivos del tema.
En este tema entramos en las estructuras de datos que se almacenan en memoria, veremos la utilización de arrays de una, dos y más
dimensiones.
33.2. Introducción.
Hasta ahora los datos se han utilizado bajo una variable la cual podía albergar un único dato, o varios datos agrupados bajo una definición
de tipo de usuario, pero en realidad seguía siendo una única información.
Un array es una estructura de datos que permite almacenar un número de datos en memoria que vendrá limitado por la capacidad de
memoria del equipo y por el número de elementos que permita utilizar el lenguaje que estemos utilizando en ese momento.
Una variable permite almacenar un dato al cual le asignamos un nombre en el programa.
Un array tiene un nombre, igual que una variable, pero como su misión es la de permitirnos manejar más de una información, le
incorporamos un índice para que podamos identificar cual de los datos que tenemos bajo esa variable queremos utilizar, o donde deseamos
guardarlo.
33.3. Datos.
Hasta ahora utilizábamos una variable para un dato, y si deseamos utilizar dos datos, teníamos que tener dos variables.

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.

Los arrays pueden tener una, dos o más dimensiones.


Cuando tienen una dimensión se conocen también como vectores, y cuando disponen de dos o más dimensiones como matrices.

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.

33.5. Índice en un array.


Un array tiene un principio y un final, eso viene dado por el número de elementos que se indica
en el momento de la creación.
Un vector de diez elementos dispone de índices desde 0 hasta nueve, o desde 1 hasta 10.
Eso va depender de la base en la que ese lenguaje trabaje.
Actualmente la más utilizada es la de base cero, eso implica que el primer índice de un vector es la cero y la última n-1, siendo n el
número de elementos con los que se declara el array.
Cuando el primer índice es el uno, se dice que trabaja en base uno, u sus elementos van desde uno hasta n, el número de elementos del
array.
Esto hace referencia igual para un vector que para una matriz.
Para referirnos en el vector “V” al elemento con el valor cuatro nos referiremos como V(2), si
en el lenguaje utilizado la primera posición del vector es la cero, o bien V(3) si es la uno.
En una matriz, “M”, como la que tenemos en el ejemplo, el valor cuatro sería M(0,2) o M(1,3), en función de que la primera posición fuera
la cero o la uno.

El primer valor de los paréntesis hace referencia a la fila y el segundo a la columna.


33.6. Acceso.
El acceso a los datos de un array, es directo no hay que recorrer los elementos
anteriores al que queremos utilizar. Pero esto depende de que la información que
almacenamos en el array permita que se pueda direccional.
En el ejemplo anterior no hay ningún criterio para localizar los datos que tenemos en
V.

Sin embargo en el que sigue sí.


Los nombres de los meses están en el lugar que les corresponde.

Se ha dejado la posición 0 vacía y de esa forma ya no hay ningún problema entre


índice y posición, aunque también se podría haber utilizado la posición como x-1.

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:

Para la misma matriz en vertical 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.

La estructura repetitiva utilizada para la solución es un bucle anidado dentro de otro.


Es una estructura habitual dentro de la programación.
Pág. 33.2

Unidad 33. Arrays (III)


33.8. Carga de datos.
Una vez que disponemos de una estructura de datos en memoria, el siguiente paso es realizar la carga de los mismos en dicha estructura
de datos.
Definición
Crear V(10) como Entero
La carga de los mismos se realizará habitualmente mediante una estructura de tipo repetitivo, lo cual no quita evidentemente que en
alguna ocasión haya que hacerlo de alguna forma más rústica, V(0) = 5.
Carga
X=0
Hacer
X=X+1
Leer "Introduce un número ", V(X)
Hasta que X=10
La estructura del bucle dependerá de cómo en cada lenguaje se definan los elementos en el mismo.
La estructura de antes es válida, pero la que sigue también.
Carga
X=0
Hacer
Leer "Introduce un número ", V(X)
X=X+1

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.

Entero Izquierda, Derecha, x


Boolean Encontrado = Falso

// Límites izquierdo y derecho iniciales


Izquierda = 0 // Base cero.

153
Derecha = LongitudVector – 1
// Punto medio entre los dos límites
x = Entero((Izquierda / Derecha) / 2)

Mientras ((Encontrado = Falso) And (Izquierda < Derecha))

Encontrado = (v[x] = x) // Lo hemos encontrado si son


iguales
Si no Encontrado
Si v[x] > x Entonces Derecha = X // Está a la izquierda del centro
Si v[x] < x Entonces Izquierda = X // Está a la derecha del centro
X = (Izquierda/Derecha) / 2 // Calculamos el nuevo punto
medio
Fin de Si
Fin de mientras
En este ejemplo tendremos en X la posición del elemento existente cuando Encontrado sea cierto.
Pág. 33.3

Unidad 33. Arrays (IV)


33.11. Aplicación de los vectores.
La aplicación de un vector al igual que el de una matriz, es muy diversa, y queda a la capacidad de imaginación de cada uno, pero vamos
a ilustrar unos ejemplos.
Un ejemplo de la aplicación de un vector lo hemos visto antes, almacenar los datos del nombre de cada uno de los meses del año, o el
nombre de los días de la semana.
NombreMes(12) Como Texto
NombreDias(7) Como Texto

DiaSemana = 7
Dia = 28
Mes = 12
Año = 2008

Visualizar “Hoy es “ + NombreDias(DiaSemana) + “, ” + Dia + “ de “ +


NombreMes(Mes) + ” de “ + Year + “.”
Que sería algo así
“Hoy es domingo, 28 de diciembre de 2008.”

33.12. Aplicación de las matrices.


Por no irnos por las ramas, una ilustración muy fácil sería la del juego de tres en raya, un sudoku.
El tres en raya sería una matriz de 3x3, el sudoku, podría ser una matriz de 9x9 o bien 9 matrices de 3x3, todo dependería de cómo
quisiera cada uno implementar el programa.

Otro uso muy habitual de una matriz es su uso en cálculos estadísticos.

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.

El ejemplo superior es un vector de 7 elementos, un array de una dimensión.


El ejemplo lateral, es una matriz de dos dimensiones, 3 x 3, un array de dos dimensiones.

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.

' 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 mes as Integer = 1
Console.writeln(NomMeses[mes])
Y si probamos éste ejemplo, veremos como el resultado es que el mes es Febrero, sí, porque la primera posición del array es cero y es el
mes de Enero, y al índice que es la variable “mes”, le hemos dado el valor uno, que es la posición del mes de “Febrero”.

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

Dim V(11) as String


Este vector tiene en realidad doce elementos, que van desde el cero hasta el once, en total doce.
Hay varias formas de declarar un vector en VB.

Podemos declararlo de forma estática.


Podemos declarar e inicializar.
Podemos declarar de forma dinámica.
1 Declaración estática.
La declaración estática es la de siempre.
Dim Meses(11) as String

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

‘ En esta línea nos dará Nothing, no hay asignación todavía


Console.WriteLine("Tipo del vector {0} ", TypeName(OtrosMeses))

‘ Asignación de dimensión
ReDim Otrosmeses(Meses.GetUpperBound(0))

‘ Aquí el resultado será String


Console.WriteLine("Tipo del vector {0} ", TypeName(OtrosMeses))

Console.WriteLine("Visualizamos el contenido ")

‘ Copia de meses sobre otros meses


Meses.CopyTo(OtrosMeses, 0)

‘ Visualización del vector


For Each Valor In OtrosMeses
Console.WriteLine(Valor)
Next

Console.WriteLine("Elementos del vector {0} ", OtrosMeses.GetLength(0))


Console.WriteLine("Primer índice {0} ", OtrosMeses.GetLowerBound(0))
Console.WriteLine("Ultimo índice {0} ", OtrosMeses.GetUpperBound(0))
Console.WriteLine("Visualizamos el contenido ")
Console.ReadLine()
End Sub
End Module
Pág. 34.1
Unidad 34. Arrays en VB (II)
34.4. Recorrido.
Para recorrer el vector podemos usar cualquiera de los dos sistemas, el de recorrerlo como una colección.
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"}
' Declaramos la variable del mismo tipo para poder
' recorrer el vector
Dim Valor As String

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")

' Mostramos lo valores


For X = 0 To UBound(Meses)
Console.WriteLine(Meses(X))
Next

For X=Meses.GetLowerBound(0) To Meses.GetUpperBound(0)


Console.WriteLine(Meses(X).ToString)
Next

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.

En el ejemplo utilizamos una matriz de dos dimensiones.


Veamos primero como cargar datos, usando una generación aleatoria de números.
Module Ejemplo
Sub Main()
' Declaración e inicialización
Dim M(3, 4) As Integer ‘ veinte elementos
Dim X As Integer
Dim Y As Integer

Randomize() ' inicializar el generador de números aleatorios

' generar la matriz


X = 0
Do
Y = 0
Do
M(X, Y) = CInt(Int((6 * Rnd()) + 1))
Y = Y + 1
Loop Until Y > UBound(M, 2)

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

Randomize() ' inicializar el generador de números aleatorios

' generar la matriz


X = 0
Do
Y = 0
Do
M(X, Y) = CInt(Int((6 * Rnd()) + 1))
Y = Y + 1
Loop Until Y > UBound(M, 2) ‘ columnas
X = X + 1
Console.WriteLine()
Loop Until X > UBound(M, 1) ‘ filas

Console.WriteLine("Visualizamos el contenido")

' Mostramos lo valores


X = 0
Do
Y = 0
Do
Console.WriteLine("Fila {0} Columna {1} Valor {2} ", X, Y, M(X, Y))
‘ Console.Write(" " & M(X, Y))
Y = Y + 1
Loop Until Y > UBound(M, 2) ‘ columnas
X = X + 1
Console.WriteLine()
Loop Until X > UBound(M, 1) ‘ filas
End Sub
End Module
En principio ésta es una forma de recorrer la matriz sin colocar en las condiciones del bucle el número de filas o de columnas de la matriz,
que suele ser el formato normal, igual que se ha hecho para recorrer el vector podemos hacer con una matriz
Loop Until Y > UBound(M, 1) ‘ filas
para las filas, la primera dimensión, 1.

Loop Until Y > UBound(M, 2) ‘ columnas


para las columnas, la segunda dimensión, 2.

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

Public Sub New(ByVal W() As Integer)


ReDim V(W.Length) ' se obliga a recibir un vector en el new.
V = W
End Sub

Public Sub GeneraVector()


Randomize()
Dim X As Integer
While (X) < UBound(V)
V(X) = CInt(Int((ValorMaximo * Rnd()) + 1))
X = X + 1
End While
End Sub

Public Sub VerVector()


Dim X As Integer
While X < UBound(V)
Console.WriteLine("Elemento número {0} valor {1} ", X, V(X))
X = X + 1
End While
End Sub
End Class
En la clase se ha recibido el vector en la inicialización del objeto, por lo que no es necesario recibirlo como argumento a la hora de
visualizarlo.
Pero se podía haber hecho lo siguiente.
Public Class ClaseVectores
Public V() As Integer ‘ declaramos public el vector
Pero lo lógico entonces sería anular ésta sobrecarga.
Public Sub New(ByVal W() As Integer)
ReDim V(W.Length) ' se obliga a recibir un vector en el new.
V = W
End Sub
Y entonces el método VerVector sería como sigue.
Public Sub VerVector(ByVal V() As Integer)
Dim X As Integer
While X < UBound(V)
Console.WriteLine("Elemento número {0} valor {1} ", X, V(X))
X = X + 1
End While
End Sub
Obligamos a que nos envíen el vector en el método.
Y todo esto se utiliza como sigue, para el primer formato:
Private Sub Ejemplo()
Dim V(10) As Integer
Dim Objeto As New ClaseVector(V)
Objeto.GeneraVector()
Objeto.VerVector()
Console.ReadKey()
End Sub
O bien si elegimos la opción de no inicializar el objeto enviando el vector
Private Sub Ejemplo()
Dim V(10) As Integer
Dim Objeto As New ClaseVector()
Objeto.GeneraVector(V)
Objeto.VerVector(V)
159
Console.ReadKey()
End Sub
Esta es otra de las posibilidades para recorrer un vector, utilizándolo como si fuera una colección.
Es un bucle del tipo For, pero en el que se incorpora la sintaxis del tipo “para cada elemento del objeto recorre todos sus elementos”. Aquí
en éste caso el elemento es del tipo entero y el objeto es un vector.
Dim X As Integer
For Each X In V
Console.Write(X)
Next
Pág. 34.3

Unidad 34. Arrays en VB (IV)


34.5. Operaciones.
La existencia de las estructuras de datos, arrays o listas, tiene como fin el resolver problemas a la hora de desarrollar programas, por lo
tanto su misión es la de almacenar datos u objetos, y la de localizarlos o acceder a ellos posteriormente.
Por lo tanto un array tiene distintos tipos de operaciones.
La principal acceder a los datos. Hay que recalcar que un vector o matriz permiten el acceso a sus datos de manera inmediata, sin
necesidad de realizar búsquedas, lo cual es muy práctico en muchas ocasiones.
Pero no siempre es posible estructurar los datos de forma que se pueda acceder cómodamente y en algunas ocasiones hay que realizar
búsquedas.
En otros momentos los datos en un array, no pueden guardarse de forma adecuada, y es necesario realizar operaciones de clasificación
para obtenerlos en la forma adecuada o que nos interesa para el programa.
1 Acceso.
El acceso, si los datos están adecuadamente utilizados, es directo sin necesidad de realizar una búsqueda.

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.

El programa podría quedar como sigue:


Private Sub Copia()
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.Length)

' Visualizamos el vector


For Each Valor In Meses
160
Console.WriteLine(Valor)
Next

' Copiamos el vector


Meses.Copy(Meses, OtrosMeses, OtrosMeses.GetUpperBound(0))

Console.WriteLine("Elementos vector {0} ", OtrosMeses.Length)

Console.WriteLine("Visualizamos el contenido ")

' Visualizamos el vector


For Each Valor In OtrosMeses
Console.WriteLine(Valor)
Next
Console.ReadLine()
End Sub

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.

Y en el principal del programa queda


Sub Main() ' No hay ni generación ni envío del vector.
Dim Objeto As New ClaseVector(10)
Objeto.GeneraVector()
Objeto.VerVector()
Objeto.OrdenaVectorAscendente()
Objeto.VerVector()
Console.ReadKey()
End Sub
Pero si hemos usado la otra opción ...
Sub Main() ' Si que hay generación y envío del vector.

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.

La diferencia entre un sistema y el otro es


public Sub OrdenaVectorAscendente() ' no se recibe el vector.
Primer ejemplo.
Se crea el objeto y se indica cuantos elementos ha de tener.
El vector está en el objeto.
Se visualiza, lo que hay en el objeto.
Se ordena, lo que hay en el objeto.
' se recibe y se devuelve el vector una vez ordenado.
public Sub OrdenaVectorAscendente(ByRef V() as Integer)
Segundo ejemplo.
Se crea el vector.
Se crea el objeto, pero no se le pasa nada.
El vector solo está en el programa principal.
Al usar el método VerVector hay que enviarle el vector que ha de visualizarse.
Al usarse el método OrdenaVectorAscendente, como no hay vector en el objeto hay que enviarlo.
Y además lo recibimos ordenado para otros usos posteriores, como es el visualizarlo ordenado.

En pocas palabras el vector va y viene de un lado para otro.


Pero se puede enfocar de muchas otras formas.
4 Búsqueda.
La búsqueda no es más que la utilización de una estructura repetitiva para recorrer el array y localizar el contenido que buscamos.
Existen distintos tipos de búsquedas, unas más eficientes que otras, aplicar una u otra solo dependerá del volumen de datos a utilizar, y
de las necesidades en tiempos de respuesta.
Casi siempre es necesario tener el vector ordenado, por cuestiones de eficiencia.
La búsqueda solo es necesaria cuando no es posible establecer una relación entre el dato y su posición como es el caso de los meses del
año, los días de la semana, etc..
Hay una búsqueda muy lógica y sencilla, que es leer el vector hasta que se encuentra o hasta el final.
Public Function BuscarDato(ByVal Que) As Integer
Dim X As Integer = 0
Dim Pos As Integer = -1 ' si no se encuentra devuelve -1
While X < V.Length And Pos < 0
If V(X) = Que Then Pos = X ' localizado y se asigna la posición
X = X + 1 ' incremento
End While
BuscarDato = Pos ' si no se ha encontrado devolverá -1
End Function
Este es el método que se puede añadir a la clase anterior para realizar la búsqueda, si lo encuentra devuelve la posición y en caso
contrario devuelve un valor negativo.

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.

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()
Posic = Objeto.BuscarDato(25)
Select Case Posic
Case Is > 0
Console.WriteLine("Encontrado en la pósición {0} ", Posic)
Case Else
Console.WriteLine("No existe ")
End Select
Console.ReadKey()
End Sub

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

' recuperación del contenido de la pila sobre el vector.


x = 0
163
While Pila.Count <> 0
' extracción de un elemento de la pila
V(X) = Pila.Pop()
x = x + 1
End While
End Sub
Y utilizarla como lo que internamente implementa la colección, que es una pila.
El principal quedaría igual que antes.
Pág. 34.5
Unidad 34. Arrays en VB (VI)
34.6. Métodos.
Hemos visto una serie de acciones que son las clásicas en un array.
Pero disponemos de una serie de métodos en VB que realizan algunas de esas tareas, vamos a nombrarlos para que se sepa de su
existencia.
Clear Limpia el contenido del array
Clone Duplica el contenido
Copy Copia un vector, o parte de él.
GetLength Indica el número de elementos.
GetLowerUbound Indica la primera posición
GetUpperUbound Indica la última posición.
GetType
GetValue Devuelve un elemento
IndexOf, LastIndexOf Indica la posición de un valor
Reverse Invierte
Sort Clasifica

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

Console.WriteLine("Visualizamos el contenido antes ")

' Visualizamos el vector


For Each Valor In Meses
Console.WriteLine(Valor)
Next
Console.WriteLine("Elementos del vector {0} ", Meses.Length)

' Vaciado del vector


Meses.Clear(Meses, 0, Meses.Length)

Console.WriteLine("Visualizamos el contenido después ")


Console.WriteLine("Elementos del vector {0} ", Meses.length)

' Visualizamos el vector


For Each Valor In Meses
Console.WriteLine(" [{0}]", Valor)
Next
Console.ReadLine()
End Sub
End Module

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

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
' Clonamos el vector
OtrosMeses = Meses.Clone()
Console.WriteLine("Elementos vector {0} ", OtrosMeses.GetUpperBound(0))
Console.WriteLine("Visualizamos el contenido ")
' Visualizamos el vector
For Each Valor In OtrosMeses
Console.WriteLine(Valor)
Next
Console.ReadLine()
End Sub
End Module

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

' Contenido vector origen


For Each Dato In Meses
Console.WriteLine(Dato)
Next

' Copia contenido de un vector en otro


Array.ConstrainedCopy(Meses, DimOrigen, Mesesitos, DimDestino, Cuantos)

' Contenido vector destino


Console.WriteLine("Visualizar el vector de destino")
For Each Dato In Mesesitos
Console.WriteLine("Mes de {0} ", Dato)
Next
Console.ReadLine()
End Sub
End Module
4 Copy
A diferencia de Clone, Copy hace un duplicado del vector, solo del número de elementos que se indica en el argumento.

' Copia solo el número de elementos indicado,


‘ OtrosMeses.GetUpperBound(0) vale 5, que es el número de elementos que
tiene
‘ Meses es el origen,
‘ OtrosMeses es el destino

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

' Copia solo el número de elementos indicado,


‘ OtrosMeses.GetUpperBound(0) vale 5, que es el número de elementos
‘ que tiene
‘ Meses es el origen, OtrosMeses es el destino
Meses.Copy(Meses, OtrosMeses, OtrosMeses.GetUpperBound(0))

Console.WriteLine("Elementos vector {0} ", OtrosMeses.GetUpperBound(0))

Console.WriteLine("Visualizamos el contenido ")


' Visualizamos el vector
For Each Valor In OtrosMeses
Console.WriteLine(Valor)
Next
Console.ReadLine()
End Sub
End Module
Pág. 34.6
Unidad 34. Arrays en VB (VII)
5 CopyTo
Realiza la copia del Vector de origen sobre el de destino, colocando los datos a partir de la posición que se indica, se ha de controlar que
hay espacio en el vector de destino.
' Se copia el vector Meses completo y se coloca
' a partir de la sexta posición en el vector de
' destino OtrosMeses
Meses.CopyTo(OtrosMeses, 6)
Module Ejemplo
Sub Main()
Dim Meses() As String = {"Enero", "Febrero", "Marzo", "Abril", _
"Mayo", "Junio", "Julio", "Agosto", _
"Septiembre","Octubre", "Noviembre",
"Diciembre"}

' Le damos 20 elementos


Dim OtrosMeses(20) 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
' Se copia el vector Meses completo y se coloca
' a partir de la sexta posición en el vector de
' destino OtrosMeses
166
Meses.CopyTo(OtrosMeses, 6)

Console.WriteLine("Elementos del vector {0} ",


OtrosMeses.GetUpperBound(0))
Console.WriteLine("Visualizamos el contenido ")
' Visualizamos el vector
For Each Valor In OtrosMeses
Console.WriteLine("[ {0} ]", Valor)
Next
Console.ReadLine()
End Sub
End Module

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

7 GetLength, GetLowerBound, GetUpperBound


Estos métodos devuelven el número de elementos del vector, el primer índice y el último.
Module Ejemplo
Sub Main()
Dim Meses() As String = {"Enero", "Febrero", "Marzo", "Abril", _
"Mayo", "Junio", "Julio", "Agosto", _
"Septiembre","Octubre", "Noviembre",
"Diciembre"}
Console.WriteLine("Visualizamos el contenido ")
Console.WriteLine("Elementos del vector {0} ", Meses.GetLength(0))

' Visualizamos el vector


For Each Valor In Meses
Console.WriteLine(Valor)
Next
Console.WriteLine("Elementos del vector {0} ", Meses.GetLength(0))‘ 12
Console.WriteLine("Primer índice {0} ", Meses.GetLowerBound(0)) ‘ 0
Console.WriteLine("Ultimo índice {0} ", Meses.GetUpperBound(0)) ‘ 11
Console.ReadLine()
End Sub

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

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 ")


Console.WriteLine(Meses.GetType)
For Each Valor In Meses
Console.WriteLine(Valor)
Next
Console.ReadLine()
End Sub
End Module

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

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 ")


Console.WriteLine(Meses.GetValue(3))

For Each Valor In Meses


Console.WriteLine(Valor)
Next
Console.ReadLine()
End Sub
End Module
Pág. 34.7

Unidad 34. Arrays en VB (VIII)


10 Búsqueda, IndexOf, LastIndexOf
Devuelve la posición de la primera, IndexOf, o de la última, LastIndexOf, vez que aparece el elemento indicado en el argumento.
En el ejemplo el resultado es 1 y 7.
Module Ejemplo
Sub Main()
Dim X As Int16

Dim Meses() As String = {"Enero", "Febrero", "Marzo", _


"Abril", "Mayo", "Junio", _
"Julio", "Febrero", "Septiembre", _
"Octubre", "Noviembre", "Diciembre"}
Dim Valor As String

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

For Each Valor In Meses


Console.WriteLine(Valor)
Next
Console.ReadLine()
End Sub
End Module

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

Console.WriteLine("Visualizamos el contenido ")


Meses.SetValue("Juan", 10)
For Each Valor In Meses
Console.WriteLine(Valor)
Next
Console.ReadLine()
End Sub
End Module

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)

For Each Valor In Meses


Console.WriteLine(Valor)
Next
Console.ReadLine()
End Sub
End Module
Ejercicios propuestos de la Unidad
Pág. 34.8
Ejercicios unidad 34: Arrays en VB
1. Crear un vector de 10 elementos numéricos enteros, cargarlo con datos y visualizar su contenido.
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.
3. Crear una matriz de 3 x 3 numérica, cargar los datos y visualizarla dando la visión de matriz.
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.
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)
6. Introducir diez números y luego visualizarlos en orden inverso, al de entrada.
7. Introducir veinte números entre uno y cincuenta, y luego indicar cuales de esos cincuenta son los que se han
utilizado.
8. Introducir veinte números entre uno y diez e indicar luego cuales han sido usados y el numero de veces que se ha
usado cada numero.
9. Introducir veinte números entre uno y diez e indicar luego cuales han sido usados, el numero de veces que se ha
usado cada numero, y el que más y el que menos se ha utilizado.
10. Introducir una fecha en tres variables, numéricas, día, mes y año. A esa fecha hay que sumarle 90 días reales, y
visualizar la fecha resultante en el formato dia_en_letra de mes_en_letra de 20XX.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.


Ayuda ejercicios unidad 34: Arrays en VB
Para la solución de los ejercicios se ha creado una clase en la que se admite que se pueda crear el vector fuera de la clase y la reciba
como argumento o en caso contrario se crea un vector por defecto de veinte elementos.
Public Class Vectores
Dim V() As Long
Dim Cuantos As Integer = 20

Private Sub New() ' se genera un vector por defecto


ReDim V(Cuantos)
End Sub

' Sobrecarga para un número determinado de elementos


Public Sub New(ByVal Elementos As Integer)
Select Case Elementos <> 0
Case True
ReDim V(Elementos)
Case Else
MsgBox("El número de elementos no es correcto",
MsgBoxStyle.Critical)
End Select
Cuantos = Elementos

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.

Para un DIM V(10)


Length devuelve once.
Ubound(V) devuelve diez.

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

Private Sub New() ' se genera un vector por defecto


ReDim V(Cuantos)
End Sub

' Sobrecarga para un número determinado de elementos


Public Sub New(ByVal Elementos As Integer)
Select Case Elementos <> 0
Case True
ReDim V(Elementos)
Case Else
MsgBox("El número de elementos no es correcto",
MsgBoxStyle.Critical)
End Select
Cuantos = Elementos
End Sub

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
End Sub

Public Sub Visualiza()


Dim X As Integer
While X <> V.Length
Console.WriteLine("Posición {0} Contenido {1}", X, V(X))
X = X + 1
End While
End Sub

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)

Randomize() ' inicializar el generador de números aleatorios


' generar la matriz
X = 0
Do
Y = 0
Do
M(X, Y) = CInt(Int((6 * Rnd()) + 1))
Y = Y + 1
Loop Until Y > Columnas ' M.GetUpperBound(1) ' UBound(M,
2)
X = X + 1
Loop Until X > Filas ' M.GetUpperBound(0) '
Ubound(M, 1)
End Sub

Private Sub VisualizaMatrizDetalle(ByVal M(,) As Integer)


Dim X As Integer
Dim Y As Integer
172
Dim Filas As Integer = UBound(M, 1)
Dim Columnas As Integer = UBound(M, 2)
Console.WriteLine("Visualizamos el contenido")

' Mostramos lo valores en detalle


X = 0
Do
Y = 0
Do
Console.WriteLine("Fila {0} Columna {1} Valor {2} ", X, Y, M(X, Y))
Y = Y + 1
Loop Until Y > Columnas
X = X + 1
Console.WriteLine()
Loop Until X > Filas
End Sub

Private Sub VisualizaMatriz(ByVal M(,) As Integer)


Dim X As Integer
Dim Y As Integer
Dim Filas As Integer = UBound(M, 1)
Dim Columnas As Integer = UBound(M, 2)

' Mostramos lo valores


X = 0
Do
Y = 0
Do
Console.Write(" " & M(X, Y))
Y = Y + 1
Loop Until Y > Columnas
X = X + 1
Console.WriteLine()
Loop Until X > Filas
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)
VisualizaMatrizDetalle(M)
VisualizaMatriz(M)

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

Public Sub Quinto(ByVal P() As Integer)


ReDim P(V.Length - 1)
Dim X As Integer

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

' Carga de números


While X < 20
Numero = CInt(Console.ReadLine)
Select Case Numero
Case 1 To 50
V(Numero) = True
End Select
X = X + 1
End While

' Visualizar números


X = 0
While X < 51
Select Case V(X)
Case True
Console.WriteLine("El número {0} ha sido utilizado ", X)
End Select
X = X + 1
End While
End Sub
8. Introducir veinte números entre uno y diez e indicar luego cuales han sido usados y el numero de veces que se ha
usado cada numero.
Este ejercicio es igual que el anterior, pero en lugar de visualizar cuales además pide cuantas veces, pero el cambio es mínimo, en lugar
de marcar número usado, contamos las veces que cada número ha sido usado.
Por lo tanto el vector no podrá ser de tipo booleano, si no que tendrá que ser entero, al menos.
V(Numero) = V(Numero) + 1
Y después el que sea mayor que cero, es el que ha sido usado.
Select Case V(X) > 0
Veamos el ejercicio.
Sub Main()
Dim V(11) As Integer
Dim X As Integer
Dim Numero As Integer
' Carga de números
While X < 10
Numero = CInt(Console.ReadLine)
Select Case Numero
Case 1 To 10
V(Numero) = V(Numero) + 1
End Select
X = X + 1
175
End While

' Visualizar números


X = 0
While X < 11
Select Case V(X) > 0
Case True
Console.WriteLine("El número {0} ha sido utilizado {1} veces ",
X, V(X))
End Select
X = X + 1
End While
'
End Sub
9. Introducir veinte números entre uno y diez e indicar luego cuales han sido usados, el numero de veces que se ha
usado cada numero, y el que más y el que menos se ha utilizado.
Private Sub Noveno()
Dim V(11) As Integer
Dim X As Integer
Dim Numero As Integer
Dim Mas As Integer
Dim Menos As Integer

' Carga de números


While X < 10
Numero = CInt(Console.ReadLine)
Select Case Numero
Case 1 To 10
V(Numero) = V(Numero) + 1
End Select
X = X + 1
End While
' Visualizar números
X = 0
Mas = 0
Menos = 1
While X < 11
Select Case V(X) > 0
Case True
If V(Mas) < V(X) Then Mas = X
If V(Menos) > V(X) Then Menos = X
Console.WriteLine("El número {0} ha sido utilizado {1} veces ",
X, V(X))
End Select
X = X + 1
End While
Console.WriteLine()
Console.WriteLine("El número {0} es el más usado {1} veces ", Mas,
V(Mas))
Console.WriteLine("El número {0} es el menos usado {1} veces",Menos,
V(Menos))
End Sub
10. Introducir una fecha en tres variables, numéricas, día, mes y año. A esa fecha hay que sumarle 90 días reales, y
visualizar la fecha resultante en el formato dia_en_letra de mes_en_letra de 20XX.
Sub Main()
Dim Dia As Integer
Dim Mes As Integer
Dim Year As Integer
Dim NvoDia As Integer
Dim Dias As Integer
Dim Y As Integer
' Creación y carga de vectores
176
Dim M() As Integer = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,
31}
Dim DiaLet() As String = {"", "UNO", "DOS", "TRES", "CUATRO", "CINCO",
_
"SEIS", "SIETE", "OCHO", "NUEVE", "DIEZ", _
"ONCE", "DOCE", "TRECE", "CATORCE", "QUINCE", "DIECISEIS",
"DIECISIETE", _
"DIECIOCHO","DIECINUEVE","VEINTE","VEINTIUNO", "VEINTIDOS",
"VEINTITRES", _
"VEINTICUATRO", "VEINTICINCO", "VEINTISEIS", "VEINTISIETE",
"VEINTIOCHO", _
"VEINTINUEVE", "TREINTA", "TREINTA Y UNO"}
Dim MesLet() As String = {"", "ENERO", "FEBRERO", "MARZO", "ABRIL",
"MAYO", _
"JUNIO", "JULIO", "AGOSTO", "SEPTIEMBRE", "OCTUBRE", _
"NOVIEMBRE", "DICIEMBRE"}
Console.WriteLine("Sumarle 90 días reales, y visualizar la fecha " & _
"en el formato dia_en_letra de mes_en_letra de XXXX")
' INTRODUCCION DE FECHA
Dia = CInt(Console.ReadLine())
Mes = CInt(Console.ReadLine())
Year = CInt(Console.ReadLine())

' Fecha a dias


Y = 0
Dias = 0
If Year Mod 4 = 0 Then M(2) = 29 Else M(2) = 28
While Y <> Mes - 1 ' Los dias del mes actual se suman al final
Y = Y + 1
Dias = Dias + M(Y)
End While
Dias = Dias + Dia + 90 ' Dias + 90 + Dias del mes actual.

' Dias a fecha


Y = 0
NvoDia = 0
While NvoDia + M(Y + 1) < Dias
Y = Y + 1 ' Contar los meses desde el principio
NvoDia = NvoDia + M(Y)
If Y = 12 Then ' Por el posible cambio de año
Y = 0
Year = Year + 1
If Year Mod 4 = 0 Then M(2) = 29 Else M(2) = 28
End If
End While

' Fecha final


Dia = Dias - NvoDia
Mes = Y + 1
Console.WriteLine("Nueva fecha {0} de {1} de {2} ", DiaLet(Dia),
MesLet(Mes), Year)
End Sub
Los array se han definido con una posición en vacío al principio para forzar a que “Uno” esté en la posición uno, etc..
Dim DiaLet() As String = {"", "UNO",
De esa forma la posición cero queda salvada.

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.

De ésta forma se puede llevar a cabo la gestión de los errores a capturar.


Se pueden controlar grupos de excepciones, es decir, que se pueden controlar, a través del argumento, excepciones semejantes.

35.5. Inhibición en la captura.


También existe la posibilidad de inhibirse en la captura de errores desviando la misma a un nivel superior o aquella clase que realiza la
llamada o genera el objeto.
35.6. Trazas.
A la hora de depurar un programa, en muchas ocasiones se recurre a la visualización de datos intermedios mediante el uso de alguna
herramienta u objeto de depuración.
35.7. 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 leer 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ó.

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;

public class Main


{
178
public static void main(String[] args)
{
ClasePrueba Objeto = new ClasePrueba();
Objeto.ErrorCadena();
Objeto.ErrorMatem();
}
}
El Main anterior tiene mucho menos volumen de código, por lo que es más claro en su seguimiento y más fácil de entender, los errores
están gestionados igual, o mejor.

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

Unidad 36. Captura de errores en VB (I)


36.1. Objetivos del tema.
Iniciarse en la gestión de los errores a nivel de programación.
36.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 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.

En VB disponemos de dos formatos de captura de errores.


ON Error GoTo Etiqueta
Try Catch
El sistema del On Error, viene heredado de versiones lejanas del Basic de Microsoft, y ahora se denomina sistema no estructurado.
Estructurado o no, es un sistema comodísimo de utilizar, aunque está claro que llamado a su desaparición.
El segundo sistema, el uso de la instrucción Try, es el denominado estructurado.
Tiene como inconveniente la gestión de un sinfín de posibilidades de gestión de errores a las que hay que anticiparse y prever para su
adecuada utilización.
Por otro lado la no escritura de captura de errores es otro sistema de gestión de los mismos, pues eso da como resultado una salida hacia
arriba hasta encontrar un procedimiento en la línea de llamadas que si los gestiona.
36.3. On Error.
Como hemos comentado anteriormente es un antiguo sistema, cómodo y practico.
Tiene distintas variaciones.
Su estructura en un procedimiento o función es
Private Sub Ejemplo
On Error Goto Errores

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.

Cualquiera de estas posibilidades es factible.


Se suele tener un procedimiento alternativo para la situación imprevista.
El código del procedimiento debe tener la estructura indicada en el ejemplo, de esa manera se abandona el procedimiento de forma
normal cuando no hay errores.
Salida:
Exit Sub
El disponer de la etiqueta “Salida:”, facilita como opción el desviar la ejecución por tratamiento de error a la salida del procedimiento.
Resume Salida
El objeto Err dispone de métodos para facilitar una descripción del error y de su código cara al usuario.
Pág. 36.1
Unidad 36. Captura de errores en VB (II)
36.4. Try Catch.
Es el denominado sistema estructurado, es algo engorroso, pues hay que escribir cada bloque de código con su propia estructura de
tratamiento de errores lo que resulta incomodo.
Obliga a prever que tipos de error se pueden producir para darles salida a los mismos.
La estructura de una instrucción try es la siguiente.
Private Sub Ejemplo()
Dim A, b, c As Integer
Try
' el programa
A = b / c
Catch Ex As OverflowException ' tratamiento de error
Console.WriteLine("Error overflow del tipo {0}", Ex.Message)
Catch Ex As ArithmeticException ' tratamiento de error
Console.WriteLine("Error aritmético del tipo {0}", Ex.Message)
Finally ' siempre se ejecutará
Console.WriteLine("Siempre se ejecutará")
End Try
End Sub

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.

Los pasos en la utilización de un archivo son


Abrir, enlazar el archivo, con los datos comentados anteriormente.
Leer o grabar, recogida o envío de datos.
Cierre, al finalizar su utilización, liberar el enlace con el archivo.

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.

37.3. Gestión de los archivos.


Con el considerable volumen al que llegan los soportes es imprescindible una adecuada gestión de los mismos para aprovechar su
capacidad y aligerar al máximo la localización de los datos en los mismos.
Para ello es necesario establecer una serie de características y sistemas que nos faciliten la gestión de administración del sistema de
archivos.
Por otro lado, ya internamente, también existirá un sistema y una estructura para la gestión de cada uno de los registros que componen el
archivo.

Tablas de asignación de archivos en los soportes.


Cuando un soporte es de escasa capacidad no existen problemas en la gestión del mismo, de hecho en los
primeros sistemas de cinta se asignaba una cinta por archivo, los primeros P. C. usaban un disquete de 160 kb. y
no tenían directorios.
Pero a medida que se amplía la capacidad es necesario mejorar la asignación y agilizar los accesos, lo cual
obliga a tener un sistema ágil de gestión, a tener una tabla de la distribución de los espacios que sea fácil y
rápida de manejar.
Las tablas de asignación de archivos varían su estructura de uno a otro S. O., pero básicamente los datos que
contienen son los siguientes.

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.

Propiedades, atributos, protecciones, permisos.

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

Unidad 37. Archivos (II)


37.4. Estructura de un archivo.
La estructura de un archivo va depender del destino que tenga el contenido del mismo.
No va a ser el mismo tipo de estructura el de un archivo de video o sonido que el de un archivo de datos.

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.

Un archivo se compone de registros, filas si deseamos llamarlo así.


Cada registro se divide a su vez en campos, o columnas si deseamos llamarlo así.

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.

También se puede dar dos tipos de registros:


Registros de longitud fija.
Registros de longitud variable.

37.5. Tipos de archivos, por su direccionamiento.


Hay dos tipos de archivos

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.

37.6. Tipos de archivos, por su contenido.


Podemos crear dos grandes tipos.
Los archivos de programa en sus distintos formatos, y el resto de archivos que serán siempre archivos de datos en sus distintas facetas.
Configuración del sistema
Ordenes para el sistema
Datos
Texto
Sonido
Imágenes
Video
182
Cada uno de estos tipos de archivo dispondrá de una estructura definida por el creador del formato.
Un archivo de ordenes puede ser de este tipo en MS-DOS, Windows.
Echo Script respaldo-bd.sh
Rem C:\Windows\Command
Rem Respaldar DB2 y Websphere
Rem Probe: Trae

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 " Fin del respaldo ...... OK "


Echo " DONE "
Echo
Suponiendo que estas direcciones fueran posibles y el comando existiera.

En LINUX de esta forma


Script respaldo-bd.sh
#!/bin/ksh
#Respaldar DB2 y Websphere
#Probe: Trae
#

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.

Podemos ver un ejemplo con delimitadores de campo.


"0001","DENOMINACION","CAMPO","CAMPO","CAMPO“
"0002","DENOMINACION","CAMPO","CAMPO","CAMPO"

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.

El siguiente ejemplo es un registro sin delimitadores de campo:


0001DENOMINACIONCAMPOCAMPOCAMPO
0002DENOMINACIONCAMPOCAMPOCAMPO

Este formato no lleva delimitadores de campo ni separadores de campo.


Al final de cada registro podrá o no llevar marga de final de registro, dependerá del diseño que se aplique por quienes lo utilizan, puede
usarse de ambas formas.
Su definición podría ser así:

Tipo de archivo Random


Nombre Archivo.Ext

Nombre Tipo Longitud Empaquetado


Código Alfanumérico 2 N
Denominación Alfanumérico 20 N
Precio Numérico 6 S
Cantidad Numérico 6 S
Descuento Alfanumérico 5 N

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

Unidad 37. Archivos (IV)


37.9. Actuaciones con archivos.
Desde el momento en que un archivo se utiliza para almacenar datos se hace imprescindible el implementar un sistema de mantenimiento
de dicha información.
Esos procesos se basan en procesos de actualización y de impresión.
1 Procesos de actualización.
Implica el diseño de programas que permitan la
Inserción Adición de registros no existentes.
Actualización Modificación del contenido de datos existentes.
Borrado Eliminación de datos.

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

Unidad 38. Archivos en VB (I)


38.1. Objetivos del tema.
Ver el acceso a un archivo en VB 2005.
38.2. Introducción.
En todos los lenguajes de programación el orden de ejecución del acceso a un archivo es el mismo.
Los requisitos serán conocer:
El nombre del archivo
Su ubicación en nuestro sistema
La estructura del mismo.

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.

En cualquier caso necesitaremos siempre un


Nombre del archivo
Ubicación del archivo.

La sintaxis de abrir un archivo para salida, grabación o escritura, es la siguiente.


Module Ejemplo
Sub main()
Dim Canal As Int16 = FreeFile()
Dim Nombre As String = "Pruebas.Txt"
FileOpen(Canal, Nombre, OpenMode.Output)
' Cierre del Archivo
FileClose(Canal)
End Sub
End Module
La explicación.
Dim Canal As Int16 = FreeFile()
Creamos la referencia del Archivo, asignándole un valor numérico que es la referencia en el programa para identificar el archivo una vez
abierto.
Dim Nombre As String = "Pruebas.Txt"
Creamos una variable de tipo string que tendrá el nombre, y que también podrá tener la dirección del archivo.
FileOpen(Canal, Nombre, OpenMode.Output)
De ésta forma se crea un archivo vacío en la ruta por defecto del proyecto en curso, el archivo se abre para realizar una grabación, salida.

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,

El siguiente paso es poder grabar datos en el mismo.

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"}

Console.WriteLine("Probamos grabar un archivo secuencial ")


FileOpen(Canal, Nombre, OpenMode.Output)
For Each Valor In Meses
WriteLine(Canal, Valor) ‘ con marca fin de registro
‘ sin marca Write a solas

Console.WriteLine("Grabado {0} ", Valor)


Next
' Cierre del Archivo
FileClose(Canal)
End Sub
End Module
Otra cosa es que en función de nuestros conocimientos, esto nos parezca o no bien, o adecuado, pero ésta es la sintaxis para grabar
datos, registros.
Por lo tanto para grabar una estructura de datos que en el mundillo de la gestión es lo necesario hay que implementar alguna herramienta,
que luego veremos, desarrollaremos una clase.
Pág. 38.1
Unidad 38. Archivos en VB (II)
38.5. Leer.
La lectura no es más complicada, claro, partiendo del supuesto de lo que se puede grabar, no puede ser mucho más compleja.
Module Ejemplo
Sub main()
Dim Canal As Int16 = FreeFile()
Dim Nombre As String = "Prueba.Txt"
Console.WriteLine()
Console.WriteLine("Probamos a leer un archivo secuencial ")
FileOpen(Canal, Nombre, OpenMode.Input)
Do While Not EOF(Canal)
Input(Canal, Valor)
Console.WriteLine("Leído {0} ", Valor)
Loop
' Cierre del Archivo
FileClose(Canal)
End Sub
End Module

Dim Canal As Int16 = FreeFile()


Dim Nombre As String = "Prueba.Txt"
Utilizamos las mismas instrucciones que antes, pero para la lectura abrimos el archivo en modo lectura, entrada.
FileOpen(Canal, Nombre, OpenMode.Input)
Solo nos queda establecer una estructura repetitiva

Console.WriteLine("Probamos a leer un archivo secuencial ")


Do While Not EOF(Canal)
Input(Canal, Valor)
Console.WriteLine("Leído {0} ", Valor)
Loop
Se ejecuta el While mientras haya datos en el archivo.
Para que todo funcione correctamente, a las clases importadas anteriormente hay que sumar ahora

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.

Ejercicios propuestos de la Unidad


Pág. 38.2
Ejercicios unidad 38: Archivos en VB
1.- Crear un archivo de texto con una frase cualquiera.
2.- Acceder al archivo anterior y visualizar la frase que se ha grabado.
3.- Crear un archivo y copiar el contenido del archivo anterior.
4.- Acceder al nuevo archivo y visualizar su contenido.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.


Ayuda ejercicios unidad 38: Archivos en VB
1.- Crear un archivo de texto con una frase cualquiera.
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.Output)
End Sub

Private Sub GrabarFrase(ByVal Canal As Integer, ByVal Frase As String)


WriteLine(Canal, Frase)
End Sub

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

Private Function LeerFrase(ByVal Canal As Integer) As String


Dim Frase As String
Input(Canal, Frase)
Return Frase
End Function

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

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

Private Sub GrabarFrase(ByVal Canal As Integer, ByVal Frase As String)


WriteLine(Canal, Frase)
End Sub

Private Function LeerFrase(ByVal Canal As Integer) As String


Dim Frase As String
Input(Canal, Frase)
Return Frase
End Function

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

Private Function LeerFrase(ByVal Canal As Integer) As String


Dim Frase As String
Input(Canal, Frase)
Return Frase
End Function

Sub Main()
Dim Canal As Integer
AbreArchivo("Nuevo.txt", Canal)

Console.WriteLine(LeerFrase(Canal))
FileClose(Canal)
Console.ReadLine()
End Sub
End Module

Unidad 39. Archivos secuenciales, formatos (I)


39.1. Objetivos del tema.
Sabemos cuales son los pasos para acceder a un archivo y las acciones a realizar, grabación y lectura.
En este tema vamos a ver como utilizar un archivo secuencial en varios formatos.
39.2. Introducción.
Los archivos secuenciales disponen de una serie de características que no los habilitan para el uso diario en una aplicación, pero sin
embargo por sus características permiten que sean usados en temas muy concretos,
Trasvase de datos entre empresas.
Almacenamientos de datos para tablas de una aplicación.
Guardar datos de configuración.
Normalmente estos datos son cargados al principio de un programa.
39.3. Formatos.
1 ASCII delimitado.
El ASCII delimitado es un formato que permite indistintamente el formato de longitud fija y variable, pues cada dato viene separado del
otro con comas.
Es el más estándar, eso significa que los datos se almacenan:
Los datos alfanuméricos delimitados entre comillas dobles.
Los campos numéricos sin delimitadores.
Los campos se separan entre si por comas.
Los registros incorporan una marca de fin de registro, los caracteres ascii trece y diez.
Los problemas que pueden surgir a la hora de su utilización vendrán dados por los distintos tipos de datos numéricos que cada aplicación,
o sea el lenguaje en el que se ha desarrollado esa aplicación, sea capaz de tratar.
Como el problema más normal es ese, una forma de saltarlo es grabar todos los datos como datos de tipo string, que es un tipo de dato
que cualquier lenguaje es capaz de tratar sin ningún problema.
Existe otro posible problema y es que el lenguaje en cuestión no sea capaz de tratar el formato, la alternativa es la de utilizar la instrucción
de lectura, que todos los lenguajes disponen, que permita leer un registro completo, es decir de marca de fin de registro hasta la siguiente.
Posteriormente se puede desarrollar una función que aísle los campos buscando las comas ubicadas entre comillas dobles, y de esa
forma se consigue separar los datos.
2 Registros de longitud fija.
Podemos evidentemente grabar registros de datos sin separadores de campos y utilizando una estructura de datos fija y conocida, sino no
es posible tratarlos.
Se leen y graban con instrucciones que trabajan con registros completos, de marca a marca de fin de registro, o leyendo una sola variable
de tipo string.
39.4. Estructuras.
Los archivos secuenciales permiten que podamos trabajar con registros de longitud fija o de longitud variable, que es otra de sus ventajas.
Otra posibilidad es la de poder utilizar estructuras de registros de distintos tipos en el interior del archivo.
39.5. Escritura.
La escritura de cada uno de los formatos que podemos utilizar dependerá en gran medida de las posibilidades del lenguaje que estemos
utilizando, ya que no todos los lenguajes incorporan instrucciones adecuadas a los posibles formatos.
La escritura en un formato de longitud fija se podrá realizar con una instrucción que permita grabar una variable de tipo string.
La escritura de un formato en ascii delimitado es posible realizarla igualmente si no hay una instrucción que genere ese formato
directamente con la misma instrucción que antes, pero previamente habrá que realizar el montaje de los datos componiendo una cadena de datos
con ese formato.
39.6. Lectura.
189
La lectura de uno u otro tipo de estructura de datos dependerá de la estructura utilizada.
Se vuelve a presentar la misma situación que en la grabación, puede ser que no dispongamos de instrucciones para la lectura del formato
recibido, por lo tanto posiblemente habrá que recurrir a la lectura de registros completos, como cadenas de caracteres, para su posterior
desmontaje o desglose en los campos y tipos adecuados.

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

Unidad 39. Archivos secuenciales, formatos (II)


39.8. Utilización.
Un archivo secuencial, es un archivo que tiene muchas utilizaciones.
Cualquier archivo de imagen, sonido, o similares, son archivos que poseen una estructura, una cabecera, y una serie de datos que se leen
posteriormente o bien en bloque o de forma secuencial.
Basta solo ver las definiciones de las estructuras de los archivos mencionados, para poder entender lo dicho anteriormente.
Estos archivos son muy compactos.
Un archivo secuencial, al igual que los random y las bases de datos, necesita de ser actualizado.
Los que contienen sonido, video e imágenes no necesitan de estos procesos, pero los que almacenan datos sí.

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.

En la imagen podemos ver una representación gráfica de dicho proceso.

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.

Esta estructura será siempre del tipo Mientras

190
Mientras no Fin de archivo
Leer registro
Proceso
Fin Mientras
Es importante tener presente que este es el mejor sistema para su proceso.

Un bucle del tipo Repite, no es adecuado.


39.9. Actualización.
El segundo proceso clásico es el de la actualización, o el de emparejamiento, son iguales en esencia.
Su proceso se basa en el uso de lo que se conoce como high value.
Se trata de crear un bucle del tipo mientras, en el que la condición es que se proceda a leer registros mientras no se alcance el máximo
valor en los archivos de proceso.
La filosofía es la de emparejar registros como ya se explicó en el tema anterior.
Importante que el valor utilizado como High value, no sea alcanzable por los datos del archivo.
El proceso se basa en que solo puede haber proceso de actualización si los códigos coinciden, en ese caso puede darse el caso de
borrado o actualización, pero nunca un alta, eso sería un error.
Si el código del archivo principal se adelanta al de los cambios, significa que los registros hasta igualarse deben ser del tipo alta, en caso
contrario sería un error en la grabación del archivo de cambios.
Si el código del archivo principal se queda por detrás significa que ese código no dispone de incidencias, por lo que debe ser copiado tal
como está en el archivo que se crea nuevo en el proceso, para no perder los datos que no van a sufrir cambios.
Siempre debemos disponer de una pareja de registros, por lo que al tratar un registro del archivo principal, inmediatamente hay que leer
otro.
Igual con el de los cambios.

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

Wientras Codigo <> Hv Or CodDatos <> Hv


Según Codigo
Si Codigo = CodDatos
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
Si Codigo > CodDatos
Proceso
If No final(Datos) Entonces
Leer(CanalDatos, CodDatos, .....)
Sino
CodDatos = Hv
Fin
Si Codigo < CodDatos
Proceso
If No final(Incidencias) Entonces
Leer(Canal, Codigo, ......)
Sino
Codigo = Hv

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

Unidad 40. Archivos secuenciales en VB (I)


40.1. Objetivos del tema.
Visto el acceso a un archivo, vamos a ver el acceso a un archivo secuencial utilizando un formato en ASCII delimitado como formato de
grabación, que es el más estándar de todos.
40.2. Introducción.
Son archivos que se generan con una estructura que puede o no ser fija y que su lectura no puede ser direccionada.
Otro aspecto, es que por la estructura de datos generada en el archivo, la misma permita que se direccionen los registros, y que dicho
archivo pueda ser abierto bajo otro formato distinto, de acceso aleatorio, pero eso es una particularidad, o una excepción, y también podríamos
enfocarlo al revés, es decir es un archivo random, que se usa como archivo secuencial, para gustos los colores.
Otro aspecto sobre los archivos secuenciales, es que la estructura de datos que albergan no tiene porque ser una estructura fija, pueden
ser registros con una estructura distinta de unos a otros, y además la longitud puede ser variable, siempre y cuando se este utilizando el formato
de ASCII delimitado, que incorpora la delimitación de campos y de final de registro.
40.3. Abrir un archivo.
El primer paso para acceder a un archivo es siempre enlazarlo con el programa, abrirlo.

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

40.6. Lectura de un archivo secuencial.


La lectura de un archivo secuencial se basa siempre en el uso de un bucle del tipo mientras.
La estructura de dicho bucle es la que sigue:
While Not EOF(Canal)
' lectura de un registro
Input(Canal, Codigo)
Input(Canal, Denom)
Input(Canal, Cant)
Input(Canal, Preci)
' Realizar el proceso correspondiente.
End While
40.7. Proceso de actualización.
El proceso de actualización se basa en el emparejamiento de registros, para ello los archivos han de estar grabados en secuencia, en
caso contrario no es posible realizar un proceso adecuadamente correcto.
El sistema seguido es el de high value, viejo sistema utilizado en otros lenguajes de programación, pero no por ello menos efectivo.
La filosofía es la de emparejar registros como ya se explicó en el tema anterior.
Importante que el valor utilizado como High value, no sea alcanzable por los datos del archivo.
El proceso se basa en que solo puede haber proceso de actualización si los códigos coinciden, en ese caso puede darse el caso de
borrado o actualización, pero nunca un alta, eso sería un error.
Si el código del archivo principal se adelanta al de los cambios, significa que los registros hasta igualarse deben ser del tipo alta, en caso
contrario sería un error en la grabación del archivo de cambios.
Si el código del archivo principal se queda por detrás significa que ese código no dispone de incidencias, por lo que debe ser copiado tal
como está en el archivo que se crea nuevo en el proceso, para no perder los datos que no van a sufrir cambios.
Siempre debemos disponer de una pareja de registros, por lo que al tratar un registro del archivo principal, inmediatamente hay que leer
otro.
Igual con el de los cambios.

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.

Ejercicios propuestos de la Unidad


Pág. 40.2
Ejercicios unidad 40: Archivos secuenciales en VB
1.- Diseñe un registro de datos con los datos de los teléfonos de sus amigos. Grabe los datos con un archivo
secuencial.
2.- Realizar el listado de esos datos en pantalla.
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.
4.- Realice el proceso de actualización del primer archivo con los datos del segundo.

Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.

Ayuda ejercicios unidad 40: Archivos secuenciales en VB


Para la resolución de los siguientes ejercicios se han seguido métodos de lectura con estructura y sin estructura de datos, o tipos de
usuario, con el fin de ilustrar que el archivo es independiente del programa, y además poder mostrar ambos formatos.

Se han utilizado los siguientes elementos en los ejercicios.


Module Estructuras
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

Public Structure FilCambios


Public Codigo As String
Public Nomb As String
Public Ape1 As String
Public Ape2 As String
Public Domic As String
Public Tipo As String
End Structure
End Module

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"

Select Case CInt(Cual)


Case 1
GrabarDatos()
Case 2
Listar()
Case 3
GrabarCambios()
Case 4
Actualizacion()
Case 5
Try
FileSystem.Kill("Antiguo.Sec")
Catch
Finally
FileSystem.Rename("Amigos.Sec", "Antiguo.Sec")
FileSystem.Rename("Nuevo.Sec", "Amigos.Sec")
End Try
End Select
Loop Until Cual = "6"
End Sub
End Module
1.- Diseñe un registro de datos con los datos de los teléfonos de sus amigos. Grabe los datos con un archivo
secuencial.
Module Grabar
Private Sub Validar(ByRef Codigo As String, _
ByVal UltCod As String)

If Codigo <> "" Then Codigo = Format(CInt(Codigo), "00000")


Select Case Codigo > UltCod
Case False
Codigo = ""
Console.WriteLine("El número de código está fuera de secuencia, el
último utilizado es el {0} ", UltCod)
Console.ReadKey()
End Select
End Sub

Private Sub Grabacion(ByVal Canal As Integer, ByVal Datos As FilDatos,


ByRef UltCod As String)
With Datos
WriteLine(Canal, .Codigo, .Nomb, .Ape1, .Ape2, .Domic)
UltCod = .Codigo
UltCod = Format(Val(UltCod), "00000")
Console.WriteLine("Datos grabados, pulse una tecla para seguir")
Console.ReadKey()
End With
End Sub

Public Sub GrabarDatos()


Dim Codigo As String
Dim UltCod As String
Dim Canal As Integer
Dim Datos As FilDatos

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

Private Sub Visualizar(ByVal Datos As FilDatos)


With Datos
Console.WriteLine(" {0} {1} {2} {3} {4} ", .Codigo, .Nomb, .Ape1,
.Ape2, .Domic)
End With
End Sub

Public Sub Listar()


Dim Datos As FilDatos
Dim Canal As Integer = 1
Dim Lin As Integer

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)

If Codigo <> "" Then Codigo = Format(CInt(Codigo), "00000")


Select Case Codigo > UltCod
Case False
Codigo = ""
Console.WriteLine("El número de código está fuera de secuencia, el
último utilizado es el {0} ", UltCod)
Console.ReadKey()
End Select
End Sub

Private Sub Grabacion(ByVal Canal As Integer, ByVal Datos As FilCambios,


ByRef UltCod As String)
With Datos
WriteLine(Canal, .Codigo, .Nomb, .Ape1, .Ape2, .Domic, .Tipo)
UltCod = .Codigo
UltCod = Format(Val(UltCod), "00000")
Console.WriteLine("Datos grabados, pulse una tecla para seguir")
Console.ReadKey()
End With
End Sub

Public Sub GrabarCambios()


Dim Codigo As String
Dim UltCod As String
Dim Canal As Integer
Dim Datos As FilCambios

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)

' lectura de un registro


Input(Canal, Codigo) ' código
Input(Canal, Nomb)
Input(Canal, Ape1)
Input(Canal, Ape2)
Input(Canal, Domic)
End Sub

Private Sub Grabacion(ByVal Canal As Integer, _


ByRef Codigo As String, _
ByRef Nomb As String, _
ByRef Ape1 As String, _
ByRef Ape2 As String, _
ByRef Domic As String)
WriteLine(Canal, Codigo, Nomb, Ape1, Ape2, Domic)
End Sub

Private Sub LeerCambios(ByVal Canal As Integer, _


ByRef Codigo As String, _
ByRef Nomb As String, _
ByRef Ape1 As String, _
ByRef Ape2 As String, _
ByRef Domic As String, _
ByRef Tipo As String)

' lectura de un registro


Input(Canal, Codigo) ' código
Input(Canal, Nomb)
Input(Canal, Ape1)
Input(Canal, Ape2)
Input(Canal, Domic)
Input(Canal, Tipo)
End Sub

Private Sub Proceso(ByVal Canal As Integer, ByVal CanalC As Integer,


ByVal CanalN As Integer)
Const Hv As String = "99999"
Dim CodCamb As String
Dim NombC As String
199
Dim Ape1C As String
Dim Ape2C As String
Dim DomicC As String

Dim Codigo As String


Dim Nomb As String
Dim Ape1 As String
Dim Ape2 As String
Dim Domic As String
Dim Tipo As String

If Not EOF(Canal) Then LeerAmigos(Canal, Codigo, Nomb, Ape1, Ape2,


Domic) Else Codigo = Hv
If Not EOF(CanalC) Then LeerCambios(CanalC, CodCamb, NombC, Ape1C,
Ape2C, DomicC, Tipo) Else CodCamb = Hv

While Codigo <> Hv Or CodCamb <> Hv


Select Case Codigo
Case Is < CodCamb ' copiar maestro
Grabacion(CanalN, Codigo, Nomb, Ape1, Ape2, Domic)
If Not EOF(Canal) Then LeerAmigos(Canal, Codigo, Nomb, Ape1,
Ape2, Domic) Else Codigo = Hv
Case Is > CodCamb
Select Case Tipo
Case "1" ' alta
Grabacion(CanalN, CodCamb, NombC, Ape1C, Ape2C, DomicC)
End Select
If Not EOF(CanalC) Then LeerCambios(CanalC, CodCamb, NombC,
Ape1C, Ape2C, DomicC, Tipo) Else CodCamb = Hv
Case Is = CodCamb
Select Case Tipo
Case "1" ' alta, error, habría que tratar el error
If Not EOF(CanalC) Then LeerCambios(CanalC, CodCamb, NombC,
Ape1C, Ape2C, DomicC, Tipo) Else CodCamb = Hv
Case "2" ' modificación, se graba el nuevo
Grabacion(CanalN, CodCamb, NombC, Ape1C, Ape2C, DomicC)
If Not EOF(Canal) Then LeerAmigos(Canal, Codigo, Nomb, Ape1,
Ape2, Domic) Else Codigo = Hv
If Not EOF(CanalC) Then LeerCambios(CanalC, CodCamb, NombC,
Ape1C, Ape2C, DomicC, Tipo) Else CodCamb = Hv
Case "3" ' baja, no se graba
If Not EOF(Canal) Then LeerAmigos(Canal, Codigo, Nomb, Ape1,
Ape2, Domic) Else Codigo = Hv
If Not EOF(CanalC) Then LeerCambios(CanalC, CodCamb, NombC,
Ape1C, Ape2C, DomicC, Tipo) Else CodCamb = Hv
End Select
End Select
End While
End Sub

Public Sub Actualizacion()


Dim Canal As Integer
Dim CanalCamb As Integer
Dim CanalNuevo As Integer

' Abrir archivos


Canal = FreeFile()
FileOpen(Canal, "Amigos.sec", OpenMode.Input)
CanalCamb = FreeFile()
FileOpen(CanalCamb, "Cambios.sec", OpenMode.Input)
CanalNuevo = FreeFile()
FileOpen(CanalNuevo, "Nuevo.sec", OpenMode.Output)

200
Proceso(Canal, CanalCamb, CanalNuevo)

' cerrar todos los archivos


FileClose()
End Sub
End Module

Unidad 41. Archivos Random (I)


41.1. Objetivos del tema.
Entrar en el funcionamiento de los archivos random.
41.2. Introducción.
Con los archivos secuenciales no se podía acceder a un registro en concreto sin haber leído todos los
anteriores, eso es un sistema compacto, pero incomodo a la hora de hacer un diseño de una aplicación en la que
siempre vamos a necesitar un acceso rápido y concreto a una información determinada.
Eso se consigue con el uso de archivos random.
De todos modos, en la actualidad todas las aplicaciones se diseñan haciendo uso de la estructura de una base
de datos, ya que estas presentan mejores prestaciones que lo que nos facilita un archivo random.
41.3. Registros.
Mientras que en un archivo secuencial, los datos pueden ser de longitud fija o variable, en un archivo random
han de ser de longitud fija, ya que de otra forma no se podría localizar la información en el mismo.

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.

41.4. Acceso a los registros.


Hablamos de dirección, pero en realidad lo que se hace es establecer a partir del inicio del archivo, cual es el
primer byte que deseamos leer, si estamos trabajando con una estructura de datos que es de longitud fija, el registro
x estará, empezará en:
Posición = Longitud de registro * (X – 1)

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.

En un archivo random, para almacenar datos, utilizamos estructuras de longitud fija.

41.5. Ubicación de los registros.


El acceso a los registros de un archivo random se realiza a partir de una dirección, esa es la dirección que
debe ocupar el registro en el archivo.
Después podemos encontrarnos con dos situaciones para localizar los datos dentro del archivo.
El registro se almacena en la posición que le corresponde por el valor de su campo
código.
El registro se almacena por la posición que le asigna un algoritmo encargado de calcular
direcciones a partir de un código.

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.

El segundo consiste en incluir en el diseño del registro un campo adicional de un


byte para grabar en el un carácter que me indique si está libre u ocupado. También se
puede utilizar un campo significativo para en función de su contenido decidir esta
situación.
De entre los dos sistemas el más adecuado es el primero, el segundo no es que sea malo, si no al contrario
puede llegar a ser hasta mejor, todo depende de las circunstancias en las que nos movamos.

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.

El otro sistema, el de utilizar blancos, tiene la ventaja, o no, de que al borrar


un registro se graban blancos en su lugar, ASCII treinta y dos, y eso impide que se pueda recuperar cualquier
información una vez borrada.
Lo importante es determinar un sistema por el cual podamos saber si el registro está libre u ocupado.
Pág. 41.1
Unidad 41. Archivos Random (II)
41.7. Diseño del registro.
En un archivo secuencial podemos establecer un diseño de registro de longitud fija o variable.
En un archivo random, el diseño del registro ha de ser de longitud fija.
Cada campo tiene un espacio asignado.
El diseño del ejemplo que tenemos en la imagen se corresponde con lo
siguiente.

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.

Por lo tanto en el diseño de un registro se puede obviar el espacio que ocupa


el campo código.

Esos dos tipos de diseño podemos llamarlos lógico y físico.


El diseño físico sería el que hemos visto antes.
El diseño lógico es el que vemos en la imagen de la derecha, en la que podemos
observar que se ha eliminado el campo código.

202
41.9. Utilización.
A partir de lo visto los pasos en la utilización de un archivo random son los siguientes.

Establecer la estructura del registro en nuestro programa.


Acceder al archivo
Leer o grabar
Cerrar el archivo.

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.

Comprobar la dirección del registro que vamos a leer.


Realizar la lectura.
Comprobar si el registro está libre u ocupado
Actuar en función de la comprobación anterior.

A la hora de realizar la grabación los pasos serían

Asignar los datos a las variables que representan el registro.


Grabar los datos.
Se supone que previamente hemos hecho una lectura que nos ha dado como resultado que la dirección a utilizar es la adecuada.
Pág. 41.2

Unidad 41. Archivos Random (III)


41.10. Altas, inserción.
El proceso de insertar o realizar altas en el archivo equivale a realizar una lectura como se ha indicado antes, en la que el resultado de la
comprobación del estado del registro es que éste está libre, y procedemos a realizar una grabación de datos posteriormente.

41.11. Modificación, actualización.


Se repite el proceso anterior, pero en lugar de que la condición sea que el registro está libre en este caso ha de estar ocupado, y
posteriormente realizamos la grabación de los datos actualizados.

41.12. Borrado, eliminación.


Se vuelve a repetir las condiciones para una modificación, es decir ha de existir el registro, para a continuación visualizarlo y confirmar
que se desea borrar.
El borrado implicará la grabación de un registro con blancos en la dirección indicada, o la de una marca en el campo correspondiente al
estado del registro.
41.13. Proceso del archivo.
El uso del archivo en un bucle, solo implica la de realizar un bucle desde la primera hasta la última posición y tratar aquellos registros que
se van leyendo que cumplan la situación de alta u ocupado, en función del sistema seguido.
41.14. Resumen de acciones.
Como se ha podido comprobar los procesos anteriores se resumen en
Leer
Comprobar
Proceder
Leer un registro del archivo, que implica comprobar la dirección a leer y realizar la lectura del registro en el archivo.
Comprobar su estado.
Proceder a realizar la acción correspondiente en función del estado del mismo.
Ocupado
Modificación
Baja
Libre
Inserción de registro nuevo, alta.
41.15. Comentarios.
Los lenguajes de programación admiten que los campos se puedan definir de cualquiera de los tipos en ellos existentes. Sin embargo la
ventaja de utilizar un array of char, string o el tipo equivalente correspondiente en cada uno de ellos, es la compatibilidad que eso supone entre
cualquier lenguaje de programación.
Un string, o char, según toque, siempre tiene un altísimo porcentaje de posibilidades de que se pueda tratar en cualquier lenguaje de
programación.
Evidentemente en cualquier gestión, actualmente lo que se utiliza es una base de datos, pero los archivos random, siguen siendo válidos
para muchas tareas, y su conocimiento es necesario.
Pág. 41.3

Unidad 42. Archivos Random en VB (I)


42.1. Objetivos del tema.
Una vez que se ha visto la parte conceptual de los archivos random, vamos a ver su uso desde VB.

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.3. Abrir el archivo.


La instrucción para la apertura del archivo es FileOpen, y su sintaxis:
FileOpen(Canal,Nombre,OpenMode.Random, , ,Len(Registro))
Donde
Canal Será 1, 2, 3 , pero utilizaremos FreeFile para obtener un canal libre.
Nombre "Fichero.ext" por ejemplo, incluida la ruta.
Forma de apertura OpenMode.Random, formato de apertura del archivo.
Longitud Len(Registro) , 56, longitud de registro.

Y no es necesario cerrar y abrir, para leer o grabar un registro.

42.4. Definir la estructura de un registro.


Antes de proceder a la lectura o grabación de un registro, hay que definir la estructura del registro que vamos a utilizar.
Structure FilRandom ‘ Tipo de usuario
<VBFixedString(15)> Public Nom As String
<VBFixedString(15)> Public Dire As String
<VBFixedString(15)> Public Pobl As String
<VBFixedString(2)> Public Prov As String
<VBFixedString(9)> Public Tele As String
End Structure
Para después utilizar una variable definida de ese tipo, en lectura o grabación.
Dim Registro as FilRandom ‘ Variable Registro

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

El código de una acción de lectura podría ser:


Select Case Campo00.Text <> ""
Case True
Posicion = CLng(Campo00.Text)
Select Case Posicion
Case 1 To 20
FileGet(CanalAgenda, Reg, Posicion) ' Lectura
Select Case Reg.Nom <> StrDup(15, " ")
Case True ' Ocupado
Visualiza() ' Visualiza registro
Case Else ' Código libre
Mensaje = "El código no existe"
End Select ' Campo siguiente
Case Else ' Código fuera de rango
Mensaje = "Código fuera de rango"
End Select
Case Else ' Valor inadecuado
Mensaje = "Valor del campo incorrecto"
End Select
Los pasos seguidos son:
Select Case Campo00.Text <> ""
Comprobar que el contenido sea distinto de nulo, previamente ya se habrá filtrado que el contenido solo pueda ser numérico.
Posicion = CLng(Campo00.Text)
Después asignamos el valor del texto con contenido numérico a una variable de tipo Long en éste caso, para usarla en la lectura.
Select Case Posicion
Case 1 To 20

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

Unidad 42. Archivos Random en VB (II)


42.6. Grabación de un registro.
La sintaxis de la instrucción.
FilePut(Canal, Registro, Posición)
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 grabación.

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 seguidos son:


Posicion = CLng(Codigo)
Obtener el valor de la dirección que se va a utilizar en la grabación.
Reg.Nom = Nombre

Asignación de los datos a la variable registro del archivo.


FilePut (Canal,Registro,Posicion)

Realizar la grabación de los datos en el archivo.

42.7. Inserción, Alta.


El proceso de realizar un alta pasa por los siguientes pasos.
Podemos tomar como punto de partida la lectura realizada anteriormente, ya que al fin y al cabo la inserción
de un registro ha de basarse en una comprobación previa de que el código no exista.
Esta lectura se haría cuando se introduce el campo código.
Una vez hecha la lectura de comprobación el resto es dejar que se vayan introduciendo los datos de cada
campo del archivo y al acabar previa confirmación proceder a grabar los datos.
Veamos el control del campo código.
Select Case Campo00.Text <> ""
Case True
Posicion = CLng(Campo00.Text)
205
Select Case Posicion
Case 1 To 20
FileGet(CanalAgenda, Reg, Posicion) ' Lectura
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
Case Else ' Código fuera de rango
Mensaje = "Código fuera de rango"
End Select
Case Else ' Valor inadecuado
Mensaje = "Valor del campo incorrecto"
End Select

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

Cuando comprobamos que el registro está libre u ocupado,


Si esta ocupado podemos elegir entre seguir después de visualizar su contenido, en
cuyo caso el alta se convierte en realidad en una actualización, o en pedir un código
nuevo.
Si está libre simplemente seguimos con la ejecución y ya está.

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

Unidad 42. Archivos Random en VB (III)


42.8. Modificación, actualización.
El proceso de realizar una modificación puede tomar de nuevo como punto de partida el de la lectura de un registro para realizar un alta,
la única variación que en éste caso el código debe existir, el resto sería idéntico.
Veamos el ejemplo
Select Case Campo00.Text <> ""
Case True
Posicion = CLng(Campo00.Text)
Select Case Posicion
Case 1 To 20
FileGet(CanalAgenda, Reg, Posicion) ' Lectura
Select Case Reg.Nom <> StrDup(15, " ")
Case True ' Ocupado
Visualiza() ' Visualiza datos, y seguimos
Case Else ' Código libre, dejamos que siga
Mensaje = "Código inexistente."
End Select ' Campo siguiente
Case Else ' Código fuera de rango
Mensaje = "Código fuera de rango"
End Select
Case Else ' Valor inadecuado
Mensaje = "Valor del campo incorrecto"
End Select
El cambio está en
Select Case Reg.Nom <> StrDup(15, " ")
Case True ' Ocupado
Visualiza() ' Visualiza datos, y seguimos
Case Else ' Código libre, dejamos que siga
Mensaje = "Código inexistente."
End Select ' Campo siguiente

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.

42.9. Baja eliminación.


Se vuelve a repetir las mismas condiciones que para realizar una modificación, pero en este caso solo hay que borrar el registro cuando
éste se ha visualizado.
Select Case Campo00.Text <> ""
Case True
Posicion = CLng(Campo00.Text)
Select Case Posicion
Case 1 To 20
FileGet(CanalAgenda, Reg, Posicion) ' Lectura
Select Case Reg.Nom <> StrDup(15, " ")
Case True ' Ocupado
Visualiza() ' Visualiza datos
Borrado() ' Pregunta y borra el registro
Case Else ' Código libre, dejamos que siga
Mensaje = "Código inexistente."
End Select ' Campo siguiente
Case Else ' Código fuera de rango
Mensaje = "Código fuera de rango"
End Select
Case Else ' Valor inadecuado
Mensaje = "Valor del campo incorrecto"
End Select
El cambio está en
Select Case Reg.Nom <> StrDup(15, " ")
Case True ' Ocupado
Visualiza() ' Visualiza datos
Borrado() ' Pregunta y borra el registro
Case Else ' Código libre, dejamos que siga
Mensaje = "Código inexistente."
End Select ' Campo siguiente
Borrado es un procedimiento que realizará una pregunta de confirmación al usuario y si la respuesta es afirmativa realizara la grabación
de blancos en el registro en cuestión.
El procedimiento de grabación, borrado, puede ser como el ejemplo que sigue.
Private Sub Borrar()
Dim Posicion As Integer
' Borrado de un registro a blancos
Posicion = CLng(Codigo)
Reg.Nom = StrDup(15, " ")
Reg.Dire = StrDup(15, " ")
Reg.Pobl = StrDup(15, " ")
Reg.Prov = StrDup(2, " ")
Reg.Tele = StrDup(9, " ")
FilePut (Canal, Registro, Posicion)
MsgBox("Datos borrados", MsgBoxStyle.OKOnly, Me.Text)
End Sub

207
Pág. 42.3

Unidad 42. Archivos Random en VB (IV)


42.10. Bucle de lectura.
Como podemos comprobar en el organigrama del ejemplo, el bucle no tiene en realidad ninguna complejidad, solo hay que asegurarse en
el mismo de que tras la lectura debemos filtrar que el registro que se ha leído está ocupado, para que pase a proceso.
Private Sub Bucle(Hasta as Integer)
Dim Posición as Integer
Posicion = 1 ' iniciar contador
While Posicion <= Hasta
FileGet(CanalAgenda, Reg, Posicion)
Select Case Reg.Nom <> Space(15)
Case True ' registro ocupado
' Acción de proceso
End Select
Posicion = Posicion + 1 ' Incremento del contador
End While
End Sub

42.11. Integrar todas las acciones.


Si revisamos las acciones de alta, baja, modificación, y las comparamos veremos que los cambios son mínimos.
Y como son mínimos podemos hacer una fusión de todos y obtener un único programa que sea capaz de realizar todas las tareas de
mantenimiento ahorrando código y complejidad cara al usuario.
Por lo tanto podría quedar de la siguiente forma la tarea de mantenimiento:
Select Case Campo00.Text <> ""
Case True
Posicion = CLng(Campo00.Text)
Select Case Posicion
Case 1 To 20
FileGet(CanalAgenda, Reg, Posicion) ' Lectura
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
Case Else ' Código fuera de rango
Mensaje = "Código fuera de rango"
End Select
Case Else ' Valor inadecuado
Mensaje = "Valor del campo incorrecto"
End Select
Explicación filosófica de la propuesta.

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

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.

Ejercicios propuestos de la Unidad


Pág. 42.4
Ejercicios unidad 42: Archivos Random en VB
1. Realizar la generación de un archivo random con 20 registros de 56 bytes de longitud cada uno.
2. A partir del diseño que se indica realizar la inserción de un registro en el archivo.
Structure FilRandom ‘ Tipo de usuario
<VBFixedString(15)> Public Nom As String
<VBFixedString(15)> Public Dire As String
<VBFixedString(15)> Public Pobl As String
<VBFixedString(2)> Public Prov As String
<VBFixedString(9)> Public Tele As String
End Structure
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.
3. Realizar la lectura de los datos grabados en el ejercicio anterior.
4. Realizar un programa que permita altas, bajas y modificaciones en un solo programa.
5. Copie el diseño del tema de archivos secuenciales del archivo de Amigos, para un archivo Random.
6. Copie los datos del archivo secuencial en uno Random, asignándole como posición el código de cada uno de sus
amigos.
7. Realizar el listado de esos datos en pantalla.
Si no tienes muy claro las operaciones a realizar, aquí te ayudamos.
Ayuda ejercicios unidad 42: Archivos Random en VB
En la solución de los ejercicios se han utilizado los siguientes módulos:
Module Estructuras
Structure FilRandom ' Tipo de usuario
<VBFixedString(15)> Public Nom As String
<VBFixedString(15)> Public Dire As String
<VBFixedString(15)> Public Pobl As String
<VBFixedString(2)> Public Prov As String
<VBFixedString(9)> Public Tele As String
End Structure
Public Structure FilDatosSec
<VBFixedString(15)> Public Nomb As String
<VBFixedString(15)> Public Ape1 As String
209
<VBFixedString(15)> Public Ape2 As String
<VBFixedString(30)> Public Domic As String
End Structure
End Module

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

Public Sub CreaFichero()


Dim Reg As FilRandom
Dim X As Integer
' Carga de blancos en los campos
Reg.Dire = Space(15)
Reg.Nom = Space(15)
Reg.Pobl = Space(15)
Reg.Prov = " "
Reg.Tele = Space(9)
' Crear registros en blanco
For X = 1 To 20
FilePut(Canal, Reg, X)
Next
Console.WriteLine("Archivo generado.")
Console.ReadKey()
End Sub

Public Sub Grabacion(ByVal Canal As Integer, _


ByVal Reg As FilRandom, ByRef Codigo As String)
Dim Donde As Integer = Val(Codigo) ' el código nos da la posición
FilePut(Canal, Reg, Donde)
Console.WriteLine("Datos grabados, pulse una tecla para seguir")
Console.ReadKey()
End Sub
End Module

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

Public Function Ocupado(ByVal Canal As Integer, _


ByRef Reg As FilRandom, _
ByRef Codigo As String) As Boolean
Dim Donde As Integer = Val(Codigo)
Ocupado = True
Try
FileGet(Canal, Reg, Donde)
' Si no son blancos, está ocupado
Ocupado = Reg.Nom <> Space(15)
Catch ex As ArgumentException
End Try
End Function
End Module

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"

Select Case CInt(Cual)


Case 1
CreaFichero()
Case 2
InsertarRegistro()
Case 3
LeerRegistro()
Case 4
ProcesoDos()
Case 5
Copia()
Case 6
Listado()
End Select
Loop Until Cual = "7"
End Sub
End Module

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()

2. A partir del diseño que se indica realizar la inserción de un registro en el archivo.


Structure FilRandom ‘ Tipo de usuario
<VBFixedString(15)> Public Nom As String
<VBFixedString(15)> Public Dire As String
<VBFixedString(15)> Public Pobl As String
<VBFixedString(2)> Public Prov As String
<VBFixedString(9)> Public Tele As String
End Structure

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

Select Case Ocupado(Canal, Reg, Codigo)


Case False
With Reg
If Codigo <> "" Then
Console.WriteLine("Introduce el nombre.")
.Nom = Console.ReadLine()
Console.WriteLine("Introduce la dirección.")
.Dire = Console.ReadLine()
Console.WriteLine("Introduce la población.")
.Pobl = Console.ReadLine()
Console.WriteLine("Introduce la provincia.")
.Prov = Console.ReadLine()
Console.WriteLine("Introduce el Teléfono.")
.Tele = Console.ReadLine()
Select Case Respuesta("Los datos son correctos S/N.")
Case True
Grabacion(Canal, Reg, Codigo)
End Select
End If
End With
Case Else
Console.WriteLine("El código {0} ya está útilizado.", Codigo)
Console.ReadKey()
End Select
Loop Until Codigo = ""
End Sub
End Module

Desde el menú principal se ejecuta:


InsertarRegistro()
3. Realizar la lectura de los datos grabados en el ejercicio anterior.

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

Desde el menú principal se ejecuta:


LeerRegistro()

4. Realizar un programa que permita altas, bajas y modificaciones en un solo programa.

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

Private Sub Accion(ByVal Existe As Boolean, ByVal Codigo As String)


Dim Graba As Boolean = False
Dim Modif As Boolean
With Reg
Select Case Existe
Case True ' si existe se visualiza
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)
Modif = Respuesta("Desea modificarlos S/N ")
End Select
Select Case (Modif And Existe) Or Not Existe
Case True ' si existe y se quiere modificar, o es nuevo
Console.WriteLine("Introduce el nombre.")
.Nom = Console.ReadLine()
Console.WriteLine("Introduce la dirección.")
.Dire = Console.ReadLine()
Console.WriteLine("Introduce la población.")
.Pobl = Console.ReadLine()
Console.WriteLine("Introduce la provincia.")
.Prov = Console.ReadLine()
Console.WriteLine("Introduce el Teléfono.")
.Tele = Console.ReadLine()
Graba = True ' cualquier acción acaba en grabar
Case Else ' si existe y no modifica, desea borrarlos
Select Case Existe And Not Modif
Case True
If Respuesta("Desea borrarlos S/N ") Then
' se cargan a blancos
Reg.Dire = Space(15)
Reg.Nom = Space(15)
Reg.Pobl = Space(15)
Reg.Prov = " "

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

Public Sub Proceso()


Dim Codigo As String
Dim Existe As Boolean
' mientras se introduzca un código
Codigo = LeerCodigo()
While Codigo <> ""
Existe = Ocupado(Canal, Reg, Codigo)
Accion(Existe, Codigo)
Codigo = LeerCodigo()
End While
End Sub
End Module

Desde el menú principal se ejecuta:


Proceso()

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

Private Sub Accion(ByVal Existe As Boolean, ByVal Codigo As String)


Dim Graba As Boolean = False
Dim Modif As Boolean
With Reg
Select Case Existe
Case True ' si existe se visualiza
Modif = Respuesta("Desea modificarlos S/N ")
End Select
Select Case (Modif And Existe) Or Not Existe
Case True ' si existe y se quiere modificar, o es nuevo
Console.WriteLine("Introduce el nombre.")
.Nom = Console.ReadLine()
Console.WriteLine("Introduce la dirección.")
.Dire = Console.ReadLine()
Console.WriteLine("Introduce la población.")
.Pobl = Console.ReadLine()
Console.WriteLine("Introduce la provincia.")
.Prov = Console.ReadLine()
Console.WriteLine("Introduce el Teléfono.")
.Tele = Console.ReadLine()
Graba = True ' cualquier acción acaba en grabar
Case Else ' si existe y no modifica, desea borrarlos
Select Case Existe And Not Modif
Case True
If Respuesta("Desea borrarlos S/N ") Then
' se cargan a blancos
Reg.Dire = Space(15)
Reg.Nom = Space(15)
Reg.Pobl = Space(15)
Reg.Prov = " "
Reg.Tele = Space(9)
Graba = True ' cualquier acción acaba en grabar
End If

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

Private Function Control(ByVal Codigo As String) As Boolean


Dim Posicion As Integer
Control = False
Select Case Codigo <> ""
Case True
Posicion = CLng(Codigo)
Select Case Posicion
Case 1 To 20
FileGet(Canal, Reg, Posicion) ' Lectura
Select Case Reg.Nom <> StrDup(15, " ")
Case True ' Ocupado
Visualiza() ' Visualizar datos y esperar
Control = True
Case Else ' Código libre, dejamos que se continúe
End Select ' Campo siguiente
Case Else ' Código fuera de rango
Console.WriteLine("Código fuera de rango")
End Select
Case Else ' Valor inadecuado
Console.WriteLine("Valor del campo incorrecto")
End Select
End Function

Public Sub Proceso()


Dim Codigo As String
Dim Existe As Boolean
' mientras se introduzca un código
Codigo = LeerCodigo()
While Codigo <> ""
Existe = Control(Codigo)
Accion(Existe, Codigo)
Codigo = LeerCodigo()
End While
End Sub
End Module

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

Public Structure FilDatosSec


<VBFixedString(15)> Public Nomb As String
<VBFixedString(15)> Public Ape1 As String
<VBFixedString(15)> Public Ape2 As String
<VBFixedString(30)> 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

Public Sub Copia()


Dim CanSec As Integer
Dim CanRan As Integer
Dim RegSec As FilDatos
Dim RegRan As FilDatosSec

CanSec = FreeFile()
FileOpen(CanSec, "Amigos.sec", OpenMode.Input)
CanRan = FreeFile()
FileOpen(CanRan, "Amigos.ran", OpenMode.Random, OpenAccess.ReadWrite, OpenShare.Shared, Len(RegRan))
CreaFichero(CanRan)

While Not EOF(CanSec)


With RegSec
' lectura del registro secuencial
Input(CanSec, .Codigo)
Input(CanSec, .Nomb)
Input(CanSec, .Ape1)
Input(CanSec, .Ape2)
Input(CanSec, .Domic)
' Copia si es menor de 21
If CInt(.Codigo) < 21 Then
RegRan.Nomb = .Nomb
RegRan.Ape1 = .Ape1
RegRan.Ape2 = .Ape2
RegRan.Domic = .Domic
FilePut(CanRan, RegRan, CInt(.Codigo))
Else ' incidencia, debería hacerse en un archivo
Console.WriteLine("Código {0} fuera de rango .", .Codigo)
Console.ReadKey()
End If
End With
End While
Console.WriteLine("Proceso finalizado")
Console.ReadKey()
FileClose(CanRan)
FileClose(CanSec)
End Sub
End Module

Desde el menú principal se ejecuta:


Copia()

7. Realizar el listado de esos datos en pantalla.


Module Listar
Private Sub Cabecera()
Console.WriteLine("Código Nombre Apellidos ")
Console.WriteLine("_________________________________")
End Sub

Private Sub LineaDetalle(ByVal Codigo As Integer, ByVal Reg As FilDatosSec)


Console.WriteLine(" {0} {1:18} {2:16} {3:16} ", CStr(Codigo), Reg.Nomb, Reg.Ape1, Reg.Ape2)
End Sub

Private Sub Bucle(ByVal CanRan As Integer, _


ByVal Desde As Integer, ByVal Hasta As Integer)
Dim Posicion As Integer ' contador de lectura
Dim RegRan As FilDatosSec
Dim L As Integer ' contador de líneas
Posicion = Desde ' iniciar contador
Console.Clear()
While Posicion <= Hasta
FileGet(Canran, RegRan, Posicion)
Select Case RegRan.Nomb <> Space(15)
Case True ' registro ocupado
If L = 0 Then Cabecera() ' control de cabcera
LineaDetalle(Posicion, RegRan)
L=L+1
If L > 50 Then L = 0 ' control de cabcera
End Select
Posicion = Posicion + 1 ' Incremento del contador

215
End While
Console.WriteLine("Listado finalizado")
Console.ReadKey()
End Sub

Public Sub Listado()


Dim Desde As Integer
Dim Hasta As Integer
Dim CanRan As Integer
Dim RegRan As FilDatosSec

CanRan = FreeFile()
FileOpen(CanRan, "Amigos.ran", OpenMode.Random, OpenAccess.ReadWrite, OpenShare.Shared, Len(RegRan))

Console.WriteLine("Indique desde que valor, 1 a 20")


Desde = CInt(Console.ReadLine)
Console.WriteLine("Indique hasta que valor, {0} a 20", Desde)
Hasta = CInt(Console.ReadLine)
Console.WriteLine("Desea realizar el listado S/N ")
Select Case UCase(Console.ReadKey.KeyChar)
Case "S"
Bucle(CanRan, Desde, Hasta)
End Select
FileClose(CanRan)
End Sub
End Module

Desde el menú principal se ejecuta:


Listado()

Unidad 43. Programación en un entorno gráfico (I)


43.1. Preliminares.
Los conceptos de programación pueden dividirse en tres grandes apartados.
Las estructuras de programación.
Las estructuras de datos.
El entorno en el que se ejecutará el programa.

Las estructuras de programación son los elementos comentados anteriormente.


Variables
Estructuras repetitivas
Estructuras condicionales
Estructuras secuenciales
Procedimientos
Funciones
Clases.

Las estructuras de datos son


Tipos de usuario
Arrays
Archivos
Bases de datos

El entorno de ejecución del programa podemos distinguir tres apartados


Los “programas”, en realidad clases, rutinas o librerías, como deseemos llamarlos, que se ejecutarán como
parte de un programa y que posiblemente no incorporen ningún elemento interactivo con el usuario.
Los programas que se ejecutan en un entorno de consola.
Los programas que se ejecutan en un entorno gráfico.

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.2. Objetivos del tema.


Definir los elementos de la programación en un entorno gráfico.

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

Unidad 43. Programación en un entorno gráfico (II)


43.4. Propiedades.
Cada uno de los objetos que usaremos en nuestros programas disponen de propiedades que nos van a permitir definir
Como reaccionará el objeto ante las acciones del usuario.
Como se mostrará el objeto en la ventana, colores, fuentes tamaño, ubicación.
La información que mostrará en algunos casos.

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

43.8. Tipos de ventanas, formularios.


Podemos hablar de cómo mínimo tres tipos de ventanas.
Contenedoras.
Contenidas.
Independientes.

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.

43.9. Crear un programa.


La creación de un programa en un entorno gráfico pasa por varias etapas.
Crear la interface.
Escribir la llamada al código que se ha de ejecutar por cada uno de los eventos que deseemos utilizar.
Escribir el programa propiamente dicho:

Control de la introducción de datos.


Validación de los mismos.
Acciones propias del programa que unas se inician en los eventos de los objetos del formulario y otras
como consecuencia de la activación de un botón de órdenes.
Pág. 43.2

Unidad 43. Programación en un entorno gráfico (III)


43.10. Fases de un programa.
Un programa en un entorno gráfico tiene varias fases.
Carga.
Activación.
Ejecución.
Finalización
1 Carga.
La carga dispone de eventos en los cuales podemos ejecutar aquellos pasos previos a la ejecución, como pueda ser la configuración de
los objetos y su ubicación en la ventana, apertura de archivos y conexiones con bases de datos.

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.

44.3. Interfaz de usuario.


Con los objetos que hemos descrito anteriormente podemos crear una interfaz de usuario para cualquiera de las necesidades que nos
puedan surgir, otro tema es que haya en el mercado objetos más sofisticados que nos permitan resultados más llamativos o de mejores
prestaciones, todo es cuestión de gustos y de necesidades.
Recordemos los objetos vistos.
Mostrar información.
Etiquetas
Grupos de objetos
Visualizar imágenes
Introducción de datos.
Cajas de texto
Grid, rejillas
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

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.

44.4. Diseñar la interfaz.


Primer paso es pensar que tipo de datos vamos a utilizar en el mismo, pues de ellos va a
depender el tipo de objetos que vamos a utilizar.
Normalmente se pueden abordar los diseños de varias formas, por lo tanto no hemos de
conformarnos con el primero, podemos intentar otros y elegir el que más nos guste.
La ventana anterior está creada con los objetos sin asignarle estilo, es decir colores, fuentes,
etc..

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

Unidad 44. ¿Cómo se hace un programa? (II)


44.5. Escribir el código.
Una vez que hemos creado un diseño de nuestra ventana, hay que incorporarle la parte de código que le corresponde.
Al ejemplo anterior le corresponde el siguiente código.
Public Class Mant_Provi
End Class
Todos los objetos disponen de eventos que es el punto de enlace del objeto con el mundo que le rodea.
En función del tipo de objeto habrá que crear el código adecuado para los apartados que deseemos controlar.
Un objeto de tipo de selección no llevará prácticamente código, sin embargo una caja de texto sí, porque posiblemente nos interesará
gestionar adecuadamente toda la introducción de datos por teclado, cosa que otros objetos no necesitan.
Por lo tanto hay que adecuar el código al tipo de objeto.

El código se divide en dos bloques:


El adecuado a la interfaz, para solucionar sus problemas de gestión y validación.
El necesario para la interacción con el sistema de almacenamiento de datos de la aplicación.

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.

Private Sub MensajesCampo(ByVal Cual As Integer)


Select Case Cual
Case 1
Mensajes.Text = "Introduzca el código de provincia."
Case 2
Mensajes.Text = "Introduzca la descripción."
End Select
End Sub
Ahora lo que hay que pensar es cuando queremos que se visualice dicho texto de ayuda.
Cuando el ratón pase por encima del objeto, mousemove.
Private Sub Campo01_MouseMove(ByVal sender As Object, _
ByVal e As
System.Windows.Forms.MouseEventArgs) _
Handles Campo01.MouseMove, Campo02.MouseMove
Dim Cual As Integer = CInt(Strings.Right(CType(sender,TextBox).Name,2))
MensajesCampo(Cual)
End Sub
Cuando entremos al objeto a escribir datos.
Private Sub Campo01_Enter(ByVal sender As Object, ByVal e As
System.EventArgs) _
Handles Campo01.Enter, _

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

Unidad 44. ¿Cómo se hace un programa? (IV)


3 Lectura de datos.
La otra parte del programa es la que se encarga de la lectura y grabación de los datos de la aplicación.
La lectura de datos se descompone en dos pasos, la realización de los pasos para realizar la lectura
Private Sub Lectura
FileGet(Canal, RegProvinc, CLng(Campo.Text)) ' Lectura
Select Case RegProvinc.Denom <> StrDup(Len(RegProvinc.Denom), " ") '
Ocupado
Case True ' Ocupado
Visualizar() ' Visualiza
Case Else ' Código libre
MsgBox("Código inexistente", MsgBoxStyle.Information, Me.Text)
End Select
End Sub
Y su visualización sería :
Private Sub Visualizar()
With RegProvinc
Campo02.Text = .Denom
End With
End Sub
En el caso de una base de datos, montaríamos primero la instrucción SQL, para después actuar en función de la base de datos utilizada.
CadenaSQL = "SELECT Codigo, Nombre, Nacionalidad " & _
"FROM Autores " & _
"WHERE Codigo = '" & Codigo & "'"
Y la visualización de los mismos con los objetos de los que dispone el programa en su interface cuando ésta es correcta.
Campo01.Text = Lector.Item("Codigo").ToString
Campo02.Text = Lector.Item("Nombre").ToString
' seleccionar en combo la nacionalidad
SeleccionaCombo(ComboBox01, Lector.Item("Nacionalidad").ToString)
La ejecución del código arrancará desde el procedimiento de validación al ejecutarse el evento validating en el objeto de caja de texto,
cuando en la validación del capo código se realiza la lectura correspondiente.

4 Grabación de los datos.


La grabación se compone de la recogida de los datos cuando se realiza la grabación.
Private Sub Grabar()
Dim Posicion As Integer = CInt(Campo01.Text)
With RegProvinc
.Denom = Campo02.Text
End With
FilePut(Canal, RegProvinc, Posicion)
MsgBox("Los datos han sido grabados", MsgBoxStyle.Information,
NomProgram)
End Sub
Para una base de datos se monta la instrucción SQL y en función de la base de datos utilizada se actúa después.
CadenaSQl = "Update Autores Set " & _
"Codigo = '" & Campo01.Text & "' , " & _
"Nombre = '" & Campo02.Text & "' , " & _
"Nacionalidad = '" & Nacion.Codigo.ToString & "' " & _

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.

44.7. Inicio del programa.


La fase de inicio del programa requiere en muchas ocasiones de una serie de actuaciones únicas para toda la fase de ejecución del
mismo.
Apertura de archivos
Tareas de configuración e inicialización de datos.
Carga de objetos del formulario

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

Unidad 44. ¿Cómo se hace un programa? (V)


44.8. Finalización del programa.
La finalización del programa pasa también por varias fases.
Existe una fase previa de salida en la cual se puede abortar la salida del programa.
Private Sub Programa_FormClosing(ByVal sender As Object, _ ByVal e As
System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
e.Cancel = MsgBox("Desea salir.", MsgBoxStyle.YesNo) = MsgBoxResult.No
End Sub
Y una fase en la que el programa se cierra.
Private Sub Programa_FormClosed(ByVal sender As Object, _ ByVal e As
System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
FileClose(Canal)
End Sub

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

Unidad 45. Objetos, mostrar datos (I)


45.1. Objetivos del tema.
Definir los objetos y formas de mostrar datos en una ventana.
45.2. Introducción.
La programación en un entorno gráfico sigue teniendo que realizar las mismas tareas que en una programación si queremos denominar
más tradicional. Hay que mostrar datos, capturar datos y realizar la selección de una entre varias opciones.
La diferencia es que en lugar de realizarlo en un entorno de texto se realiza con el apoyo de una sería de imágenes a las que se les dota
de una serie de capacidades, propiedades, métodos y eventos.
Estos objetos son los que tenemos en las cajas de herramientas de los entornos de programación.

45.3. Etiqueta, Label.


Una de las acciones de programación es la de mostrar información al usuario, para ello disponemos de varias
posibilidades.

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.

La utilización suele ser


Label.Text = “Texto a mostrar”
Si tenemos presente que las necesidades de mostrar datos en un programa son
muy diversas, podemos ver que éste objeto podrá intervenir en varios tipos de acciones.
Por ejemplo :
Mensajes de ayuda a la introducción de datos.
Información sobre el valor de un dato de código introducido en un campo.
Como título de una zona de nuestra ventana.

Y todavía podrían salir más casos seguramente.


Cada una de estas acciones se pueden realizar con una etiqueta convenientemente utilizada, en ubicación y
tipos de fuente utilizada.
Un ejemplo de su utilización lo tenemos al final del tema en la imagen de una ventana, donde se señaliza los
posibles distintos usos de las etiquetas y otros objetos.

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

Unidad 45. Objetos, mostrar datos (II)


45.4. Visualizar imágenes.
Otra situación para mostrar datos es la necesidad de mostrar una imagen, porque sea el logotipo de una empresa o por cualquier otra
necesidad de nuestra aplicación.

Estos objetos permiten visualizar varios tipos de archivos.

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)

45.5. Grupos de objetos.


La organización de los datos en una ventana, normalmente conlleva la necesidad de la ordenación, o agrupación de una manera más o
menos lógica.
Para ello existe una serie de objetos que son como un contenedor que en su interior son capaces albergar a otros objetos y crear un
entorno más o menos agradable y de esa forma obtener una organización y una visión más fácil de los datos que se están mostrando.
En la siguiente imagen podemos observar distintos objetos dentro de una ventana.

Pág. 45.2

Unidad 46. Objetos, el teclado (I)


46.1. Objetivos del tema.
Hemos visto antes como mostrar datos en un formulario, veamos ahora como capturar datos por teclado.

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.

46.3. Caja de texto, text box.


Su misión es la de recibir los eventos generados por el teclado, y mostrar los datos que se escriben.
Dispone de eventos para poder detectar cuando se está pulsando una tecla, separados de tal modo que nos permite saber si:
La tecla baja
La tecla sube
La tecla se pulsa

Con respecto al ratón podemos detectar:


Si pasa por encima.
Si se hace clic.
Si se hace doble clic.
Si el botón baja.
Si el botón sube.

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

Unidad 46. Objetos, el teclado (II)


46.5. Validaciones.
Salvados esos dos pasos, longitud y cuales, el siguiente paso es comprobar la veracidad de los datos introducidos.
Hay informaciones que son imposibles de comprobar, un nombre, una dirección, solo es posible asumirlos y prepararlos para su almacenamiento
en la base de datos.
Pero hay otros que si es posible comprobarlos, porque su contenido es un código, y ese código debe comprobar se su existencia,
realizando la lectura de comprobación correspondiente.
El final del camino es conseguir un control sobre los datos que se escriben en un programa para eliminar al máximo los errores en los
datos de nuestra aplicación.
Los datos deben controlarse en el momento en el que se introducen en la aplicación, de esta forma se reduce posteriormente el código
que hay que escribir en los programas que tratan estos datos.

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.

46.6. Ejemplo de filtrado en el tratamiento de teclado.


Private Sub Campo01_KeyPress(ByVal sender As Object, _
ByVal e As
System.Windows.Forms.KeyPressEventArgs) _
Handles Campo01.KeyPress, _
Campo02.KeyPress

Dim Cual As Integer = CInt(Strings.Right(CType(sender, TextBox).Name, 2))


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, no nos interesa
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

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.

Private Sub Campo00_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
No hay porque tener un procedimiento escrito para realizar la validación, podría realizarse toda la tarea en el evento, pero es cuestión de
estilos.
Expliquemos la línea de llamada.
Validacion(Cual, CType(sender, TextBox), e.Cancel)
Cual es un valor que índica el objeto que ha producido el evento.
CType(sender, TextBox) realiza la conversión del objeto a textbox, para recibir un objeto concreto en el procedimiento.
e.Cancel es el parámetro que nos va a permitir cancelar si procede la transición de un objeto a otro.
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")
LeerRegistro(Campo01.Text, Cancel)
End If
Case 2

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

Unidad 48. Seleccionar una opción (I)


48.1. Objetivos del tema.
En cualquier programa siempre existe la necesidad de ofrecer varias posibilidades al usuario para que este seleccione una de ellas, este
es el tema que vamos a abordar.

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.

Sin embargo se puede presentar también la


opción de tener que ofrecer una condición en la que
la opción es que interese o no, como podemos
observar en la imagen, que nos dan la posibilidad
de que se seleccione la opción de obtener un listado de todo el contenido de la tabla.
En ese caso el objeto adecuado es el checkbox.

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

Unidad 48. Seleccionar una opción (II)


48.4. RadioButton, utilización.
Este objeto permite describir cada una de una serie de las opciones posibles a seleccionar, de las que solo podemos elegir
una.
Cuando hemos de describir distintos conceptos si colocamos todos los objetos juntos no podríamos distinguir uno de otro de los
conceptos, pues solo se permite que esté activado un radiobutton.
Para poder expresar varias opciones lo único que hay que hacer es que cada una de ellas esté agrupada en un contenedor, como
podemos ver en la imagen de ejemplo. Cada contenedor podrá tener varios radiobutton de los que solo tendremos uno activado.
La forma de capturar su estado es comprobar el valor de la propiedad checked.
Los eventos que podemos utilizar para actuar en el objeto pueden ser click y checkedchanged.
Aunque en la mayoría de los casos no se tiene que realizar nada, ya que lo que suele ocurrir es que estos objetos se utilizan como valores
boléanos dentro de nuestro programa durante la ejecución.
Select Case Opcion01.Checked
Case True
O bien pueden formar parte de la llamada a un procedimiento.
El texto que se coloca en el objeto, propiedad text, podemos asignarle distintos tipos de alineaciones textalign, para conseguir que figure
de la forma adecuada a nuestras necesidades, derecha, centro o izquierda.

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.

48.5. CheckBox, utilización.


La utilización es básicamente idéntica al radiobutton, salvando la forma en la cual expresamos las condiciones.
Es decir un radiobutton expresa una de las posibles opciones disponibles, de las cuales elegimos una de ellas, cuando hemos de
describir varias circunstancias cada una de ellas ha de estar separada en un contenedor, dígase panel o groupbox.
Un checkbox es una condición en si mismo por lo tanto el texto que lo acompaña ha de ser muy explicito
para no inducir a error.
Pueden coexistir varios checkbox en un mismo contendor sin que eso suponga un problema de uso entre
ellos.
Como podemos ver en la imagen de ejemplo, tenemos todos los objetos en el mismo contenedor, el texto
que se utiliza en cada uno de ellos no deja lugar a dudas.

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

El resultado de sus combinaciones son:


CheckState Checked
Checked True
UnChecked False
Indeterminate True

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

Unidad 49. Selección de datos (I)


231
49.1. Objetivos del tema.
Utilización de los objetos ListBox y ComboBox.

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.

Para esta tarea disponemos de dos tipos de objetos, el listbox y el combobox.

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.

1 Características del listbox.


No permite que se pueda escribir datos en el mismo para su incorporación.
Permite que los datos que contienen puedan seleccionarse de distintas formas.
Para seleccionar la forma de selección hay que asignar el valor adecuado a la propiedad SelectionMode.
None No se admite selección de elementos.
One Predeterminado, no se admite multiselección.
MultiSimple Multiselección contigua, usando <Shift>
MultiExtended El elemento seleccionado se queda seleccionado, aunque se cambie de elemento

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.

2 Características del combobox.


No permite la multiselección, pues es solo para seleccionar un dato.
Sin embargo permite que se pueda escribir en el mismo y de esa forma o facilitar a búsqueda o
incorporar el dato a la lista de elementos del mismo.
En los formatos de su utilización disponemos de las siguientes opciones, asignándole el valor adecuado
a la propiedad DropDownStyle.
Simple Caja de texto, no desplegable.
DropDown El formato estándar
DropDownList Desplegable, no permite escribir, solo seleccionar.
Pág. 49.1

Unidad 49. Selección de datos (II)


49.4. Utilización.
La utilización de estos dos objetos es similar, ya que como hemos dicho cambia la forma de exponer los
datos, pero no la de utilizarlos.
En estos objetos para comprender su utilización hay que comprender cual es su filosofía.
Estos dos objetos, combobox y listbox, lo que almacenan en su interior no es información
en realidad, si no que lo que hacen es almacenar objetos que representan datos.
Hay que tener presente que a nivel de programación, una cosa es lo que el usuario
necesita y otra lo que necesitamos a nivel de programa.
El usuario necesita la denominación de un dato para facilitar la selección del mismo, pero
a nosotros no nos interesa la denominación del mismo, si no su código.
Por lo tanto hay que combinar ambas necesidades, y eso lo hacemos en el momento de
incorporar los datos al objeto en cuestión.
Lo que se hace, teniendo en cuenta que lo que se gestiona en el listbox y en el combobox, son objetos, es
crear un objeto que por un lado incorpore la denominación pero por otro a nosotros nos permita conocer su código.

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)

Y después solo hay que añadirlo a la colección de objetos del ComboBox.


Denom y Codigo representan las variables que contienen los datos que nos interesa incorporar al objeto.
Una vez que disponemos de la colección cargada los objetos, los datos, pueden verse en el combo o en el
listbox.

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

Creamos un objeto del mismo tipo que hemos incorporado al ComboBox.


Nacion = CType(ComboBox.SelectedItem, Combo_Lista)

Recuperamos el elemento seleccionado en el ComboBox, que nos lo proporciona SelectedItem.


Codigo = Nacion.Codigo

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

4 Vaciado del contenido.


Para ello se utiliza el método clear en cualquiera de los dos objetos.
ListaNueva.Items.Clear()

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)

Con RemoveAt eliminamos el elemento que se indica en el argumento como índice.


Con Remove se elimina el objeto que se indica.
Pág. 49.2

Unidad 49. Selección de datos (III)


6 Eliminar la selección de los elementos seleccionados.
Para ello es suficiente con asignar el valor de –1 a la propiedad SelectedIndex de cualquiera de los dos objetos.
Lista.SelectedIndex = -1

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.

50.4. Creación del menú clásico.


Arrancaremos de la ventana principal de la aplicación, el formulario MDI, en el que colocaremos un objeto que contendrá las distintas
opciones del menú.

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

Unidad 50. Los menús (II)


Como esto es muy largo, se puede desarrollar un procedimiento que reduzca el volumen de código escrito.

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

Texto de ayuda en formato de globo,


ToolTipText El texto que se desea visualizar
AutoToolTip Si se activa o no.

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

Unidad 50. Los menús (III)


50.5. Creación de un menú contextual.
Para incluir un menú contextual en la ventana, seleccionamos en la caja de herramientas el objeto
ContextMenuStrip, de la sección de menú y barra de herramientas.
Lo arrastramos encima de la ventana y lo dejamos en cualquier punto de la misma. Como es un objeto no
visualizable se creara la referencia en la barra de objetos inferior.
Le asignamos en la ventana de propiedades el nombre que deseemos.
Vamos a la propiedad Ítems y la seleccionamos, aparecerá una ventana que nos
permitirá añadir los elementos que deseemos en el menú.
Si desplegamos el combo que tenemos en la parte superior podemos seleccionar
el tipo de componente que deseamos en nuestro menú, normalmente será un menuItem ,
opción por defecto.

Pulsamos en agregar y a continuación en la ventana de la derecha seleccionamos


la propiedad Text, para escribir el texto que deseemos se visualice.
Conviene también en la propiedad Name asignar un valor acorde a su utilización.
Después solo queda ir asignando los valores a cada grupo de propiedades para
darle la apariencia que nos parezca adecuada.
Se puede anidar opciones dentro de cada uno de los elementos del menú, creando
más elementos en la propiedad DropDownItems del elemento del menú que necesitemos.

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

50.6. Barra de herramientas.


Igual que hemos creado un menú, podemos crear una barra de herramientas, todo es cuestión de si es o no
necesaria, y que no la hagamos solo como elemento decorativo y que no sea imprescindible, al fin y al cabo una barra de
herramientas en algunos casos no es nada más que un acceso rápido a determinadas acciones.

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

Dicha enumeración recoge todas las posibilidades existentes en estos cuadros.


Como objetos que son, disponen de sus eventos, propiedades y métodos, que conviene estudiar detenidamente en cada caso para poder
obtener el máximo partido de cada uno.
Pág. 51.1

Unidad 51. Cuadros de diálogo (II)


51.3. Abrir archivo.

Este es el aspecto del cuadro,,


Pero también podría ser este otro, dependerá de la versión de Windows y de la configuración del equipo.

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.

Abrir.Filter = “Texto(*.txt)|*.txt|Imágenes *.bmp;*.ico)|*.bmp;*.ico”

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

InitialDirectory Devuelve o indica el directorio de inicio para el cuadro de dialogo.

Abrir.InitialDirectory = “C:\”
Pág. 51.2

Unidad 51. Cuadros de diálogo (III)


51.4. Guardar archivo.

Este puede ser el aspecto del objeto,


O bien este:

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.

Sus valores son True / False

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

CreatePrompt Indica si hay que avisar o no cuando se va a crear un nuevo archivo.


Solo se puede utilizar con ValidateName activado a True

CreatePrompt = 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.

ValidateName = True / False

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.

Guardar.Filter = Texto(*.txt)|*.txt|Imágenes *.bmp;*.ico)|*.bmp;*.ico

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

InitialDirectory Devuelve o indica el directorio de inicio para el cuadro de dialogo.

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

Unidad 51. Cuadros de diálogo (IV)


51.5. Seleccionar impresora.

Esta puede ser la apariencia del cuadro de impresora.


Esta puede cambiar en función de los parámetros de configuración que usemos.
A continuación tenemos un ejemplo de su utilización.
Dim Imprimir As DialogResult ‘ Variable de resultado
’ Definición de los parámetros
DialogoImpresora.AllowSelection = False
DialogoImpresora.AllowSomePages = False
DialogoImpresora.PrintToFile = False
DialogoImpresora.PrinterSettings.Copies = 1
DialogoImpresora.Document = Hoja
Siguiente paso captura del resultado comprobando que la respuesta sea de aceptar.
‘ Captura del resultado
Imprimir = DialogoImpresora.ShowDialog() = DialogResult.OK
Y ya actuar si es correcta.
‘ Actuar en función del resultado
If Imprimir Then Hoja.Print()
Las propiedades más usadas son
AllowSelection
AllowSomePAges
PrintToFile
PrinterSettings

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.

51.6. Seleccionar color.


Como podemos ver en la imagen, el tipo de cuadro a encontrar cambia en función de la versión instalada de Windows, igual que en los
objetos anteriores.

La utilización de éste objeto es como sigue:


Dim Color As Color
Dim Aceptar As DialogResult
' Definimos las características
CuadroColor.AllowFullOpen =
True
CuadroColor.AnyColor = True
' Asignamos un color por
defecto
CuadroColor.Color = Color.Red
CuadroColor.Reset()
CuadroColor.SolidColorOnly = True
' Se visualiza el cuadro y se captura el resultado
Aceptar = CuadroColor.ShowDialog() = DialogResult.OK
' Control del resultado
If Aceptar Then Color = CuadroColor.Color
Las propiedades son:
AllowFullOpen
AnyColor
Color
CustomColors
SolidColorOnly
DialogTitle
Pág. 51.4

Unidad 51. Cuadros de diálogo (V)


51.7. Seleccionar fuente.
Es otra de las posibilidades que se pueden presentar en una aplicación, sobre todo cuando se desea ofrecer la posibilidad de personalizar
la misma, o cuando se deben ofrecer listados de cierto nivel de personalización.

Su uso al igual que los anteriores es sencillo.


Como siempre se divide en dos fases, la preparación del objeto
CuadroFont.MinSize = 6
CuadroFont.MaxSize = 20
CuadroFont.AllowScriptChange = True
CuadroFont.AllowSimulations = True
CuadroFont.ShowEffects = True
Y una fase de recogida de datos, con la comprobación de que sea aceptado el dato seleccionado.
If CuadroFont.ShowDialog = Windows.Forms.DialogResult.OK Then
Objeto.Font = CuadroFont.Font
End If
Podemos hacer que el cuadro asuma los valores que tengamos de muestra en el formulario, en el ejemplo que sigue se supone que en el
evento clic del objeto de muestra ejecutamos esas líneas que lo que provocan es que la ventana arranque con los valores de la muestra.

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

Unidad 51. Cuadros de diálogo (VI)


51.8. Grabar los resultados.
Los datos que se recogen de estos cuadros pueden tener diversos destinos.
Uno de ellos el de grabarse en un archivo, o una base de datos,
El sistema es fácil, declarar una tabla con el contenido adecuado a nuestras necesidades y proceder como con cualquier otra información.
Por ejemplo
With RegConfig
.ColorFondo = Objeto.BackColor.ToArgb
.ColorTexto = Objeto.ForeColor.ToArgb
.FontNombre = Trim(Objeto.Font.Name)
.Italica = Objeto.Font.Italic
.Negrita = Objeto.Font.Bold
.Subrayado = Objeto.Font.Underline
.Tachado = Objeto.Font.Strikeout
.Tamanyo = CByte(Objeto.Font.Size)
End With
En este ejemplo se recibe un objeto del tipo control, que es el que se ha usado para mostrar las características de los datos de
configuración actuales, y se asignan los datos que se han considerado útiles a una estructura de datos.
Esa estructura puede ser usada para grabarse en un archivo random,
FilePut(CanalConfig, RegConfig, Posicion)
o en una base de datos.
GrabacionBD(RegConfig, Posicion)
En el que el procedimiento de una inserción podría ser:
Private Sub GrabacionBD(ByVal RegConfig As FilConfig, _
ByVal Posicion As Long)

Dim Codigo As String = Format(Posicion, "00")


Dim CadenaSQL As String
Dim Comando As New MySql.Data.MySqlClient.MySqlCommand

CadenaSQL = "INSERT INTO Config_Objetos " & _


"( Codigo, ColorFondo, " & _
"ColorTexto, FontNombre, Italica, Negrita, " & _
"SubRayado, Tachado, Tamanyo) " & _
"Values (" & Codigo & ", " & _
RegConfig.ColorFondo & ", " & _
RegConfig.ColorTexto & ", " & _
244
"'" & RegConfig.FontNombre & "', " & _
RegConfig.Italica & ", " & _
RegConfig.Negrita & ", " & _
RegConfig.Subrayado & ", " & _
RegConfig.Tachado & ", " & _
RegConfig.Tamanyo & ");"
Conexion.Open()
' Nombre de la consulta en la base de datos.
Comando.CommandText = CadenaSQL
' Tipo de comando a ejecutar
Comando.CommandType = CommandType.Text
' Conexión a utilizar, configurada previamente.
Comando.Connection = Conexion
Select Case Comando.ExecuteNonQuery
Case 1
.. / ..
La lectura
CadenaSQL = "Select * from Config_Objetos Where Codigo = " & Codigo & ";"

Public Function LeerGenerico( _


ByVal Conexion As
MySql.Data.MySqlClient.MySqlConnection, _
ByVal CadenaSQL As String, _
ByRef Reg As DataRow, _
ByVal NomProgram As String) _
As Boolean

Dim Adaptador As MySql.Data.MySqlClient.MySqlDataAdapter


Dim Tabla As New System.Data.DataTable
Dim Trab As Boolean = False
Dim Cerrar As Boolean = Conexion.State = ConnectionState.Closed

If Cerrar Then Conexion.Open()


Try
Adaptador = New MySql.Data.MySqlClient.MySqlDataAdapter(CadenaSQL,
Conexion)
Adaptador.Fill(Tabla)
Select Case Tabla.Rows.Count > 0
Case True
Reg = Tabla.Rows.Item(0)
Trab = True
End Select
Catch ex As MySql.Data.MySqlClient.MySqlException
Msgbox(ex.ErrorCode & ex.message )
End Try
' Liberar recursos
If Cerrar Then Conexion.Close()
LeerGenerico = Trab
End

Asignación de lo leído al objeto


Dim Result As Integer
RegConfig = LecturaBD(Format(Posicion, "00"), Objeto)
Objeto.BackColor = Color.FromArgb(RegConfig.ColorFondo)
Objeto.ForeColor = Color.FromArgb(RegConfig.ColorTexto)
Objeto.Font = New Font(Trim(RegConfig.FontNombre), RegConfig.Tamanyo)
Select Case RegConfig.Negrita
Case True
Result = Result Or FontStyle.Bold
End Select
Select Case RegConfig.Italica
Case True
245
Result = Result Or FontStyle.Italic
End Select
Select Case RegConfig.Tachado
Case True
Result = Result Or FontStyle.Strikeout
End Select
Select Case RegConfig.Subrayado
Case True
Result = Result Or FontStyle.Underline
End Select
Objeto.Font = New Font(Objeto.Font, Result)
La estructura utilizada es la siguiente:
Public Structure FilConfig
Public FontNombre As String
Public Tamanyo As Integer
Public Negrita As Boolean
Public Subrayado As Boolean
Public Tachado As Boolean
Public Italica As Boolean
Public ColorTexto As Integer
Public ColorFondo As Integer
End Structure
Y la definición de la tabla:
"CREATE TABLE IF NOT EXISTS Config_Objetos " & _
"( " & _
"Codigo SMALLINT PRIMARY KEY, " & _
"FontNombre VARCHAR(25), " & _
"Tamanyo SMALLINT," & _
"Negrita SMALLINT, " & _
"Subrayado SMALLINT, " & _
"Tachado SMALLINT, " & _
"Italica SMALLINT, " & _
"ColorTexto INTEGER, " & _
"ColorFondo INTEGER " & _
")"
Pág. 51.6

Unidad 52. Otros objetos (I)


52.1. Objetivos del tema.
Existen otros objetos que sin ser imprescindibles, sin embargo aportan en algunos casos un a cómoda operatividad y ofrecen unos
resultados estupendos con muy poco esfuerzo.

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

Su utilización se basa en:


Progresion.Visible = true
Progresion.Value = 0
Progresion.Maximum = Valor máximo.
Do
X = X + 1
Progresion.Value = X
Loop until X = Final
Como ajuste para que cuadre el valor final del objeto con el final del proceso, dado que a lo mejor no coincide la el valor máximo con el
valor final del bucle, es al salir del bucle ejecutar
Progresion.value = Progresión.Maximum
Por el mismo motivo en el bucle puede interesar ejecutar
If X < Progresion.Maximum Then Progresion.Value = X
De esa forma se evitan posibles errores de valores inadecuados.
Y al acabar su uso
Progresión.visible = False
52.4. Incremento numérico.
Es un objeto de utilización ocasional, nos permite marcar un valor inicial y final de posibles valores y que se puedan alcanzar con el clic
del ratón.
Permite marcar un valor inicial que puede ser negativo, un incremento que puede ser decimal o entero, el número de decimales que
deseamos utilizar y un valor final máximo.
De esta forma se puede configurar el objeto de una forma muy ajustada.
Su valor se captura con la propiedad value.
Las propiedades principales son
DecimalPlaces
Maximum
Minimum
Value
TextAlign
UpDownAlign
Hexadecimal
Increment
IntercepArrowKeys

De estas propiedades las no comentadas son


DecimalPlaces Indica cuantas posiciones decimales visualizará el objeto.
TextAlign que indica cual es la alineación del texto visualizado en el objeto, lateral o centrada.
UpDownAlign Que indica a que lado se colocarán las flechas para pulsar.
Hexadecimal, que permite que la visualización se realice en formato Hexadecimal, en función de su valor true o false.
Increment El valor con el que se incrementara en cada pulsación, puede ser decimal.
IntercepArrowKeys Si se captura o no las teclas de cursor para su activación.
Pág. 52.1

Unidad 52. Otros objetos (II)


52.5. Pestañas.
En un programa para indicar un tipo de selección de datos, o una forma de hacer algo de una forma determinada se puede colocar un
radiobutton, y en función de su estado la interface de usuario se puede configurar de una u otra forma, o que reaccione de una determinada
manera.

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.

De esta forma un formulario que puede tener este diseño

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.

El uso de los objetos en el


programa se hace de forma individual
sin contar para nada con el tabcontrol.
El tabcontrol solo lo usaremos
para saber cual es la opción
seleccionada.

Select Case TabPage.SelectedTab.Name


Case "Page01"

Case Else
End Select
De ésta forma sabemos cual es la opción seleccionada y decidimos.
Pág. 52.2

Unidad 52. Otros objetos (III)


52.6. Calendario, DateTimePicker.
Es un objeto que nos muestra la fecha actual en distintos formatos,

Puede visualizarse en distintos formatos

En función de los valores de ShowUpDown y ShowChecBox.


Cuando pulsamos en el objeto se despliega la hoja de un calendario con formato mensual, por la que podemos navegar para seleccionar
la fecha adecuada, por el año actual, anterior y posterior, dentro de los límites marcados en el inicio o por defecto.

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.

Si deseamos capturar el valor para mostrarlo de otra forma

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.

Pero ocupa mucho más espacio en el formulario que el anterior.

Pág. 52.3

Unidad 53. DataGrid (I)


53.1. Objetivos del tema.
248
Ver en una fase de aproximación las posibilidades de utilización del DatGrid.

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.

53.3. Formas de utilización.


Este objeto permite un amplio espectro de posibilidades.
La más sencilla.
Obteniendo los datos desde una base de datos, o desde un archivo random o secuencial.

Private Sub Anyade(ByVal Impor as Double)


Dim Celdas(7) As Object
Celdas(0) = Campo01.Text
Celdas(1) = Informa04.Text
Celdas(2) = Campo02.Text
Celdas(3) = Campo03.Text
Celdas(4) = RegIVA.Porcen
Celdas(5) = Campo04.Text
Celdas(6) = Format(Impor, "##,##0.00")
Celdas(7) = Cheque01.Checked
DataGrid.Rows.Add(Celdas)
End Sub
Bien mediante el sistema de enlazar el gris a una tabla de base de datos, o consulta.
DataGrid.DataSource = TablaProvinc
Habiendo asignado previamente los datos al objeto TablaClientes.
O bien añadiéndolo campo a campo.

Private Sub AnyadirSocio()


Datagrid.Rows.Add(Lista03.SelectedValue, Lista03.Text, "")
End Sub
En el formato actual el objeto DataGridView, se ha convertido en un objeto que en realidad en sus celdas actua como contenedor, y puede
albergar los siguientes objetos
TextBox
CheckBox
ComboBox
Button
Imágenes

El resultado es un objeto muy versátil.


Pág. 53.1

Unidad 53. DataGrid (II)


53.4. Configuración.
Podríamos hablar de una configuración mínima y adecuada, y de una configuración exhaustiva.
249
With DataGrid
' Forma de acople del objeto a su contenedor, el Form
.Dock = DockStyle.None
' DockStyle.None, respeta el formato del diseño
' DockStyle.Fill, genera espacio para cada columna y activa la barra
' horizontal si es necesario.
' los demás no generan pegas.
' Color de fondo de la zona no ocupada por el datagrid
.BackgroundColor = Formulario.BackColor

' texto del datagrid


.ForeColor = Color.Black

' Estilo del borde


.BorderStyle = BorderStyle.None

' Estilo del objeto


.CellBorderStyle = DataGridViewCellBorderStyle.Sunken

' color de las lineas entre celdas, el grid


.GridColor = SystemColors.ActiveBorder

' Columna de cursor lateral


.RowHeadersVisible = False

' Asignar color de fondo de la celda que toma el foco


.DefaultCellStyle.SelectionBackColor = Color.White

' Asignar color de primer plano de la celda que toma el foco


.DefaultCellStyle.SelectionForeColor = Color.Black

' Generar columnas automático


.AutoGenerateColumns = False

' fila seleccionada


.RowsDefaultCellStyle.SelectionBackColor = Color.LightGreen

' Asignar valores apropiados para solo lectura


.AllowUserToAddRows = Estado
.AllowUserToDeleteRows = Estado
.AllowUserToOrderColumns = Estado
.EditMode = DataGridViewEditMode.EditOnEnter
.ReadOnly = False
' Sistema de selección de las celdas
.SelectionMode = DataGridViewSelectionMode.FullRowSelect
.MultiSelect = False
' Dimensionar las columnas del DataGrid para ajustarlas al contenido
cargado

.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)

' Forma de acople


.Dock = DockStyle.None

' Ajustarlo las columnas


.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
.Columns.Item(0).Width = CInt(DataGrid.Width * 0.1)
.Columns.Item(1).Width = CInt(DataGrid.Width * 0.3)
.Columns.Item(2).Width = CInt(DataGrid.Width * 0.15)
.Columns.Item(3).Width = CInt(DataGrid.Width * 0.2)
.Columns.Item(4).Width = CInt(DataGrid.Width * 0.2)

' Asignación, o cambio del texto de cabecera


.Columns(0).HeaderText = "Codigo"
.Columns(1).HeaderText = "Denominación"
.Columns(2).HeaderText = "Importe"
' Alineación de la columna, centrada verticalmente y a la derecha

.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

Unidad 53. DataGrid (III)


53.5. Crear la estructura del Grid.
Disponemos de varias formas de generar la estructura del grid.
Crearla desde la ventana de propiedades.
Generar objetos del tipo Columna.
A partir de la estructura de un objeto Tabla, mediante el enlace con DataSource.

Cualquiera de estos sistemas es válido, pero no siempre podemos usarlos siempre.


Desde la ventana de propiedades se puede hacer siempre.
251
A partir de la generación de objetos columna también.
Pero para el sistema del objeto Tabla es necesario disponer de un objeto DataTable, sino, no es posible.

1 Ventana de propiedades.
Seleccionamos la propiedad Columns y pulsamos en el botón para activar la ventana de configuración de dicha
propiedad.

A continuación solo hay que


Asignar el nombre de la
columna que vamos a añadir.
Elegir el tipo de columna que
deseamos añadir
Escribir el texto que aparecerá
en cabecera
Y pulsar agregar.

Así para cada columna del Grid.


Después hay que tener presente que cada uno de estos objetos debe de ser configurado adecuadamente, en función de su tipo y destino.
Por ejemplo para los textbox, podemos indicar si capacidad máxima.

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

Unidad 53. DataGrid (IV)


2 Objetos del tipo Columna.
Este sistema es básicamente idéntico al anterior, pero se hace desde nuestro programa, y se obtiene los mismos resultados. Solo que no
disponemos de la aplicación que nos configura , o nos ofrece las propiedades del mismo.
Dim Columna As New DataGridViewTextBoxColumn

Columna.Name = "Codigo"
Columna.HeaderText = "Código"
DataGrid.Columns.Add(Columna)

Columna = New DataGridViewTextBoxColumn


252
Columna.Name = "Descr"
Columna.HeaderText = "Descripción"
DataGrid.Columns.Add(Columna)

Columna = New DataGridViewTextBoxColumn


Columna.Name = "Importe"
Columna.HeaderText = "Importe"
DataGrid.Columns.Add(Columna)
O bien también se puede hacer:
Private Sub ConfigurarDataGrid()
'
' El objeto es un DataGridView
'
DataGrid.ColumnCount = 4
DataGrid.Columns.Item(0).Name = "Tipo"
DataGrid.Columns.Item(0).HeaderText = "Tipo"

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)

DataGrid.Columns(0).Width = CInt(DataGrid.Width * 0.1)


DataGrid.Columns(1).Width = CInt(DataGrid.Width * 0.1)
DataGrid.Columns(2).Width = CInt(DataGrid.Width * 0.6)
DataGrid.Columns(3).Width = CInt(DataGrid.Width * 0.1)
End Sub
Una vez creada la estructura, podemos ejecutar el procedimiento estándar de configuración.
3 A partir de un objeto Tabla.
Mediante este sistema creamos un DataGrid que posee una columna para cada uno de los campos que figuran en la consulta SQL que
hemos creado en nuestro programa.
Las columnas se crean en el mismo orden en el que se colocan en la instrucción SQL.
Posteriormente a su creación podemos añadir columnas nuevas.
Arrancamos con la llamada a éste procedimiento:
CargaGrid(Conexion, _
Adaptador, _
Tabla, _
CType(DataGrid, DataGridView), _
"SELECT Cod AS Código, Den AS Denominación, Impo, Tipo, Cuota FROM
Servicios ")
En el que podemos ver la instrucción SQL
"SELECT Cod AS Código, Den AS Denominación, Impo, Tipo, Cuota FROM
Servicios "
El procedimiento en cuestión es el que sigue:
Public Sub CargaGrid(ByVal Conexion As
MySql.Data.MySqlClient.MySqlConnection, _
ByRef Adaptador As
MySql.Data.MySqlClient.MySqlDataAdapter, _
ByRef Tabla As System.Data.DataTable, _
ByRef DataGrid As DataGridView, _
ByVal CadenaSql As String)

Dim ComandoActualizar As MySql.Data.MySqlClient.MySqlCommandBuilder


' DataGrid.Rows.Clear() si está enlazado no se puede
253
Tabla.Rows.Clear()
Try
' Crear un nuevo adaptador de datos
Adaptador = New MySql.Data.MySqlClient.MySqlDataAdapter(CadenaSql,
Conexion)
' Crear un 'commandbuilder' que genere el SQL Update/Insert/Delete
' el comando, no puede cambiarse de sitio pues captura datos de la
' operación anterior del adaptador.
ComandoActualizar = New
MySql.Data.MySqlClient.MySqlCommandBuilder(Adaptador)
' Llenar la tabla con los datos y enlazarla con DataSource
Adaptador.Fill(Tabla)
DataGrid.DataSource = Tabla
Catch ex As MySql.Data.MySqlClient.MySqlException
MsgBox(ex.Message, MsgBoxStyle.Information)
End Try
End Sub
En este procedimiento ya se queda enlazado el DataGrid a la tabla.
DataGrid.DataSource = Tabla
Antes que eso hemos llenado la tabla con
Adaptador.Fill(Tabla)
Que arranca a partir de
Adaptador = New MySql.Data.MySqlClient.MySqlDataAdapter(CadenaSql,
Conexion)
Pág. 53.4

Unidad 53. DataGrid (V)


53.6. Carga de datos.
La carga de datos al igual que la generación puede realizarse de varias formas
A partir de un objeto DataTable, enlazado.
Public Sub CargaGrid(ByVal Conexion As
MySql.Data.MySqlClient.MySqlConnection, _ ByRef Adaptador As
MySql.Data.MySqlClient.MySqlDataAdapter, _
ByRef Tabla As System.Data.DataTable, _
ByRef DataGrid As DataGridView, _
ByVal CadenaSql As String)

Dim ComandoActualizar As MySql.Data.MySqlClient.MySqlCommandBuilder


' DataGrid.Rows.Clear() si está enlazado no se puede
Tabla.Rows.Clear()
Try
' Crear un nuevo adaptador de datos
Adaptador = New MySql.Data.MySqlClient.MySqlDataAdapter(CadenaSql,
Conexion)
' Crear un 'commandbuilder' que genere el SQL Update/Insert/Delete
' el comando, no puede cambiarse de sitio pues captura datos de la
' operación anterior del adaptador.
ComandoActualizar = New
MySql.Data.MySqlClient.MySqlCommandBuilder(Adaptador)
' Llenar la tabla con los datos y enlazarla con DataSource
Adaptador.Fill(Tabla)
DataGrid.DataSource = Tabla
Catch ex As MySql.Data.MySqlClient.MySqlException
MsgBox(ex.Message, MsgBoxStyle.Information)
End Try
End Sub
Añadiendo los datos de forma manual, fila a fila.
Dim Tipo, Cod, Denom As String
Dim Cant As Integer

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

53.7. Borrado de datos.


Se realiza siempre a partir del método
DataGrid.Rows.Remove(DataGrid.CurrentRow)
De esta forma borramos la fila actualmente seleccionada.
Si el objeto está enlazado, al ejecutar posteriormente
Adaptador.Update(Tabla)
el contenido en la base de datos quedará actualizado.
Pág. 53.5

Unidad 53. DataGrid (VI)


53.8. Edición.
La edición quedará condicionada a los tipos de objetos que hayamos añadido al DataGrid.
Podemos editar solo cuando hay un textbox.
Private Sub DataGrid_CellValidating(ByVal sender As Object, _ ByVal e As
System.Windows.Forms.DataGridViewCellValidatingEventArgs) _ Handles
DataGrid.CellValidating

If DataGrid.Rows(e.RowIndex).IsNewRow Then Return


Select Case e.ColumnIndex
Case 0
If String.IsNullOrEmpty(e.FormattedValue.ToString()) Then
MsgBox("No puede quedar en blanco.", MsgBoxStyle.Information,
NomProgram)
e.Cancel = True
Else
If e.FormattedValue.ToString().Length > 3 Then
MsgBox("El código excede de la longitud.",
MsgBoxStyle.Information, NomProgram)
e.Cancel = True
End If
End If
Case 1
If String.IsNullOrEmpty(e.FormattedValue.ToString()) Then
MsgBox("No puede quedar en blanco.", MsgBoxStyle.Information,
NomProgram)
e.Cancel = True
End If
End Select
End Sub

Private Sub DataGrid_CellValidated(ByVal sender As Object, _ ByVal e As


System.Windows.Forms.DataGridViewCellEventArgs) _ Handles
DataGrid.CellValidated

Dim Valor As String


Select Case e.ColumnIndex
Case 0
Valor = DataGrid.CurrentCell.Value.ToString

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

Private Sub Validar_Celdas(ByVal sender As Object, _ ByVal e As


System.Windows.Forms.KeyPressEventArgs)
' Capturamos el índice de la columna
Dim Columna As Integer = DataGrid.CurrentCell.ColumnIndex
TratarTeclado(Columna, e)
End Sub
De tal forma que lo que podemos es manejar la celda del DataGrid, como un textbox más.
' Agregar el controlador de eventos para el KeyPress
AddHandler CeldasGrid.KeyPress, AddressOf Validar_Celdas
AddHandler CeldasGrid.Validating, AddressOf Validando
Ya que aquí asociamos el evento keypress normal que usamos siempre para el control del teclado.
AddHandler CeldasGrid.KeyPress, AddressOf Validar_Celdas

Private Sub Validar_Celdas


Y en este usamos creamos el evento validating para la llamada al procedimiento de validación que usemos siempre.
AddHandler CeldasGrid.Validating, AddressOf Validando
Private Sub Validando
Pág. 53.6

Unidad 53. DataGrid (VII)


53.9. Recorrido.
Podemos hacerlo de forma numérica, con un contador, o recorrer los objetos de tipo fila que componen el objeto DataGrid, o bien las
celdas que componen cada objeto fila
Recorrer el DataGrid por lo tanto podría ser:

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)

For Each Celda In Fila.Cells


Next
Ahora solo queda llenar el bucle.

53.10. Intercambio de filas.


En realidad el intercambio de filas no es posible, así tal cual.
Lo que pasa es que podemos crear objetos fila que sean iguales y no visualizarlos completos en un DataGrid, o en un ListBox, y a partir
de ahí apoyándonos en un objeto DataTable, usando el método ImportRow trasvasar objetos fila de una tabla a otra.
Private Sub Anyadir()
Dim Campos(3) As Object
Dim Fila As DataRow
Dim Fecha As String

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

Unidad 53. DataGrid (VIII)


53.11. Objetos ComboBox.
En un Datagrid podemos utilizar un objeto del tipo Combo en la columna que deseemos, eso facilita el uso de los datos de la celda, ya que
de esa forma no se visualiza el código sino su significado.
Para que funcione correctamente hay que enlazar varias propiedades.

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

Unidad 53. DataGrid (IX)


53.12. Objetos ChekBox.
Igual que podemos tener un Combo en una columna, podemos tener un ChekBox.
La forma de crearlo es muy parecida a lo ya visto.
Private Sub AnyadirCheckBox()
Dim CheckColum As New DataGridViewCheckBoxColumn
CheckColum.Name = "Contado"
CheckColum.DataPropertyName = "FormaPago"
CheckColum.ValueType = GetType(Boolean)
CheckColum.FalseValue = "0"
CheckColum.TrueValue = "1"
CheckColum.HeaderText = "Forma de Pago"
DataGrid.Columns.Add(CheckColum)
End Sub
Primero creamos el objeto.
Dim CheckColum As New DataGridViewCheckBoxColumn
Le asignamos un nombre
CheckColum.Name = "Contado"
Indicamos cual es el nombre de la columna en la SQL.
CheckColum.DataPropertyName = "FormaPago"
Indicamos que tipo de dato vamos a encontrar.
CheckColum.ValueType = GetType(Boolean)
Definimos los valores cierto y falso.
CheckColum.FalseValue = "0"
CheckColum.TrueValue = "1"

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.

53.13. Mensajes de ayuda.


Podemos utilizar el evento CellMouseMove y el parámetro ColumIndex para emitir un texto en función de la columna en la que estamos.
Private Sub DataGrid_CellMouseMove(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs)
_ Handles CellMouseMove

Select Case e.ColumnIndex


Case 0
Mensajes01.Text = "Código del servicio"
Case 1
Mensajes01.Text = "Denominación "
Case 2
Mensajes01.Text = "Tipo de servicio"
Case 3
Mensajes01.Text = "Cuota del mismo"
Case 4
Mensajes01.Text = "Importe del servicio"
End Select
End Sub

53.14. El evento CellFormatting.


En este evento podemos asignar formato en función del contenido o valor a la celda que nos interese.
En el ejemplo se asigna un color a la columna en función del número de caracteres que posee la tercera columna.
Private Sub ObjDataGrid_CellFormatting(_ ByVal sender As Object, _ ByVal e
As System.Windows.Forms.DataGridViewCellFormattingEventArgs) _ Handles
ObjDataGrid.CellFormatting

' Formato en función de la longitud de la columna, y que no esté vacía


If e.ColumnIndex = ObjDataGrid.Columns(3).Index AndAlso e.Value IsNot
Nothing
Then
Select Case e.Value.ToString().Length
Case 1
e.CellStyle.SelectionForeColor = Color.Red
e.CellStyle.ForeColor = Color.Red
Case 2
e.CellStyle.SelectionForeColor = Color.Yellow
e.CellStyle.ForeColor = Color.Yellow
Case 3
e.CellStyle.SelectionForeColor = Color.Green
e.CellStyle.ForeColor = Color.Green
Case Else
e.CellStyle.SelectionForeColor = Color.Blue
e.CellStyle.ForeColor = Color.Black
End Select
End If
End Sub
Pág. 53.9

Unidad 54. Impresión (I)


54.1. Objetivos del tema.
Realizar la tarea de imprimir sobre los objetos de impresora y de vista previa, sin utilizar la utilidad Crystal Report.
54.2. Introducción.
La tarea de impresión puede ser abordada de muchas formas, vamos a ver una de tantas, ni mejor ni peor, la comprensión de la misma,
permitirá abordar tareas de impresión más complejas.
Actualmente se imprime desde el evento, PrintPage, que se desencadena al asignar el objeto de impresión, un Objeto del tipo
PrintDocument, sobre uno de sus posibles destinatarios, PrintPreviewDialog o una impresora de las del sistema.

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

En esta secuencia se ha de desarrollar todo el proceso.


Hay que advertir de una situación que si se desconoce o se olvida, nos puede llevar de cabeza.
El salto de página se produce dentro del evento PrintPage, y la forma de provocarlo es activando una propiedad denominado
HasMorePages, a cierto, y ejecutando a continuación una salida de procedimiento.
El activar a cierto dicha propiedad provoca un retorno al evento, procedimiento al fin y al cabo, pero este retorno se produce desde el
principio, con todas sus consecuencias, no retorna al punto donde se realiza la acción.
Si no se tiene presente dicha situación, la perdida de datos incomprensible puede llevarnos de cabeza.
Por otro lado la acción de asignar el objeto de impresión, PrintDocument a su destino, impresora o vista previa, no hace que se ejecute
todo el proceso y después se siga con la siguiente línea de código, sino que provoca la ejecución de un hilo distinto de programa, lo que lleva a
que el programa haya finalizado, aunque se esté ejecutando todavía todo el proceso de impresión.

54.3. Secuencia de funcionamiento.


La secuencia de un listado en VB es la siguiente:
Introducción de los parámetros del listado por teclado.
Indicación de conformidad.
Inicio del proceso de listado.

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.

54.4. Fases de un listado.


Un listado tiene distintas fases.
–Inicio de proceso.
–Línea de identificación.
–Título
–Cabecera
–Detalle
–Pie de página
–Final de proceso

La parte repetitiva del mismo es esta:


–Línea de identificación.
–Título
–Cabecera
–Detalle
–Pie de página

Y la parte donde realmente se desarrolla todo el listado es


–Detalle

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.

Parte cíclica del listado PrintPage


–Línea de identificación.
–Título
–Cabecera
–Detalle
–Pie de página

Fin del proceso EndPrint


–Final de proceso

Veamos primero los distintos procedimientos, para así ya después solo nombrarlos por su nombre.
Pág. 54.1

Unidad 54. Impresión (II)


54.5. Procedimientos.
Los pasos que hemos nombrado antes son los siguientes:
–Inicio de proceso.
–Línea de identificación.
–Título
–Cabecera
–Detalle
–Pie de página
–Final de proceso

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)

Dim Fuente As Font = New Font("Arial", 6, FontStyle.Italic)


Dim Pincel As New System.Drawing.SolidBrush(System.Drawing.Color.Black)
Dim Alto As Long = e.PageSettings.PaperSize.Height
Dim Ancho As Long = e.PageSettings.PaperSize.Width
Dim Cx As Long ' Coordenada horizontal
Dim Texto As String

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.

El siguiente paso será ver la cabecera.


262
La cabecera se compone de varias zonas.

Esto sería el mínimo de una cabecera.


Pero podemos encontrarnos con esto también.

Pág. 54.2

Unidad 54. Impresión (III)


Los procedimientos para obtener dicho resultado podrían ser:
El título.
Public Sub Titulo(ByRef Cy As Single, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs, _
ByVal Texto As String)

Dim Fuente As Font = New Font("Arial", 16, FontStyle.Italic)


Dim Pincel As New System.Drawing.SolidBrush(System.Drawing.Color.Black)

Dim Ancho As Long = e.PageSettings.PaperSize.Width


Dim Cx As Long ' Coordenada horizontal

Cx = CLng(Ancho * 0.05) ' Margen izquierdo


Cy = Cy + Fuente.Height ' Separación de línea
e.Graphics.DrawString(Texto, Fuente, Pincel, Cx, Cy)
Cy = Cy + Fuente.Height ' Separación de línea
End Sub

El siguiente paso sería la cabecera de detalle.


Public Sub Cabecera(ByRef Cy As Single, _ ByVal TextoCab() As
CabecDetalle, _ ByVal e As System.Drawing.Printing.PrintPageEventArgs)

Dim Fuente As Font


Dim Pincel As New System.Drawing.SolidBrush(System.Drawing.Color.Black)
Dim Lapiz As New Pen(Color.Black, 3)
Dim Ancho As Long = e.PageSettings.PaperSize.Width
Dim X As Integer

Select Case e.PageSettings.Landscape


Case True
Ancho = e.PageSettings.PaperSize.Height
Case Else
Ancho = e.PageSettings.PaperSize.Width
End Select

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

' Campos del listado


TextoCabecera(0).Texto = "Num. "
TextoCabecera(1).Texto = "Servicio "
TextoCabecera(2).Texto = "Fecha "
TextoCabecera(3).Texto = "Hora "
TextoCabecera(4).Texto = ""

' Formato del texto


Formato.FormatFlags = StringFormatFlags.MeasureTrailingSpaces
' Margen lateral
Cx = CLng(Hoja.DefaultPageSettings.Margins.Left)
' Fuente a utilizar
Fuente = New Font("Arial", 12, FontStyle.Italic)
264
' 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
End Sub
Hasta aquí, el código se ejecuta desde este procedimiento al cual llamaremos cuando se de la situación de cambio de página.
Private Sub Cabeceras(ByRef Cy As Single, _ ByVal e As
System.Drawing.Printing.PrintPageEventArgs)

LineaIden(Cy, ContPag, e) ' Línea de


identificación
Titulo(Cy, e, "Listado de reservas por sócios") ' Título del
listado
Cabecera(Cy, TextoCabecera, e) ' Cabecera de
detalle
End Sub
Si en nuestro listado necesitamos unas líneas de ampliación de los datos del listado, podemos utilizar
Private Sub SubCabecera(ByRef Cy As Single, _
ByVal Texto As String, _
ByVal D As String, _
ByVal H As String, _
ByVal e As
System.Drawing.Printing.PrintPageEventArgs)

Dim Grafico As Graphics = Me.CreateGraphics


Dim AnchoString As New SizeF
Dim Fuente As Font
Dim Pincel As New System.Drawing.SolidBrush(System.Drawing.Color.Black)
Dim Cx As Single

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)

LineaIden(Cy, ContPag, e) ' Línea de


identificación
Titulo(Cy, e, "Listado de reservas por sócio.") ' Título del listado
SubCabecera(Cy, Reg.Item("NomSocio").ToString, Campo01.Text,
Campo02.Text, e)
Cabecera(Cy, TextoCabecera, e) ' Cabecera de detalle
End Sub
El siguiente paso sería las líneas de detalle.

Pág. 54.4

Unidad 54. Impresión (V)


Estas líneas se obtienen con el siguiente procedimiento.
Private Sub LineaDetalle(ByVal Reg As DataRow, _ ByVal e As
System.Drawing.Printing.PrintPageEventArgs, _ ByRef Cy As Single)

Dim Grafico As Graphics = Me.CreateGraphics


Dim AnchoString As New SizeF
Dim Fuente As Font
Dim Pincel As New System.Drawing.SolidBrush(System.Drawing.Color.Black)
Dim Fec As String

Fec = Reg.Item("Fec").ToString
Fec=Strings.Right(Fec,2) & "-" & Strings.Mid(Fec,5,2) & "-" &
Strings.Left(Fec, 4)

Fuente = New Font("Arial", 12, FontStyle.Italic)

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)

Dim Alto As Long = e.PageSettings.PaperSize.Height


Dim Ancho As Long = e.PageSettings.PaperSize.Width
Dim Fuente As Font
Dim Pincel As New System.Drawing.SolidBrush(System.Drawing.Color.Black)
Dim Cx As Long

Fuente = New Font("Arial", 14, FontStyle.Italic)


Cy = CLng(Alto * 0.95) ' Situación con respecto al alto de la
página
Cx = CLng(Ancho * 0.05) ' Situación con respecto al ancho de la
página

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

Select Case Opcion


Case 1
Hoja.DefaultPageSettings.Landscape = False
ConfigCabeceraCodigo(TextoCabecera)
Case 2
Hoja.DefaultPageSettings.Landscape = False
ConfigCabeceraSituacion(TextoCabecera)
Case 3
Hoja.DefaultPageSettings.Landscape = True
ConfigCabeceraExcepcion(TextoCabecera)
Case 4
Hoja.DefaultPageSettings.Landscape = True
ConfigCabeceraValora(TextoCabecera)
End Select
End Sub
O bien tan sencillo como esto.
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

Unidad 54. Impresión (VI)


También podemos aprovechar para esta otra situación.
Private Sub Hoja_BeginPrint(ByVal sender As Object, _
ByVal e As
System.Drawing.Printing.PrintEventArgs) _
Handles Hoja.BeginPrint
Dim CadenaSQL As String
Dim Codigo As String
Dim FechaD As String = InvierteFecha(Campo01.Text, True)
Dim FechaH As String = InvierteFecha(Campo02.Text, True)

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

Dim Cy As Long ' Coordenada vertical


Dim Cabec As Boolean = True
Dim Posicion As Integer = CInt(Campo01.Text)
While Posicion <= CLng(Campo02.Text)
FileGet(Canal, Reg, Posicion)
Select Case Reg.Modelo <> " "
Case True ' registro ocupado
If Cabec Then ' Cabeceras
Cabeceras(Cy, e)
Cabec = False
End If
LineaDet(Posicion, e, Cy) ' Línea de detalle
If Cy > e.MarginBounds.Height * 0.8 Then
e.HasMorePages = True ' Hay más hojas
Exit Sub
End If
End Select
Posicion = Posicion + 1 ' Incremento del contador
End While
e.HasMorePages = False ' No hay más hojas
End Sub
Pero tiene un pequeño fallo, y es que cuando se lance el cambio de página, el proceso vuelve al inicio, y no progresaría, porque
Dim Posicion As Integer = CInt(Campo01.Text)
Volvería a su valor inicial.
La solución puede ser
Static Posicion As Integer
Y al finalizar el listado
End While
e.HasMorePages = False ' No hay más hojas
Posicion = 0
End Sub
Otro ejemplo de bucle, este basado en un archivo secuencial
Este ejemplo funciona correctamente, porque la apertura del archivo se realiza fuera del evento PrintPage, en el BeginPrint, por lo tanto al
reentrar en el procedimiento, no se produce un error de fichero ya abierto, y como el control del bucle es por EOF, el proceso no se altera.
Cada vez que entremos como se produce
Dim Cabec As Boolean = True
Al entrar en el bucle se lanzan las cabeceras y no habría problema.
Private Sub Hoja_PrintPage(ByVal sender As Object, _
268
ByVal e As
System.Drawing.Printing.PrintPageEventArgs) _
Handles Hoja.PrintPage

Dim Cy As Long ' Coordenada vertical


Dim Cabec As Boolean = True

While Not EOF(Canal)


Input(Canal, Reg.Fecha)
Input(Canal, Reg.CodArt)
Input(Canal, Reg.Tipo)
Input(Canal, Reg.Codigo)
Input(Canal, Reg.Cantidad)
Input(Canal, Reg.Descto)

If Cabec Then ' Cabeceras


Cabeceras(Cy, e)
Cabec = False
End If
LineaDet(e, Cy) ' Línea de detalle
If Cy > e.PageSettings.PaperSize.Height * 0.9 Then
e.HasMorePages = Trae ' Hay más hojas
Exit Sub
End If
End While
e.HasMorePages = False ' No hay más hojas
End Sub
Pág. 54.6

Unidad 54. Impresión (VII)


El siguiente ejemplo utiliza una base de datos, como soporte de datos.
Private Sub Hoja_PrintPage(ByVal sender As Object, _
ByVal e As
System.Drawing.Printing.PrintPageEventArgs) _
Handles Hoja.PrintPage

Static Posicion As Integer

Dim Cy As Single ' Coordenada vertical


Dim Cabec As Boolean = True

While Posicion < Tabla.Rows.Count


Reg = Tabla.Rows(Posicion)
If Cabec Then ' Cabeceras
Cabeceras(Cy, e)
Cabec = False
End If
LineaDetalle(Reg, e, Cy) ' Línea de detalle
Posicion = Posicion + 1 ' Incremento del contador
If Cy > e.MarginBounds.Height * 0.8 Then
e.HasMorePages = True ' Hay más hojas
Exit Sub
End If
End While
e.HasMorePages = False ' No hay más hojas
Posicion = 0 ' para más listados
End Sub
Si se compara éste ejemplo con los anteriores, podremos ver que los cambios son mínimos.

Visto varios ejemplos vamos a detallar el funcionamiento de los mismos.


Definición de elementos que intervienen
Static Posicion As Integer

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

Incremento de la posición en la tabla.


If Cy > e.MarginBounds.Height * 0.8 Then
e.HasMorePages = True ' Hay más hojas
Exit Sub
End If
El control de final de página.
Se realiza porque la variable Cy, se compara con un porcentaje del alto del objeto, 80, 90 % según las necesidades.
e.HasMorePages = True ' Hay más hojas
Exit Sub
Esto es lo que provoca el salto de página en realidad, y la reentrada en el procedimiento de nuevo, y eso es desde el principio, es decir se
vuelve a ejecutar
Static Posicion As Integer

Dim Cy As Single ' Coordenada vertical


Dim Cabec As Boolean = True
De ahí, que al inicializarse a cierto Cabec, la cabecera se ejecute al principio de cada página.
Y ese es el peligro del funcionamiento del evento PrintPage, si no se escribe bien, se pierden datos por lecturas indebidas.
Y al finalizar el listado, el bucle, el While.
End While
e.HasMorePages = False ' No hay más hojas
Posicion = 0 ' para más listados
Indicamos que no hay más páginas.

e.HasMorePages = False ' No hay más hojas


Y la variable posición se asigna a cero para segundos usos.
Esto es en detalle el funcionamiento del evento Printpage, desde donde se lanza el listado.
Lo más importante es
e.HasMorePages = True ' Hay más hojas
Exit Sub
Que es lo que provoca la salida del procedimiento de evento, la obtención de una página nueva, y la reentrada en el mismo, desde el
principio, con todas sus consecuencias.

3 Fin del proceso, EndPrint.


Cuando finaliza el proceso se ejecuta este evento, y en el se cierran archivos, si procede, o se realizan procesos de actualización, etc.
Pero al igual que el BeginPrint, se ejecuta solo una vez.
Pág. 54.7
Unidad 54. Impresión (VIII)
54.7. Más situaciones.
Un listado no siempre tiene que ser tabular, a veces hay que realizar listados o impresos en los que hay que colocar membretes, o
direcciones de clientes, etc.

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)

Dim AnchoString As New SizeF


Dim Fuente As Font
Dim Pincel As New System.Drawing.SolidBrush(System.Drawing.Color.Black)
Dim Despla As New SizeF
Dim Provinc As String
Dim Cx As Long
Cy = CLng(e.PageSettings.PaperSize.Height * 0.05)
Fuente = Est_Lin_Det

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

Unidad 55. Bases de datos (I)


55.1. Objetivos del tema.
Hacer una introducción a los objetos y forma de acceder a una base de datos desde VB.

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.

55.5. Las clases.


Cada base de datos dispone de una clase especializada en el manejo de la misma.
Oracle OracleClient
MySQL MySQL
SQL SQLClient
Access OleDb
Odbc ODBC
Genérico DB

Y estas clases están disponibles en el espacio de nombres System.Data.


MySQL tiene su propio espacio de nombres, que es MySQL.
Pág. 55.1

Unidad 55. Bases de datos (II)


55.6. Los objetos.
Podemos clasificarlos o agruparlos en
Conexión.
Almacenamiento.
Visualización.
Otros.
1 Conexión.
El objeto de conexión en Access es el OleDbConnection.
Permite definir los datos necesarios para acceder a cada tipo de base de datos.

Otro objeto de conexión, es el DataAdapter.


Este objeto permite realizar el acceso a la base de datos para el intercambio de información en los dos sentidos, digamos que gestiona los
datos entre la base de datos y la aplicación a partir de los datos facilitados en la conexión.
Pertenece a System.Data.oleDb.OleDbDataAdapter.
Cada objeto de almacenamiento debe tener un objeto DataAdapter asignado, pues es el que a través del cual puede hacerse luego el
proceso de actualización.

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

Unidad 56. Enlazar VB y MySQL (I)


56.1. Objetivos del tema.
Documentar los pasos a seguir para el uso de VB con bases de datos de MySQL.
56.2. Introducción.
MySQL se puede enlazar con el uso de ODBC, pero parece más cómodo, el uso del mismo sistema basado en los objetos de conexión.
Estos están desarrollados y se pueden descargar de la página de SUN.
Igualmente podemos descargar de la misma página el gestor de la base de datos, es decir MySQL y herramientas gráficas de
administración.

56.3. Objetos necesarios.


La base de datos,
mysql-noinstall-5.1.33-win32
Los objetos de conexión para Visual Studio NET,
mysql-connector-net-5.x.x
Por comodidad la herramienta de administración del entorno de Windows,
mysql-gui-tools-noinstall-5.0-r17-win32

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

Unidad 56. Enlazar VB y MySQL (II)


56.5. Uso de VB con MySQL.
El primer paso será definir en referencias el uso de la librería, espacio de nombres, como deseemos llamarlo, de MySQL.
Deberemos saber donde hemos instalado dicha utilidad de SUN para su localización.
Para ello hay que acudir a
Proyectoà Agregar referencia.

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

Unidad 56. Enlazar VB y MySQL (III)


56.6. Creamos la base de datos.
Claro está que no hay porque hacerlo desde VB, pero veamos como hacerlo de forma mínima.
Antes de eso hay que configurar la conexión a la base de datos con el objeto Connection.
El nombre de la base de datos se supone declarado a nivel de módulo, la ruta será dentro del directorio de datos de MYSQL, por defecto.
Public Sub ConfigConexion( _
ByRef Conexion As MySql.Data.MySqlClient.MySqlConnection)
Dim CadenaConexion As String = "Data Source=localhost;" & _
"Database=" & NombreBaseDatos & ";" & _
"User Id=root;Password="
Conexion = New MySql.Data.MySqlClient.MySqlConnection(CadenaConexion)
Try
Conexion.Open()
Catch ex As MySql.Data.MySqlClient.MySqlException
MsgBox("No se ha podido establecer " & vbCrLf & _
"la conexión con la base de datos.", MsgBoxStyle.Critical)
Finally
Select Case Conexion.State
Case ConnectionState.Open
Conexion.Close()
End Select
End Try
End Sub
Está es una opción de entre varias posibles.
Hay que tener presente que la conexión es donde más cambios vamos a encontrar siempre.

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)

Conexion = New MySql.Data.MySqlClient.MySqlConnection(CadenaConexion)


Try
Conexion.Open()
Comando.Connection = Conexion
Comando.CommandType = CommandType.Text
Try
Select Case Comando.ExecuteNonQuery
Case 0
MsgBox("No se ha creado")

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

Unidad 56. Enlazar VB y MySQL (IV)


56.7. Creamos las tablas.
Con la misma filosofía se puede proceder a crear la tablas de la base de datos.
La sintaxis mínima puede ser esta.
"CREATE TABLE IF NOT EXISTS Tipo_Socio " & _
"( " & _
"Codigo VARCHAR(2) PRIMARY KEY," & _
"Denominacion VARCHAR(12) " & _
")"
Solo hay que ceñirse a la sintaxis de SQL.

Un ejemplo algo más complejo


"CREATE TABLE IF NOT EXISTS Serv_Realiz " & _
"( " & _
"Socio VARCHAR(5)," & _
"Fecha VARCHAR(8), " & _
"Reserva VARCHAR(6), " & _
"Servicio VARCHAR(3) REFERENCES Servicios ON DELETE NO ACTION " & _
"ON UPDATE NO ACTION, " & _
"Numero VARCHAR(2) REFERENCES Serv_Exist ON DELETE NO ACTION " & _
"ON UPDATE NO ACTION, " & _
"Hora VARCHAR(5), " & _
"PRIMARY KEY (Socio, Fecha, Reserva)," & _
"FOREIGN KEY (Socio) REFERENCES Socios ON DELETE NO ACTION " & _
"ON UPDATE NO ACTION, " & _
"UNIQUE (Socio, Fecha, Reserva) " & _
")"
El código puede ser el que sigue:
Private Sub CreaTabla(ByVal Conexion As
MySql.Data.MySqlClient.MySqlConnection, _
ByVal Comando As MySql.Data.MySqlClient.MySqlCommand,
_
ByVal CadenaSQL As String)

Comando = New MySql.Data.MySqlClient.MySqlCommand(CadenaSQL)


Comando.Connection = Conexion
Comando.CommandType = CommandType.Text
Try ' capturamos si hay errores
Select Case Comando.ExecuteNonQuery
Case 0
MsgBox("No se ha creado " & CadenaSQL, MsgBoxStyle.Critical,
Me.Text)
Case 1
' Creada la tabla
Case Else
MsgBox("A saber que ha pasado")
End Select
Catch ex As Exception
' si hay errores retornamos el mensaje de error
MsgBox(ex.Message, MsgBoxStyle.Critical, Me.Text)
' con Finally que es parte de TRY CATCH y END TRY
' ponemos el código que se ejecutará se produzca o no un error
278
Finally
Comando = Nothing ' lo eliminamos de la memoria
End Try
End Sub
La creación de la tabla se basa en el mismo sistema que antes, el uso de un objeto command.
El objeto connection se supone ya configurado.
Comando = New MySql.Data.MySqlClient.MySqlCommand(CadenaSQL)
Comando.Connection = Conexion
Comando.CommandType = CommandType.Text
Select Case Comando.ExecuteNonQuery
Case 0
MsgBox("No se ha creado " & CadenaSQL, MsgBoxStyle.Critical, Me.Text)
Case 1
' Creada la tabla
Case Else
MsgBox("A saber que ha pasado")
End Select
Este procedimiento se llama pasando como parámetros un objeto Connection, un objeto Command, que se podría crear en el mismo
procedimiento, no es imprescindible, y la instrucción SQL con la descripción de la tabla.
CreaTabla(Conexion, Comando, CadenaSQL)
Este procedimiento se puede basar en un array que contenga todas las tablas y un sistema adjunto de checkbox que habilite las que
deseamos crear, en la fase de pruebas de la aplicación es cómodo, después no tiene sentido.
' Tablas de apoyo
V(1).Nombre = "Tipos de socios"
V(1).Create = "CREATE TABLE IF NOT EXISTS Tipo_Socio " & _
"( " & _
"Codigo VARCHAR(2) PRIMARY KEY," & _
"Denominacion VARCHAR(12) " & _
")"
Pág. 56.4

Unidad 56. Enlazar VB y MySQL (V)


El bucle podría ser algo así.
While X < V.Length
Objeto = CType(Me.Panel01.Controls.Item(X), CheckBox)
Select Case Objeto.Checked
Case True
CreaTabla(Conexion, Comando, V(X).Create)
End Select
X = X + 1
End While
Esta es una forma de crear las tablas desde programa.
Pero disponemos de la opción del programa de administración del entorno gráfico que es comodo.

Para ello arrancamos el programa MySQLAdministrator y pulsamos en el botón de Create Table.


La ventana del programa es esta.
Seleccionamos en la lista de la izquierda la base de datos que deseamos utilizar y después pulsamos Create Table.

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.

Y el resultado es la adición de la tabla 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.

Y así con todas las tablas que deseemos crear o modificar.

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

Unidad 56. Enlazar VB y MySQL (VI)


56.8. Resto de acciones.
Con respecto al resto de acciones que se pueden presentar en un programa, no hay diferencia, su uso se basa en la misma filosofía que
con SQLServer o Access, salvando las diferencias que podamos encontrar en la sintaxis de SQL.

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

S-ar putea să vă placă și