Academia.eduAcademia.edu

POO Visual Basic

2013, ADENSA REVERSE SORIANA

Presentacion Este Manual pequeño es una redacción sobre un tema en particular Visual Basic 2010 (POO), aunque es un lenguaje muy usado también muy criticado, preferentemente no muy elegido para iniciarte en el mundo de la programación, porque muchos desarrolladores de sistemas o de algunas dicen que es un lenguaje el cual no es programar, para mi en lo particular la versión de este lenguaje me es muy divertido y bueno para programar muchas tareas o todos en ambiente Windows en este caso la versión 2010 tiene una característica muy en particular por su versión Framework 4, este tipo de versión nos permite trabajar en el ambiente .Net, aplicaciones de consola, librerías de clases, entre otras que se describirán en el manual, aquí veremos teoría, ejemplos prácticos y reales que son orientados a la realidad, para que la información aquí descrita, contendrá el código redactado de los ejemplos utilizados. También les dejare el programa y licencia del mismo así como lo que utilizamos, se los pondré en el libro mediante el desarrollo del mismo. Como todo libro antes de mostrar ejemplos, debemos explicar los conceptos básicos que a continuación describiremos con el paso del tema.

Presentacion     Este  Manual  pequeño  es  una  redacción  sobre  un  tema  en  particular  Visual  Basic   2010   (POO),   aunque   es   un   lenguaje   muy   usado   también   muy   criticado,   preferentemente   no   muy   elegido   para   iniciarte   en   el   mundo   de   la   programación,   porque   muchos   desarrolladores   de   sistemas   o   de   algunas   dicen   que   es   un   lenguaje   el   cual   no   es   programar,   para   mi   en   lo   particular   la   versión   de   este   lenguaje   me   es   muy   divertido   y   bueno   para   programar   muchas   tareas   o   todos   en   ambiente  Windows  en  este  caso  la  versión  2010  tiene  una  característica  muy  en   particular  por  su  versión  Framework  4,  este  tipo  de  versión  nos  permite  trabajar   en  el  ambiente  .Net,  aplicaciones  de  consola,  librerías  de  clases,  entre  otras  que   se  describirán  en  el  manual,  aquí  veremos  teoría,  ejemplos  prácticos  y  reales  que   son  orientados  a  la  realidad,  para  que  la  información  aquí  descrita,  contendrá  el   código  redactado  de  los  ejemplos  utilizados.  También  les  dejare  el  programa    y   licencia  del  mismo  así  como  lo  que  utilizamos,  se  los  pondré  en  el  libro  mediante   el  desarrollo  del  mismo.     Como   todo   libro   antes   de   mostrar   ejemplos,   debemos   explicar   los   conceptos   básicos  que  a  continuación  describiremos  con  el  paso  del  tema.                                                     INDICE Capitulo I Marco de Teoría Introducción a los lenguajes de programación Inicios de la programación Lenguajes de programación Algoritmos y tipos Características de un algoritmo Tipos de Datos Representacion de Algoritmos Diagramas y tipos de estructuras Introduccion a la Plataforma .NET El Entorno CLR Biblioteca de clases .NET Espacios de Nombres Arquitectura de ADO.NET LINQ Orígenes de datos Aplicaciones Windows Forms WPF Aplicaciones Web Forms Características del lenguaje Sistema de Tipos Tipos por Valor y tipos por referencia Inferencia de tipos Variables y constantes Option Strict On Inicializacion de colecciones Enumeraciones Opciones de corrección de errores Arrays (matrices) Clases y estructuras Sobrecarga de métodos y propiedades Parámetros por valor y parámetros por referencia Constructores parametrizados Propiedades Interfaces Manejo de excepciones Bloque Try y Catch Atributos Ejemplar desarrollo de Addenda Reverse Soriana   Introducción  a  la  Programación.     *  Que  es  la  Programación.   Una persona piensa y se comporta obedeciendo a una secuencia lógica. Una computadora realiza tareas y maneja datos obedeciendo a una secuencia de pasos lógicos indicados en un programa el cual ejecuta. Definición 1. La Programación de Computadoras es aquella rama de las tecnologías de la información, encargada del diseño y escritura de las instrucciones o sentencias que un ordenador debe ejecutar para completar una operación o resolver un problema. Definición 2. La Programación de Computadoras es la Ciencia que permite a una persona programar una computadora para que resuelva tareas de manera rápida. Al conjunto de operaciones que lleva a cabo un ordenador para proporcionar un determinado resultado se le denomina proceso, el conjunto de varios procesos que realizan tareas comunes, conformando de esta manera una única entidad, la denominamos programa. Programa. Un programa de computadora se puede definir como una secuencia de instrucciones que indican las acciones o tareas que han de ejecutarse por una computadora para dar solución a un problema determinado. Es un conjunto de instrucciones escritas en un lenguaje de programación, que pueden llevar a cabo uno o múltiples procesos, normalmente relacionados, aunque sin ser esto obligatorio, y que en definitiva nos permiten resolver uno o más problemas. A las instrucciones o código que forman parte de un programa se le denomina código fuente. Lenguajes de Programación. Se puede definir un lenguaje de programación como un conjunto de reglas ó normas, símbolos y palabras especiales utilizadas para construir un programa y con él, darle solución a un problema determinado. Se puede decir que un lenguaje de programación es el intermediario entre la máquina y el usuario para que este último pueda resolver problemas a través de la computadora haciendo uso de palabras (funciones) que le traducen dicho programa a la computadora para la realización de dicho trabajo. Desde que se desarrollaron las máquinas programables se han desarrollado lenguajes con los cuales las personas puedan dar órdenes a éstas. Los lenguajes de programación se pueden clasificar así: Lenguaje de máquina. Las primeras computadoras se programaban en código de máquina. Se puede decir que los programas eran diseñados en código binario. Eran difíciles de leer, difíciles de entender y por su puesto difíciles de corregir. Los Programas se caracterizaban por ser pequeños. Lenguajes de Bajo Nivel. Para dar solución a lo difícil que era programar en código máquina, se desarrolló un lenguaje conocido como lenguaje ensamblador. Este lenguaje era encargado de tomar algunas palabras comunes a una persona y traducirlas al código máquina. Lo anterior facilitaría un poco la escritura de programas. Lenguajes de Alto Nivel. Un ejemplo para entender lo que son los niveles de los lenguajes de programación es el siguiente. Suponga que usted le va a dar una instrucción a una persona para que se levante de la silla en la que está sentado. Haciendo la analogía hacia un lenguaje de alto nivel, usted simplemente le indicaría: “levántese” Haciendo la analogía hacia un Lenguaje de Bajo nivel, las instrucciones serían: “Mueva su cuerpo hacia adelante e impulse sus piernas hacia arriba hasta lograr estar de pie.” La palabra "algoritmo" es debida al celebre matematico de origen aLrabe, Mohmed ben Musa. Viene del sobrenombre del matemaÅLtico, "Al-Khwrizm+", que hace referencia al estado donde nacion. Definición. Al conjunto de pasos a seguir para llegar a la solucion de un problema, se le llama Algoritmo. Tipos de algoritmos. Se llaman algoritmos Cualitativos, a aquellos en que los pasos de la solucion se describen utilizando palabras. Se llaman algoritmos Cuantitativos, a aquellos en que la solucion se describe a traves de calculos numericos. Características de un algoritmo. Las caracteristicas con las cuales debe contar un algoritmo, son las siguientes: · Preciso: es decir que debe indicar claramente el orden de realizacion de cada paso. · Definido: es decir que si se sigue un algoritmo varias veces se debe obtener el mismo resultado cada vez. · Finito: es decir que debe tener un numero finito de pasos, que debe terminar. Nota: Cuando utilizamos el atributo, en el constructor que de forma predeterminada crea Visual Basic, los parámetros se indican por el orden alfabético de las propiedades, pero que nosotros podemos alterar usando directamente los nombres de las propiedades, tal como podemos ver en el código de ejemplo anterior. n momento. Fases Un algoritmo consta de las siguientes 3 fases: · Datos de Entrada: es la informacion proporcionada al algoritmo. · Proceso: son los calculos necesarios para encontrar la solucion del problema. · Datos de Salida: son las respuestas proporcionadas por el algoritmo o resultados finales del proceso. Ejemplo 2) Leer la base y altura de un paralelogramo. Calcular su area. Inicio P1. Solicitar la Base P2. Solicitar la Altura P3. Calcular el area = base * altura. P4. Desplegar el area del Paralelogramo Fin Datos de Entrada ---> base y altura Proceso ---> area = base x altura Datos  de  Salida  -­‐-­‐-­‐>  El  area  del  paralelogramo   Elementos.   Los   elementos   basicos   que   forman   par   te   esencial   o   fundamental   de   un   algoritmo   o   programa  son:   -­‐  Palabras  reservadas.   -­‐  Identif  icadores.   -­‐  Var  iables.   -­‐  Constantes.   -­‐  Instrucciones.   -­‐  Subprogramas   -­‐  Funciones  Internas   Palabras  reservadas.   Palabras   uti   li   zadas   por   los   algori   tmos   o   lenguajes   de   programacion   para   representar   sentencias,  ordenes,  etc.   Ejemplos:   ●  inicio.   ●  Fin.   ●  hacer.   ●  si–entonces-­‐sino.   ●  mientras.   ●  desde.   Identificadores.   Son  nombres  usados  para  identif  icar  a  los  objetos  y  demas  elementos  de  un  programa:   var   iables,   constantes,   operadores,   funciones,   procedimientos,   expresiones,   etc.   Existen   reglas  para  construer  identificadores  validos  y  son  los  siguientes:   ●  El  primer  caracter  debe  ser  una  letra  o  el  caracter  subrayado  bajo.   ●  Los  caracteres  siguientes  pueden  ser  letras,  numeros  o  simbolos  de  subrayado  bajo.   ●   Las   letras   mayusculas   y   las   letras   minusculas   se   tratan   como   distintas.   Asi   suma,   Suma   y  SUMA  son  tres  identi  f  icadores  dist  intos.   ●  No  pueden  ser  iguales  a  ninguna  palabra  reservada.   A  continuacion  se  presentan  los  conceptos  de  los  elementos  fundamentals  dentro  de  un   programa.   Variables.   Una   var   iable   es   un   objeto   a   quien   se   le   asigna   un   valor   y   cuyo   valor   puede   cambiar   durante   el   desarrol   lo   del   algori   tmo   o   ejecucion   del   programa.   Si   una   variable   esta   compuesto   por   dos   palabras,   estas   pueden   ser   juntas   o   unidos   por   el   subrayado   bajo,   guion  bajo  o  subguion  ‘_’  .   Nota:   No   se   deben   util   izar   como   nombres   de   variables   (identif   icadores)   palabras   reservadas  del  algor  i  tmo  o  del  lenguaje  de  programacion.   Ejemplos:   ●  Nota   ●  Nombre       Los   nombres   de   las   variables   elegidas   deben   ser   significativos   y   tener   relacion   con   el   objeto  que  representan,  como  pueden  ser  los  casos  siguientes:       Constantes.   Una  constante  es  un  objeto  que  se  le  asigna  un  valor  AL  INICIO,  y  que  no  cambia  durante   el  desarrollo  del  algoritmo  o  la  ejecucion  del  programa.   Inst  rucciones.   Las   instrucciones   especifican   las   operaciones   o   acciones   que   deben   ser   realizadas   o   ejecutadas.   Subprogramas.   Es   un   conjunto   de   instrucciones   agrupadas,   al   cual   se   hace   referencia   a   traves   de   un     nombre.  Cuando  el  subprograma  devuelve  un  valor  se  le  conoce  como  función;  cuando   no  devuelve  ningun  valor;  se  le  conoce  como  procedimiento.  Un  subprograma  puede  ser   definido   utilizando   parámetros,   que   son   variables   que   utilizadas   por   el   subprograma,   para  que  este  realice  alguna  funcion  especifica  de  acuerdo  a  estos  valores  recibidos.   Funciones  Internas.   Son   subprogramas   que   son   propios   del   Lenguaje   de   programacion   y   que   se   utilizan   para   realizar  acciones  en  el  algoritmo.  Todos  los  Lenguajes  de  Programacion  cuentan  con  su   propio  conjunto  de  funciones  internas,  las  cuales  alguna  gran  mayoria  son  comunes  para   todos  los  lenguajes.   Expresiones.   Son   combinaciones   de   constantes,   variables,   simbolos   de   operacion,   parentesis   y   nombres   de   funciones   especiales,   que   cumplen   determinadas   reglas.   Son   parte   de   las   instrucciones   y   se   utilizan   para   realizar   operaciones   aritmeticas   o   logicas   dentro   de   un   programa.     Expresiones  Matemát  icas.   Son  analogas  a  las  formulas  matematicas.  Las  variables  y  constantes  son  numericas  (real   o   entera)   y   las   operaciones   son   las   aritmeticas.   Cuando   necesitemos   indicar   una   operacion   aritmetica,  emplearemos  los  siguientes  simbolos:   +  Suma.  Ejemplo:  5+4  =  9   -­‐  Resta.  Ejemplo:  5-­‐4  =  1   *  Multiplicacion.  Ejemplo:  5*4=  20   /  Division.  Ejemplo:  5/4=  1.25   Division  entera.  Ejemplo:  54=1   mod  Modulo.  (residuo  de  la  division)  Ejemplo:  5  mod  4  =  1   ^  Potenciacion.  Ejemplo:  5^4  =  626   Ejemplos  utilizando  variables  y  numeros:   a  +  (  b  *  3  )  /  c   5  *  a  *  b  /  (  c  +  d)   Precedencia  de  Operadores.   Cuando  en  una  expresion  aritmetica,  existen  mas  de  una  operacion;  las  operaciones  se   evaluan   de   acuerdo   a   la   precedencia   de   operadores.   La   precedencia   de   operadores   indica  el  orden  en  el  cual  las  operaciones  deben  realizarse;  es  decir;  cual  operacion  debe   realizarse  primero  y  cual  despues.   Las   expresiones   que   tienen   dos   o   mas   operaciones   en   una   expresion   se   evaluan,   en   general,  segun  el  siguiente  orden.   1.   Las   operaciones   que   estan   encerradas   entre   parentesis   se   evaluan   primero.   Si   existen   diferentes  parentesis  anidados  (internos  unos  a  otros),  las  expresiones  mas  internas  se   evaluan  primero.   2.  Las  operaciones  aritmeticas  dentro  de  una  expresion  suelen  seguir  el  siguiente  orden   de  Prioridad  en  relacion  a  sus  operadores.   -­‐  Operador  exponencial  (^)   -­‐  Operadores  *,  /,  Ä.  mod   -­‐  Operadores  +  ,  -­‐     Lo   anterior   significa   que   el   operador   exponencial   “^”,   es   el   de   mayor   prioridad.   El   operador   de   multiplicacion   “*”,   division   “/”   y   division   entera   “Ä”   y   mod;   tienen   igual   precedencia;   pero   menor   que   el   operador   exponencial.   Los   operadores   de   suma   “+”   y   resta   “-­‐“;   tienen   la   misma   precedencia;   pero   menor   que   la   multiplicacion   “*”,   division   “/”   y   division   entera   “Ä”   y   por   consecuencia;   menor   precedencia   que   el   operador   exponencial  “^”.   3.-­‐   Cuando   en   una   expresion;   2   operadores   tienen   la   misma   precedencia;   se   evalua   primero  el  que  se  encuentra  a  la  izquierda.  Ejemplos:     Ejemplo  1.  .Cual  es  el  resultado  de  las  siguientes  expresiones?   a)  15  +  9  *  2  –  6  *  2  ^  2   b)  -­‐8  /  4  *  6  +  3  ^  2  *  (10  /  5)   SolucioÅLn:   a)  15  +  9  *  2  –  6  *  2  ^  2   15  +  9  *  2  –  6  *  4   15  +  18  -­‐  24  =  9     b)  -­‐8  /  4  *  6  +  3  ^  2  *  (10  /  5)   -­‐8  /  4  *  6  +  3  ^  2  *  2   -­‐8  /  4  *  6  +  9  *  2   -­‐2  *  6  +  18  =  6     Expresiones  Lógicas   Una  expresion  logica  es  una  expresion  que  solo  puede  tomar  dos  valores:  verdad  y  falso.   Las   expresiones   logicas   se   forman   combinando   constantes   logicas,   variables   logicas   y   otras   expresiones   logicas,   utilizando   los   operadores   relacionales   (de   relacion   o   comparacion)  y  los  operadores  logicos.   Operadores  de  Relación.   Permiten  realizar  comparaciones  de  valores  de  tipo  numerico  o  caracter.  Los  operadores   de   relacion   sirven   para   expresar   las   condiciones   en   los   algoritmos.   El   resultado   de   las   operaciones  de  comparacion  sera  verdadero  o  falso.   Los  operadores  de  relacioÅLn,  son  los  comunmente  conocidos:   >  Mayor  que.   >=  Mayor  o  igual  que.   <  Menor  que.   <=  Menor  o  igual  que.   =  Igual  que.   Ejemplos:   Si  P  =  7  *  2  y  Q  =  3  ^  2   Expresion  Logica  Resultado   P  >  Q  Verdad   P  <  Q  Falso   P  <>  Q  Verdad   (P-­‐3)  =  (Q+2)  Verdad   15  <  14  Falso   4  +  6  =  9  Falso   Operadores  Lógicos.   Los  operadores  logicos  o  voleanos  son  NOT(no),  AND  (y)  y  OR(o).  Las  definiciones  de  las   operaciones  NOT,  AND,  y  OR  se  resumen  en  unas  tablas  conocidas  como  las  tablas  de  la   verdad.     TABLA  DE  VERDAD  OPERADOR  NOT.   El   operador   NOT,   uÅLnicamente   necesita   un   operando   para   ser   utilizado.   La   tabla   de   Verdad  es  la  siguiente:     OPERANDO  NOT  OPERANDO   Verdad  False   Falso  Verdad     El   operador   simplemente   “niega”   el   valor   del   operando;   y   de   esta   forma   “invierte”   su   valor.     TABLA  DE  VERDAD  OPERADOR  AND.   El   operador   AND   necesita   2   operandos   para   ser   utilizado.   La   tabla   de   verdad   es   la   siguiente:     OPERANDO1  OPERANDO2  OPERANDO1  AND  OPERANDO2   Verdad  Verdad  Verdad   Verdad  Falso  Falso   Falso  Verdad  Falso   Falso  Falso  Falso     Como   se   observa,   este   operando   unicamente   devuelve   el   valor   Verdad;   cuando   los   2   operandos  son  Verdad.     TABLA  DE  VERDAD  OPERADOR  OR.     El   operador   OR   necesita   2   operandos   para   ser   utilizado.   La   tabla   de   verdad   es   la   siguiente:     OPERANDO1  OPERANDO2  OPERANDO1  OR  OPERANDO2   Verdad  Verdad  Verdad   Verdad  Falso  Verdad   Falso  Verdad  Verdad   Falso  Falso  Falso     Como   se   observa,   este   operando   uÅLnicamente   devuelve   el   valor   Falso;   cuando   los   2   operandos  son  Falso.       Tipos  de  Datos.     El  primer  objetivo  de  toda  computadora  es  el  manejo  de  la  informacion  o  datos.  Estos   datos   pueden   ser   las   cifras   de   ventas   de   una   bodega,   ticket’s   para   un   encuentro   deportivo,   ingreso   diario   de   una   empresa   o   las   calificaciones   de   un   salon   de   clase.   Los   algoritmos  y  programas  correspondientes  operan  sobre  datos.     Los   tipos   de   datos   definen   un   conjunto   de   valores   que   puede   almacenar   una   variable,   junto   con   un   conjunto   de   operaciones   que   se   pueden   realizar   sobre   esa   variable.   Los   tipos  de  datos  simples  son  los  siguientes:   -­‐Numericos  (enteros,  reales).   -­‐Logicos  (booleanos).   -­‐Caracter  (char,  string).       Tipos  de  Datos  Numéricos.   El  tipo  numerico  es  el  conjunto  de  los  valores  numericos.  Estos  pueden  representarse  en   dos  formas  distintas:     Tipo  entero  (int,  integer)   Es   el   subconjunto   finito   de   los   numeros   enteros,   no   tienen   componentes   fraccionarios   o   decimales,  y  pueden  ser  negativos  o  positivos.     Ejemplos:  6  -­‐9  -­‐20  11  5  19  15  -­‐1   Tipo  numérico  real  (float,  double)     Subconjunto  de  los  numeros  reales,  siempre  tiene  un  punto  decimal  y  pueden  ser   positivos  o  negativos.  Constan  de  un  entero  y  una  parte  decimal.   Ejemplos:  9.9  12.24  -­‐123.11  0.89  1470.274  -­‐0.99  54.77  3.0     Nota:   Existe  un  tipo  de  representacion  denominado  notacion  exponencial  o  cientifica  y  que  se   utiliza  para  numeros  muy  grandes  o  muy  pequenos.     Ejemplo:   Dado  un  numero  cualquiera:   367520100000000000000     Se  representa  en  notacion  descomponiendolo  en  grupo  de  tres  digitos:     367  520  100  000  000  000  000     y  posteriormente  en  forma  de  potencias  de  10,  es:     3.675201  x  1020     La  potencia  20  significa  que  despues  del  “.”  hay  que  recorrer  el  “.”  20  posiciones  a  la   derecha  para  obtener  la  cantidad     Ejemplos:   2079546000000  =  2.079546  x  1012   8927645125  =  8.927645  x  109   0.000000032458  =  3.2458  x  10-­‐8   0.0000000009284  =  9.284  x  10-­‐10     Tipos  de  Datos  Lógicos  (booleanos).   Es  aquel  dato  que  solo  puede  tomar  uno  de  dos  valores:  cierto  o  verdadero  (true)  y  falso   (false).  Ejemplo:  bSalida  =  falso.   Tipos  de  Datos  Carácter  (char,string).   Un   dato   tipo   caracter   contiene   un   solo   caracter   y   se   encuentra   delimitado   por   comilla   simple.     Una   cadena   (string)   de   caracteres   es   una   sucesion   de   caracteres   que   se   encuentran   delimitados  por  una  comilla  simple  (apostrofo)  o  dobles  comillas.     Ejemplos:  ‘Hola  Martha’,  ‘14  de  Septiembre  de  1965’,  ‘Carol  y  Dianis’.     Representación  de  Algoritmos.   Para  representar  un  algoritmo  se  debe  utilizar  algún  método  que  permita  independizar   dicho  algoritmo  del  lenguaje  de  programación  elegido.  Ello  permitirá  que  un  algoritmo   pueda  ser  codificado  indistintamente  en  cualquier  lenguaje.     Las  más  usadas  son:   -­‐  Diagrama  de  flujo   -­‐  Diagramas  Nassi-­‐Shneiderman  (diagramas  N-­‐S)   -­‐  Pseudocódigo     Dejare   un   concepto   para   tener   una   idea,   el   concepto   mas   a   fondo   lo   encontramos   en   su   pagina  official  o  google,  la  Wikipedia.     Diagramas  de  flujo.     En   esencia   el   diagrama   de   flujo   es   un   medio   de   presentación   visual   y   gráfica   del   flujo   de   datos   a   través   del   algoritmo,   de   las   operaciones   ejecutadas   y   del   orden   en   que   se   ejecutan.     Pseudo  Código.   El   pseudocódigo   es   una   herramienta   de   programación   que   nació   como   un   lenguaje   en   que  las  instrucciones  se  escriben  en  palabras  similares  al  inglés  o  español,  que  facilitan   tanto   la   escritura   como   la   lectura   de   programas.   En   esencia   el   pseudocódigo   se   puede   definer  como  un  lenguaje  de  especificación  (descripción)  de  algoritmos.     La   ventaja   del   pseudocódigo   es   que   en   su   uso,   es   decir   durante   la   planificación   de   un   programa,   el   programador   se   puede   concentrar   en   la   lógica   y   en   las   estructuras   de   control,  sin  preocuparse  por  las  reglas  de  un  determinado  lenguaje  de  programación.       Estructuras  Secuenciales.   En   esta   estructura,   las   instrucciones   se   descr   iben   una   por   una,   en   una   secuencia   descendente,  que  normalmente  está  determinada  por  el  número  de  renglón  que  ocupa.   En  esta  estructura  las  instrucciones  se  ejecutan  de  arriba  hacia  abajo.  Ejemplo:   Sol  ici  ta  el  valor  de  X;   Lee  el  valor  de  X;   Sol  ici  ta  el  valor  de  Y;   Lee  el  valor  de  Y;       Estructuras  Condicionales.   En  esta  estructura,  se  evalúa  una  expresión;  la  cual  solo  puede  tener  2  valores  posibles:   verdadero  o  falso.       Si  X  >  Y  entonces   Despl  iega  en  Pantal  la  “X  es  mayor  que  Y”   De  ot  ro  modo   Despl  iega  en  Pantal  la  “X  es  igual  o  menor  que  Y”   Fin     Estructuras  de  Condición  Múltiple.   Esta   estructura   permi   te   evaluar   una   expresión   en   donde   esta   puede   tener   más   de   2   valores  posibles.  Las  palabras  del  Lenguaje  natural  uti  l  izadas  son:     “Según”,  “hacer”,  “caso”,  ”de  otro  modo”  y  “Fin”.  Ejemplo:   Según  “expresión”  hacer   Caso  valor1:   Inst  rucciones  Caso  1:   Caso  valor2:   Inst  rucciones  Caso  2:   De  ot  ro  modo   Inst  rucciones  De  otro  modo   Fin     Estructura  de  Ciclo  Mientras.   Esta  estructura  representa  un  ciclo  que  se  repi  te  mientras  que  una  condición,  especi  f   icada  al  inicio,  se  cumpla.   Mientras  condición  haz   Instrucciones;   Fin   Estructura  de  Ciclo  Repetir.   Esta  estructura  representa  un  ciclo  que  se  repi  te  hata  que  una  condición,especificada  al   f  inal  ,  se  cumpla.   Repet  ir   Instrucciones;   Hasta  que  condición         Estructura  de  Ciclo  Hacer.   Esta   estructura   representa   un   ciclo   que   se   repi   te   mientras   que   una   condición,   especificada  al  f  inal  ,  se  cumpla.   Hacer   Instrucciones;   Mientras  condición         Estructura  de  Ciclo  Para.   Esta  estructura  representa  un  ciclo  que  se  repi  te  un  número  de  veces  determinado  por   una  variable  que  t  iene  un  valor  inicial  ,  y  que  alcanza  un  valor  f  inal  .   Para  variable=1  hasta  variable=n   Instrucciones   Fin   Estructura  de  Ciclo  Para  Cada.   Esta  estructura  representa  un  ciclo  que  se  repi  te  un  número  de  veces  determinado  por   el   número   de   elementos   que   existan   en   un   conjunto   de   datos;   como   puede   ser   una   l   ista.  Se  def  ine  una  var  iable,  la  cual  toma  cada  uno  de  los  valores  posibles  del  conjunto   de  datos.  Ejemplo:     Para  cada  nombre  en  Lista_Alumnos   Instrucciones   Fin       Diagramas  de  N-­‐S  o  de  Nassi-­‐Schederman     Este  tipo  de  diagramas,  también  denominados  como  “diagramas  de  caja”,  se  basan  en  la   representación  de  los  pasos  del  algoritmo  mediante  recuadros  adyacentes,  eliminando   los  símbolos  de  flechas  y  líneas  de  conexión.     Bien  a  continuacion  nos  enfocamos  mas  a  fondo  en  teoria  de  nuestro  Lenguaje  el  cual  es   definido  en  el  nombre  del  Libro,  finalizando  con  un  par  de  ejemplos    que  se  aplican  en  la   vida  real.       Comentario*     Bien  ahora  iniciamos  con  la  plataforma  a  la  que  nos  enfocamos  a  nuestro  libro  de  POO,   saben   a   mi   me   aburre   un   poco   la   teoria   pero   que   creen,   debemos   estudiar   antes   de   programar   es   algo   basico   pero   no   deja   de   ser   importante   para   tener   nocion   de   los   cone=ceptos  a  tocar  en  unos  momentos  mas,  no  me  profundizo  solo  lo  mas  importante.     Me   dedique   a   investigar   muchos   conceptos   de   los   cuales   algunas   referencias   las   tomo   de  google,  wiki,  un  curso  el  cual  actualmente  cursamos.     Este   libro   es   para   introducirse   a   POO   la   cual   espero   sea   de   su   agrado   y   espero   criticas   que  seran  corregidas.  Iniciamos  con  .Net  en  Visual  Basic  2010                   Introduccion  a  la  plataforma  .NET     Simplificando mucho las cosas para poder dar una definición corta y comprensible, se podría decir que la plataforma .NET es un amplio conjunto de bibliotecas de desarrollo que pueden ser utilizadas por otras aplicaciones para acelerar enormemente el desarrollo y obtener de manera automática características avanzadas de seguridad, rendimiento, etc... En realidad .NET es mucho más que eso ya que ofrece un entorno gestionado de ejecución de aplicaciones, nuevos lenguajes de programación y compiladores, y permite el desarrollo de todo tipo de funcionalidades: desde programas de consola o servicios Windows hasta aplicaciones para dispositivos móviles, pasando por desarrollos de escritorio o para Internet. Son estos últimos de los que nos ocuparemos en este curso. Pero antes conviene conocer los fundamentos en los que se basa cualquier aplicación creada con .NET, incluyendo las que nos interesan. El entorno de ejecución CLR .NET ofrece un entorno de ejecución para sus aplicaciones conocido como Common Language Runtime o CLR. El CLR es la implementación de Microsoft de un estándar llamado Common Language Infrastructure o CLI. Éste fue creado y promovido por la propia Microsoft pero desde hace años es un estándar reconocido mundialmente por el ECMA. El CLR/CLI esencialmente, define un entorno de ejecución virtual independiente en el que trabajan las aplicaciones escritas con cualquier lenguaje .NET. Este entorno virtual se ocupa de multitud de cosas importantes para una aplicación: desde la gestión de la memoria y la vida de los objetos, hasta la seguridad y la gestión de subprocesos. Lenguaje Intermedio y CLS Al contrario que otros entornos, la plataforma .NET no está atada a un determinado lenguaje de programación ni favorece a uno determinado frente a otros. En la actualidad existen implementaciones para varias decenas de lenguajes que permiten escribir aplicaciones para la plataforma .NET. Los más conocidos son Visual Basic .NET o C#, pero existen implementaciones de todo tipo, como F#, Python, Fortran, e incluso COBOL. Lo mejor de todo es que cualquier componente creado con uno de estos lenguajes puede ser utilizado de forma transparente desde cualquier otro lenguaje .NET. Además, como ya se ha comentado, es posible ejecutar el código .NET en diferentes plataformas y sistemas operativos. ¿Cómo se consigue esta potente capacidad?, esta es una Buena pregunta. Dentro del CLI, existe un lenguaje llamado IL (Intermediate Language o Lenguaje Intermedio) que está pensado de forma independiente al procesador en el que se vaya a ejecutar. Es algo parecido al código ensamblador pero de más alto nivel y creado para un hipotético procesador virtual que no está atado a una arquitectura determinada. Cuando se compila una aplicación escrita en un lenguaje .NET cualquiera (da igual que sea VB, C# u otro de los soportados), el compilador lo que genera en realidad es un Nuevo código escrito en este lenguaje intermedio. Así, todos los lenguajes .NET se usan como capa de más alto nivel para producir código IL. Un elemento fundamental del CLR es el compilador JIT (just-in-time). Su cometido es el de compilar bajo demanda y de manera transparente el código escrito en lenguaje intermedio a lenguaje nativo del procesador físico que va a ejecutar el código. Biblioteca de Clases .NET Todo lo que se ha estado comentando hasta ahora en el curso constituye la base de la plataforma .NET. Si bien es muy interesante y fundamental, por sí mismo no nos serviría de mucho para crear programas si debiésemos crear toda la funcionalidad desde cero. Obviamente esto no es así, y la plataforma .NET nos ofrece infinidad de funcionalidades "de fábrica" que se utilizan como punto de partida para crear las aplicaciones. Existen funcionalidades básicas (por ejemplo todo lo relacionado con la E/S de datos o la seguridad) y funcionalidades avanzadas en las que se fundamentan categorías enteras de aplicaciones (acceso a datos, creación de aplicaciones Web...). Toda esta funcionalidad está implementada en forma de bibliotecas de funciones que físicamente se encuentran en diversas DLL (bibliotecas de enlazado dinámico). A su conjunto se le denomina Base Classes Library (Biblioteca de clases base o BCL), y forman parte integral de la plataforma .NET, es decir, no se trata de añadidos que se deban obtener o adquirir aparte. Los espacios de nombres Dada la ingente cantidad de clases con la que podemos trabajar, debe existir alguna forma de organizarlas de un modo coherente. Además hay que tener en cuenta que podemos adquirir más funcionalidades (que se traducen en clases) de otros fabricantes, por no mencionar que crearemos continuamente nuevas clases propias. Para solucionar este problema existen en todos los lenguajes .NET los espacios de nombres o namespaces. Así por ejemplo, todo lo que tiene que ver con el manejo de estructuras de datos XML en la plataforma .NET se encuentra bajo el espacio de nombres System.Xml, entre otros. Acceso a datos con ADO NET El acceso a fuentes de datos es algo indispensable en cualquier lenguaje o plataforma de desarrollo. La parte de la BCL que se especializa en el acceso a datos se denomina de forma genérica como ADO.NET. Si usted ha programado con Visual Basic 6.0 ó con ASP, ha empleado en su código con total seguridad la interfaz de acceso a datos conocida como ADO (ActiveX Data Objects), y posiblemente lo ha combinado además con ODBC (Open Database Connectivity). Si además es usted de los programadores con solera y lleva unos cuantos años en esto, es probable que haya usado RDO o incluso DAO, todos ellos métodos mucho más antiguos. ADO.NET ofrece una funcionalidad completamente nueva, que tiene poco que ver con lo existente hasta la fecha en el mercado. Sin embargo, con el ánimo de retirar barreras a su aprendizaje, Microsoft denominó a su nuevo modelo de acceso a datos con un nombre similar y algunas de sus clases recuerdan a objetos de propósito análogo en el vetusto ADO. Arquitectura de ADO.NET El concepto más importante que hay que tener claro sobre ADO.NET es su modo de funcionar, que se revela claramente al analizar su arquitectura:                                     Existen dos capas fundamentales dentro de su arquitectura: la capa conectada y la desconectada. Capa conectada La primera de ellas contiene objetos especializados en la conexión con los orígenes de datos. Así, la clase genérica Connection se utiliza para establecer conexiones a los orígenes de datos. La clase Command se encarga de enviar comandos de toda índole al origen de datos. Por fin la clase DataReader está especializada en leer los resultados de los comandos mientras se permanece conectado al origen de datos. La clase DataAdapter hace uso de las tres anteriores para actuar de puente entre la capa conectada y la desconectada. Estas clases son abstractas, es decir, no tienen una implementación real de la que se pueda hacer uso directamente. Es en este punto en donde entran en juego los proveedores de datos. Cada origen de datos tiene un modo especial de comunicarse con los programas que los utilizan, además de otras particularidades que se deben contemplar. Un proveedor de datos de ADO.NET es una implementación concreta de las clases conectadas abstractas que hemos visto, que hereda de éstas y que tiene en cuenta ya todas las particularidades del origen de datos en cuestión. Así, por ejemplo, las clases específicas para acceder a SQL Server se llaman SqlConnection, SqlCommand, SqlDataReader y SqlDataAdapter y se encuentran bajo el espacio de nombres System.Data.SqlClient. Es decir, al contrario que en ADO clásico no hay una única clase Connection o Command que se use en cada caso, si no que existen clases especializadas para conectarse y recuperar información de cada tipo de origen de datos.   Existen proveedores nativos, que son los que se comunican directamente con el origen de datos (por ejemplo el de SQL Server o el de Oracle), y proveedores "puente", que se utilizan para acceder a través de ODBC u OLEDB cuando no existe un proveedor nativo para un determinado origen de datos. Capa desconectada Una vez que ya se han recuperado los datos desde cualquier origen de datos que requiera una conexión ésta ya no es necesaria. Sin embargo sigue siendo necesario trabajar con los datos obtenidos de una manera flexible. Es aquí cuando la capa de datos desconectada entran en juego. Además, en muchas ocasiones es necesario tratar con datos que no han sido obtenidos desde un origen de datos relacional con el que se requiera una conexión. A veces únicamente necesitamos un almacén de datos temporal pero que ofrezca características avanzadas de gestión y acceso a la información. Por otra parte las conexiones con las bases de datos son uno de los recursos más escasos con los que contamos al desarrollar. Su mala utilización es la causa más frecuente de cuellos de botella en las aplicaciones y de que éstas no escalen como es debido. Esta afirmación es especialmente importante en las aplicaciones Web en las que se pueden recibir muchas solicitudes simultáneas de cualquier parte del mundo. Finalmente otro motivo por el que es importante el uso de los datos desconectado de su origen es la transferencia de información entre capas de una aplicación. Éstas pueden encontrarse distribuidas por diferentes equipos, e incluso en diferentes lugares del mundo gracias a Internet. Por ello es necesario disponer de algún modo genérico y eficiente de poder transportar los datos entre diferentes lugares, utilizarlos en cualquiera de ellos y posteriormente tener la capacidad de conciliar los cambios realizados sobre ellos con el origen de datos del que proceden. Todo esto y mucho más es lo que nos otorga el uso de los objetos DataSet. Es obvio que no se trata de tareas triviales, pero los objetos DataSet están pensados y diseñados con estos objetivos en mente. Como podremos comprobar más adelante en este curso es bastante sencillo conseguir estas funcionalidades tan avanzadas y simplemente usando de manera adecuada este tipo de objetos. algunas otras   LINQ     LINQ es quizás una de las características más novedosas introducidas en Microsoft .NET Framework en los últimos años. No cejaré en animarle a usar LINQ siempre que pueda, no porque sea mejor que otras formas de trabajar que encontrará en Microsoft .NET Framework, sino porque simplifica el código, acorta los tiempos de desarrollo, y bajo mi particular punto de vista, permite que el desarrollador desarrolle aplicaciones más productivas. LINQ significa Language INtegrated Query, o lo que es lo mismo, lenguaje integrado de consultas. Se trata de una de las novedades incluidas en Microsoft .NET Framework 3.5 y continuada en Microsoft .NET Framework 4.0, y representa una forma nueva de desarrollo tal y como la conocíamos hasta ahora. LINQ está pensado desde la orientación a objetos, pero su objetivo fundamental es la manipulación y trabajo con datos. Cuando hablamos de datos siempre pensamos en bases de datos, pero LINQ tiene una implicación mucho más generalista, de hecho, podemos trabajar con colecciones, matrices, etc. Para que comprenda más aún la importancia de LINQ, diremos que la inmensa mayoría de las novedades introducidas en Microsoft .NET Framework 3.5 tienen su razón de ser gracias a LINQ, y que LINQ juega un importante papel en las novedades de Microsoft .NET Framework 4.0 y en las próximas novedades de Microsoft .NET Framework. A la hora de trabajar con datos, con LINQ tenemos la posibilidad de seleccionar, manipular y filtrar datos como si estuviéramos trabajando con una base de datos directamente. Evidentemente, podemos usar LINQ con bases de datos, pero también con matrices, colecciones de datos, etc como decíamos antes. En todo esto, Intellisense juega un papel muy importante evitando que cometamos errores a la hora de escribir nuestras aplicaciones, errores como por ejemplo seleccionar el dato erróneo o el tipo de dato inadecuado, ya que el compilador nos avisaría de estos y otros errores. Por lo tanto, el desarrollo de aplicaciones con LINQ, permite diseñar aplicaciones más seguras a la hora de trabajar con datos y sus tipos. Orígenes de datos Dentro de LINQ encontramos diferentes orígenes de datos dentro de Microsoft .NET Framework 3.5 ó posterior. Estos orígenes de datos son los siguientes: LINQ to Objects: representa el uso de LINQ sobre objetos. LINQ to XML: representa el uso de LINQ sobre documentos XML. ADO.NET y LINQ: dentro de este grupo encontramos los diferentes orígenes de datos de LINQ que tienen relación directa con datos relacionales. Los orígenes de datos de LINQ y ADO.NET son: LINQ to DataSet: representa el uso de LINQ sobre DataSet. LINQ to SQL: representa el uso de LINQ sobre orígenes de datos de SQL Server. LINQ to Entities: representa el uso de LINQ sobre cualquier origen de datos, SQL Server, Oracle, MySql, DB2, etc. Como vemos, LINQ abarca más que el propio trabajo con datos de bases u orígenes de datos. Así, con LINQ podemos manipular y trabajar con datos de objetos o de documentos XML. Aplicaciones Windows Forms. Esto va de maravilla, nos acercamos mas al Corazon de este libro. Las aplicaciones de escritorio son aquellas basadas en ventanas y controles comunes de Windows que se ejecutan en el sistema local. Son el mismo tipo de aplicaciones que antes construiríamos con Visual Basic 6 u otros entornos similares. En la plataforma .NET, el espacio de nombres que ofrece las clases necesarias para construer aplicaciones de escritorio bajo Windows se denomina Windows Forms. Este es también el nombre genérico que se le otorga ahora a este tipo de programas basados en ventanas. Windows Forms está constituido por multitud de clases especializadas que ofrecen funcionalidades para el trabajo con ventanas, botones, rejillas, campos de texto y todo este tipo de controles habituales en las aplicaciones de escritorio. Visual Studio ofrece todo lo necesario para crear visualmente este tipo de programas, de un modo similar aunque más rico al que ofrecía el entorno de desarrollo integrado de Visual Basic. Al contrario que en en VB6, .NET proporciona control sobre todos los aspectos de las ventanas y controles, no dejando nada fuera del alcance del programador y otorgando por lo tanto la máxima flexibilidad. Los formularios (ventanas) son clases que heredan de la clase base Form, y cuyos controles son miembros de ésta. De hecho se trata únicamente de código y no es necesario (aunque sí muy recomendable) emplear el diseñador gráfico de Visual Studio para crearlas. Este es el aspecto que presenta parte del código que genera la interfaz mostrada en la anterior figura: Al contrario que en Visual Basic tradicional, en donde siempre existían instancias por defecto de los formularios que podíamos usar directamente, en .NET es necesario crear unobjeto antes de poder hacer uso de los formularios: Dim frm As New MiFormulario frm.Show() Todos los controles heredan de una clase Control por lo que conservan una serie de funcionalidades comunes muy interesantes, como la capacidad de gestionarlos en el diseñador (moviéndolos, alineándolos...), de definir márgenes entre ellos o hacer que se adapten al tamaño de su contenedor. WPF Sin embargo, en los últimos años Microsoft ha estado trabajando intensamente en lo que se ha denominado como WPF, o lo que es lo mismo, Windows Presentation Foundation. WPF es "otra forma" de crear aplicaciones de escritorio con un enriquecimiento en la experiencia del usuario. Aplicaciones Web Forms Tradicionalmente las aplicaciones Web se han desarrollado siguiendo un modelo mixto que intercalaba código HTML y JavaScript propio de páginas Web (parte cliente), junto con código que se ejecutaría en el servidor (parte servidora). Este modelo contrastaba por completo con el modelo orientado a eventos seguido por las principales herramientas de desarrollo de aplicaciones de escritorio. En el modelo orientado a eventos se define la interfaz de usuario colocando controles en un contenedor y se escribe el código que actuará como respuesta a las interacciones de los usuarios sobre estos controles. Si conoce el diseñador de VB6 o de Windows Forms mencionado en el apartado anterior sabe exactamente a qué nos referimos. Hacer esto en una aplicación de escritorio no tiene mayor dificultad ya que todo el código se ejecuta en el mismo lugar. La principal característica de las aplicaciones Web sin embargo es que se la interfaz de usuario (lo que los usuarios de la aplicación ven) se ejecuta en un lugar diferente al código de la aplicación que reside en un servidor. Para mayor desgracia estas aplicaciones se basan en el uso del protocolo HTTP que es un protocolo sin estado y que no conserva la conexión entre dos llamadas consecutivas. Por ejemplo, el siguiente código ilustra el código que es necesario escribir en ASP para disponer de una página que rellena una lista de selección con unos cuantos nombres (podrían salir de una base de datos y aún sería más complicado), y que dispone de un botón que escribe un saludo para el nombre que se haya elegido de la lista. Código ASP sencillo que genera una lista de selección y saluda al presionar un botón. Obviamente se podría haber simplificado sin enviar el formulario al servidor usando JavaScript en el cliente para mostrar el saludo, pero la intención es ilustrar la mezcla de código de cliente y de servidor que existe en este tipo de aplicaciones. Caracteristicas del Lenguaje. - El Sistema de Tipos - Clases y estructuras - Manejo de excepciones - Eventos y delegados - Atributos Continuacion de Linea Implicita. En Visual Basic 2010 se denota como cambio de linea o continuación de línea implícita. En el siguiente ejemplo, podemos ver como usar la antigua forma de realizar una continuación de línea en Visual Basic: Dim sample As String = "Ejemplo con Visual Basic 2010" & _ Environment.NewLine & _ "Con salto de linea" Esta antigua forma, que consiste en continuar la línea utilizando el caracter _ al final de la misma, continua siendo válido. Sin embargo, a partir de Visual Basic 2010, también podremos continuar la línea sin necesidad de utilizar dicho caracter. Un ejemplo de código compatible con lo que estamos diciendo, sería el siguiente: Dim sample As String = "Ejemplo con Visual Basic 2010" & Environment.NewLine & "Con salto de linea" Como vemos, la única diferencia reside en utilizar u omitir el caracter de salto de línea _ que ha sido usado desde que apareciera la primera versión de Visual Basic antes incluso de la plataforma .Net. Bien ahora explicamos teoricamente cada uno de los puntos, explico teoria porque es necesario saber conceptos que adelante encontraremos, pero bien vamos explicamos brevemente y pasamos a ejemplos. El Sistemas de tipos. -Tipos primitivos. -Variables y constants -Enumeraciones -Arrays (matrices) En esta parte veremos los tipos de datos que .Net Framework pone a nuestra disposicion en Visual Basic 2010. Los tipos de datos que podemos usar en Visual Basic 2010 son los mismo tipos de datos definidos en .NET Framework y por tanto están soportados por todos los lenguajes que usan esta tecnología. Tipos primitivos, estos son algunos que coloco los cuales son communes. En la siguiente tabla los tipos de datos definidos en .NET Framework y los alias utilizados en Visual Basic 2010. Las últimas filas mostradas en la tabla son tipos especiales que si bien son parte del sistema de tipos comunes (CTS) no forman parte de la Common Language Specification (CLS), es decir la especificación común para los lenguajes "compatibles" con .NET, por tanto, si queremos crear aplicaciones que puedan interoperar con todos los lenguajes de .NET. Tipos por valor y tipos por referencia Los tipos de datos de .NET los podemos definir en dos grupos: -Tipos por valor -Tipos por referencia Los tipos por valor son tipos de datos cuyo valor se almacena en la pila o en la memoria "cercana", como los numéricos que hemos visto. Es decir se almacena directamente en la memoria reservada para ese tipo y cualquier cambio que hagamos lo haremos directamente sobre dicho valor, de igual forma cuando copiamos valores de un tipo por valor a otro, estaremos haciendo copias independientes. Por otro lado, los tipos por referencia se almacenan en el "monto" (heap) o memoria "lejana", a diferencia de los tipos por valor, los tipos por referencia lo único que almacenan es una referencia (o puntero) al valor asignado. Si hacemos copias de tipos por referencia, realmente lo que copiamos es la referencia propiamente dicha, pero no el contenido. Inferencia de tipos Una de las características nuevas en Visual Basic 2008 y Visual Basic 2010 es la inferencia de tipos. Se conoce como inferencia de tipos a la característica de Visual Basic para inferir el tipo de un dato al ser inicializado. Para que la inferencia de tipos sea efectiva, deberemos activar la opción Option Infer a True, aunque por defecto, ese es el valor que tiene el compilador de Visual Basic. Sin embargo, si se hace una migración de una aplicación de Visual Basic a Visual Basic 2010, el valor de esta opción será False. Supongamos por lo tanto, la siguiente declaración: Dim datoDeclarado = 2010 En este ejemplo, la variable datoDeclarado, será una variable de tipo Integer (Int32). Si deseamos cambiar el tipo de dato a un tipo Int64 por ejemplo, el compilador nos devolverá un error. Así, el siguiente Ejemplo no será válido en Visual Basic 2010 con la opción de inferencia activada: Dim datoDeclarado = 2010 datoDeclarado = Int64.MaxValue Ahora bien, si cambiamos el valor de Option Infer a False, el mismo Ejemplo sera correcto. Ahora bien, si cambiamos el valor de Option Infer a False, el mismo ejemplo sera correcto. ¿Dónde está la diferencia?. En este último caso, el caso de tener desactivada la opción de inferencia, la declaración de la variable datoDeclarado nos indica que es un tipo de dato Object en su origen, y que al darle un valor Integer, ésta funciona como una variable entera. Al cambiar su valor a Long, esta variable que es de tipo Object, cambia sin problemas a valor Long. En todo este proceso, hay un problema claro de rendimiento con acciones de boxing y unboxing que no serían necesarias si tipáramos la variable con un tipo concreto. Eso es justamente lo que hace la opción Option Infer por nosotros. Nos permite declarer una variable con el tipo inferido, y ese tipo de datos se mantiene dentro de la aplicación, por lo que nos da la seguridad de que ese es su tipo de dato, y que ese tipo de dato no va a variar. Variables y constantes Disponer de todos estos tipos de datos no tendría ningún sentido si no pudiéramos usarlos de alguna otra forma que de forma literal. Y aquí es donde entran en juego las variables y constantes, no vamos a contarte qué son y para que sirven, salvo en el caso de las constantes, ya que no todos los desarrolladores las utilizamos de la forma adecuada. Consejo para usar las constantes Siempre que tengamos que indicar un valor constante, ya sea para indicar el máximo o mínimo permitido en un rango de valores o para comprobar el término de un bucle, deberíamos usar una constante en lugar de un valor literal, de esta forma si ese valor lo usamos en varias partes de nuestro código, si en un futuro decidimos que dicho valor debe ser diferente, nos resultará más fácil realizar un solo cambio que cambiarlo en todos los sitios en los que lo hemos usado, además de que de esta forma nos aseguramos de que el cambio se realiza adecuadamente y no tendremos que preocuparnos de las consecuencias derivadas de no haber hecho el cambio en todos los sitios que deberíamos. Las constantes se definen utilizando la instrucción Const seguida del nombre, opcionalmente podemos indicar el tipo de datos y por último una asignación con el valor que tendrá. Como veremos en la siguiente sección, podemos obligar a Visual Basic 2010 a que en todas las constantes (y variables) que declaremos, tengamos que indicar el tipo de datos. Para declarar una constante lo haremos de la siguiente forma: Const maximo As Integer = 12345678 Declarar variables La declaración de las variables en Visual Basic 2010 se hace por medio de la instrucción Dim seguida del nombre de la constante y del tipo de datos que esta contendrá. Con una misma instrucción Dim podemos declarar más de una variable, incluso de tipos diferentes, tal y como veremos a continuación. La siguiente línea de código declara una variable de tipo entero: Dim i As Integer Tal y como hemos comentado, también podemos declarar en una misma línea más de una variable: Dim a, b, c As Integer En este caso, las tres variables las estamos definiendo del mismo tipo, que es el indicado al final de la declaración. En Visual Basic 2010 se pueden declarar las constantes y variables sin necesidad de indicar el tipo de datos que contendrán, pero debido a que eso no es una buena práctica, a lo largo de este curso siempre declararemos las variables y constantes con el tipo de datos adecuado a su uso. Declarar variables y asignar el valor inicial En Visual Basic 2010 también podemos inicializar una variable con un valor distinto al predeterminado, que en los tipos numéricos es un cero, en las fechas es el 1 de enero del año 1 a las doce de la madrugada (#01/01/0001 12:00:00AM#) y en la cadenas es un valor nulo (Nothing), para hacerlo, simplemente tenemos que indicar ese valor, tal como veremos es muy parecido a como se declaran las constantes. Por ejemplo: Dim a As Integer = 10 En esa misma línea podemos declarar y asignar más variables, pero todas deben estar indicados con el tipo de datos: Dim a As Integer = 10, b As Integer = 25 Por supuesto, el tipo de datos puede ser cualquiera de los tipos primitivos: Dim a As Integer = 10, b As Integer = 25, s As String = "Hola" Aunque para que el código sea más legible, y fácil de depurar, no deberíamos mezclar en una misma instrucción Dim más de un tipo de datos. El tipo de datos Char En Visual Basic 2010 podemos declarar valores de tipo Char, este tipo de datos es un character Unicode y podemos declararlo y asignarlo a un mismo tiempo. El problema con el que nos podemos encontrar es a la hora de indicar un carácter literal. Podemos convertir un valor numérico en un carácter o bien podemos convertir un carácter en su correspondiente valor numérico. Dim c As Char c = Chr(65) Dim n As Byte n = Asc(c) En Visual Basic 2010 los tipos Char se pueden asignar a variables de tipo String y se hará una conversión automática sin necesidad de utilizar funciones de conversión. Si nuestra intención es asignar un valor Char a una variable, además de la función Chr, podemos hacerlo con un literal, ese valor literal estará encerrado entre comillas dobles, (al igual que una cadena), aunque para que realmente sea un character debemos agregarle una c justo después del cierre de las comillas dobles: Dim c As Char = "A"c Aplicar Option Stict On a todo el Proyecto También podemos hacer que Option Strict funcione igual que Option Explicit, es decir, que esté activado a todo el proyecto, en este caso no tendríamos que indicarlo en cada uno de los ficheros de código que formen parte de nuestro proyecto, si bien solamente será aplicable a los que no tengan esas instrucciones, aclaremos esto último: si Option Strict (u Option Explicit) está definido de forma global al proyecto, podemos desactivarlo en cualquiera de los ficheros, para ello simplemente habría que usar esas declaraciones pero usando Off en lugar de On. De igual forma, si ya está definido globalmente y lo indicamos expresamente, no se producirá ningún error. Lo importante aquí es saber que siempre se usará el estado indicado en cada fichero, independientemente de cómo lo tengamos definido a nivel de proyecto. Desde este momento el compilador de Visual Basic se volverá estricto en todo lo relacionado a las declaraciones de variables y conversiones, tal como vemos al intentar declarar una variable sin indicar el tipo de datos. Una de las ventajas del IDE (Integrated Development Environment, entorno de desarrollo integrado) de Visual Basic 2010 es que nos avisa al momento de cualquier fallo que cometamos al escribir el código, este "pequeño" detalle, aunque alguna veces puede llegar a parecer fastidioso, nos facilita la escritura de código, ya que no tenemos que esperar a realizar la compilación para que tengamos constancia de esos fallos. Tipos Nullables Otra interesantísima característica introducida en Visual Basic 2008 y utilizable en Visual Basic 2010 que conviene conocer, es lo que se denominan tipos Nullables o anulables. Los tipos anulables no son nuevos en Visual Basic, de hecho su origen lo encontramos en Visual Studio 2005, aunque eso sí, implementando la clase Nullable(Of T). Con Visual Basic 2008 y Visual Basic 2010 no es necesario declarar ninguna clase para implementar tipos anulables dentro de nuestras aplicaciones, y podemos declararlos de forma directa. Un tipo de dato anulable nos permitirá declarar una variable que podrá tener un tipo de dato nulo. Si hemos estado atentos hasta ahora, hemos podido ver que las variables numéricas por ejemplo, se inicializan a 0. Si quisiéramos por la razón que fuera, declarar esa variable como nula para saber si en un determinado momento ha cambiado de valor o cualquier otra acción, deberíamos utilizar los tipos de datos anulables, o bien, utilizar técnicas más rudimentarias como una variable de tipo Boolean que nos permitiera saber si ha habido un cambio de valor en una variable, sin embargo, coincidirá conmigo en que el uso de un tipo de datos anulable es más natural y directo. De esta forma, podríamos trabajar con tipos de datos anulables o que los declararemos como nulos. A continuación veremos un ejemplo: Dim valor As Integer? Para acceder al valor de un tipo anulable, podríamos hacerlo de la forma habitual, ahora bien, si no sabemos si el valor es nulo o no, podríamos acceder a su valor preguntando por él mediante la propiedad HasValue. La propiedad Value nos indicará también, el valor de esa variable. Un ejemplo que aclare esta explicación es el que podemos ver a continuación: Dim valor As Integer? If Valor.HasValue Then MessageBox.Show(valor.Value) End If Otra característica de los tipos anulables es la posibilidad de utilizar la function GetValueOrDefault. Esta función nos permitirá acceder al valor de la variable si no es nulo, y al valor que le indiquemos si es nulo. Un breve ejemplo de este uso es el que se indica a continuación: Dim valor As Integer? valor = 2010 MessageBox.Show(valor.GetValueOrDefault(2012)) End If En este ejemplo, el compilador nos devolvería el valor 2010, ya que GetValueOrDefault sabe que la variable no posee un valor nulo y que por lo tanto, debe obtener el valor no nulo de la variable anulable. En el caso de que no hubiéramos dado ningún valor a la variable, la aplicación obtendría el valor 2012. Tipos anónimos Esta característica de Visual Basic 2008 y Visual Basic 2010, nos permite declarar los tipos de datos de forma implícita desde el código de nuestras aplicaciones. Un ejemplo práctico de declaración de tipos anónimos es el siguiente: Dim declaracion = New With {.Nombre = "Carlos", .Edad = 27} MessageBox.Show(String.Format("{0} tiene {1} años", _ declaracion.Nombre, declaracion.Edad)) Como podemos ver, en el ejemplo anterior hemos declarado un objeto al que no hemos indicados ningún tipo de dato concreto, pero a la hora de crear ese objeto, hemos creado implícitamente un miembro Nombre y un miembro Edad. Propiedades autoimplementadas Esta característica de Visual Basic 2010 nos permite declarar propiedades y autoimplementarlas con un valor determinado. De esta manera, podremos inicializar una propiedad con un valor determinado. Un sencillo ejemplo de uso de esta característica es el siguiente: Property Id As Integer = 0 Property NamePerson As String = "<sin nombre>" Property AgePerson As Byte = 0 En este ejemplo, se han creado tres propiedades, una de ellas de tipo Int32, otra de tipo String, y una tercera de tipo Byte. Estas propiedades están inicializadas con valores por defecto. Inicialización de colecciones Otra característica muy útil en Visual Basic es la inicialización de colecciones, que nos permite inicializar una colección de datos con valores de forma directa. La mejor forma de entender esto es viendo un ejemplo. Supongamos la siguiente interfaz en Visual Basic: Interface IPerson Property Id As Integer Property Name As String Property Age As Byte End Interface Ahora, crearemos una clase que implemente la interfaz IPerson: Public Class Estudiante Implements IPerson <DefaultValue("0")> Property Id As Integer Implements IPerson.Id Property Name As String Implements IPerson.Name Property Age As Byte Implements IPerson.Age End Class Ya tenemos la interfaz y la clase que implementa la interfaz, por lo que ahora, lo tenemos que hacer es consumir la clase Estudiante e inicializar los elementos de la colección. Un ejemplo práctico de inicialización es el que se indica a continuación: Property StudentCollection As New List(Of ... Me.StudentCollection.Add(New Estudiante Me.StudentCollection.Add(New Estudiante Me.StudentCollection.Add(New Estudiante Estudiante) With {.Id = 1, .Name = "Luisa", .Age = 25}) With {.Id = 2, .Name = "Antonio", .Age = 27}) With {.Id = 3, .Name = "Juan", .Age = 26}) Como podemos apreciar, al mismo tiempo que declaramos un nuevo objeto de tipo Estudiante, inicializamos sus propiedades con valores, de forma que asignamos esos elementos a la colección con valores directos. Enumeraciones: Constants agrupadas Una enumeración es una serie de constantes que están relacionadas entre sí. La utilidad de las enumeraciones es más manifiesta cuando queremos manejar una serie de valores constantes con nombre, es decir, podemos indicar un valor, pero en lugar de usar un literal numérico, usamos un nombre, ese nombre es al fin y al cabo, una constante que tiene un valor numérico. En Visual Basic 2010 las enumeraciones pueden ser de cualquier tipo numérico integral, incluso enteros sin signo, aunque el valor predefinido es el tipo Integer. Podemos declarar una enumeración de varias formas: 1- Sin indicar el tipo de datos, por tanto serán de tipo Integer: Enum Colores Rojo Verde Azul End Enum 2- Concretando explícitamente el tipo de datos que realmente tendrá: Enum Colores As Long Rojo Verde Azul End Enum En este segundo caso, el valor máximo que podemos asignar a los miembros de una enumeración será el que pueda contener un tipo de datos Long. 3- Indicando el atributo FlagsAttibute, (realmente no hace falta indicar el sufijo Attribute cuando usamos los atributos) de esta forma podremos usar los valores de la enumeración para indicar valores que se pueden "sumar" o complementar entre sí, pero sin perder el nombre, en breve veremos qué significa esto de "no perder el nombre". <Flags()> _ Enum Colores As Byte Rojo = 1 Verde = 2 Azul = 4 End Enum Nota: Los atributos los veremos con más detalle en otra lección de este mismo módulo. El nombre de los miembros de las enumeraciones Tanto si indicamos o no el atributo Flags a una enumeración, la podemos usar de esta forma: Dim c As Colores = Colores.Azul Or Colores.Rojo Es decir, podemos "sumar" los valores definidos en la enumeración. Antes de explicar con detalle que beneficios nos puede traer el uso de este atributo, veamos una característica de las enumeraciones. Como hemos comentado, las enumeraciones son constantes con nombres, pero en Visual Basic 2010 esta definición llega más lejos, de hecho, podemos saber "el nombre" de un valor de una enumeración, para ello tendremos que usar el método ToString, el cual se usa para convertir en una cadena cualquier valor numérico. Por ejemplo, si tenemos la siguiente asignación: Dim s As String = Colores.Azul.ToString La variable s contendrá la palabra "Azul" no el valor 4. Esto es aplicable a cualquier tipo de enumeración, se haya o no usado el atributo FlagsAttribute. Una vez aclarado este comportamiento de las enumeraciones en Visual Basic 2010, veamos que es lo que ocurre cuando sumamos valores de enumeraciones a las que hemos aplicado el atributo Flags y a las que no se lo hemos aplicado. Empecemos por este último caso. Si tenemos este código: Enum Colores As Byte Rojo = 1 Verde = 2 Azul = 4 End Enum Dim c As Colores = Colores.Azul Or Colores.Rojo Dim s As String = c.ToString El contenido de la variable s será "5", es decir, la representación numérica del valor contenido: 4 + 1, ya que el valor de la constante Azul es 4 y el de la constante Rojo es 1. Pero si ese mismo código lo usamos de esta forma (aplicando el atributo Flags a la enumeración): <Flags()> _ Enum Colores As Byte Rojo = 1 Verde = 2 Azul = 4 End Enum Dim c As Colores = Colores.Azul Or Colores.Rojo Dim s As String = c.ToString El contenido de la variable s será: "Rojo, Azul", es decir, se asignan los nombres de los miembros de la enumeración que intervienen en ese valor, no el valor "interno". Los valores de una enumeración no son simples números Como hemos comentado, los miembros de las enumeraciones realmente son valores de un tipo de datos entero. Los tipos subyacentes posibles de una enumeración Por tanto, podemos pensar que podemos usar cualquier valor para asignar a una variable declarada como una enumeración, al menos si ese valor está dentro del rango adecuado. En Visual Basic 2010 esto no es posible, al menos si lo hacemos de forma "directa" y con Option Strict conectado, ya que recibiremos un error indicándonos que no podemos convertir, por ejemplo, un valor entero en un valor del tipo de la enumeración. En la figura siguiente podemos ver ese error al intentar asignar el valor 3 a una variable del tipo Colores (definida con el tipo predeterminado Integer). Error al asignar un valor "normal" a una variable del tipo Colores El error nos indica que no podemos realizar esa asignación, pero el entorno integrado de Visual Studio 2010 también nos ofrece alternativas para que ese error no se produzca, esa ayuda se obtiene presionando en el signo de admiración que tenemos justo donde está el cursor del mouse, pero no solo nos dice cómo corregirlo, sino que también nos da la posibilidad de que el propio IDE se encargue de corregirlo, tal como podemos apreciar en la figura anterior. Opciones de corrección de errores Lo único que tendríamos que hacer es presionar en la sugerencia de corrección, que en este caso es la única que hay, pero en otros casos pueden ser varias las opciones y tendríamos que elegir la que creamos adecuada. El código final (una vez corregido) quedaría de la siguiente forma: Dim c As Colores = CType(3, Colores) CType es una de las formas que nos ofrece Visual Basic 2010 de hacer conversiones entre diferentes tipos de datos, en este caso convertimos un valor entero en uno del tipo Colores. Si compilamos y ejecutamos la aplicación, ésta funcionará correctamente. Aunque sabemos que es posible que usando CType no asignemos un valor dentro del rango permitido. En este caso, el valor 3 podríamos darlo por bueno, ya que es la suma de 1 y 2 (Rojo y Verde), pero ¿que pasaría si el valor asignado es, por ejemplo, 15? En teoría no deberíamos permitirlo. Estas validaciones podemos hacerlas de dos formas: 1- Con la clásica solución de comprobar el valor indicado con todos los valores posibles. 2- Usando funciones específicas del tipo Enum. Aunque en este último caso, solo podremos comprobar los valores definidos en la enumeración. En el siguiente Ejemplo podemos hacer esa comprobación. Sub mostrarColor(ByVal c As Colores) ' comprobar si el valor indicado es correcto ' si no está¡ definido, usar el valor Azul If [Enum].IsDefined(GetType(Colores), c) = False Then c = Colores.Azul End If Console.WriteLine("El color es {0}", c) End Sub Este código lo que hace es comprobar si el tipo de datos Colores tiene definido el valor contenido en la variable c, en caso de que no sea así, usamos un valor predeterminado. Nota: La función IsDefined sólo comprueba los valores que se han definido en la enumeración, no las posibles combinaciones que podemos conseguir sumando cada uno de sus miembros, incluso aunque hayamos usado el atributo FlagsAttribute. Arrays (matrices) Los arrays (o matrices) nos permitirán agrupar valores que de alguna forma queremos que estén relacionados entre si. Comentario: Esta es la definición usada en la documentación de Visual Studio sobre qué es una matriz: "Una matriz es una estructura de datos que contiene una serie de variables denominadas elementos de la matriz." Aclaramos este punto, porque la traducción en castellano de Array puede variar dependiendo del país (arreglos, matrices, etc). Aquí utilizaremos la usada a lo largo de la documentación de Visual Studio. Declarar arrays En C# los arrays se definen indicando un par de corchetes en el tipo de datos. En Visual Basic 2010 la declaración de un array la haremos usando un par de paréntesis en el nombre de la variable o del tipo, en el siguiente Ejemplo declaramos un array de tipo String llamado nombres: Dim nombres() As String Dim nombres As String() Estas dos formas son equivalentes. También podemos indicar el número de elementos que contendrá el array o matriz: Dim nombres(10) As String Pero solo podemos hacerlo en el nombre, si esa cantidad de elementos lo indicamos en el tipo, recibiremos un error indicándonos que "los límites de la matriz no pueden aparecer en los especificadores del tipo". Al declarar un array indicando el número de elementos, como es el caso anterior, lo que estamos definiendo es un array de 11 elementos: desde cero hasta 10, ya que en Visual Basic 2010, al igual que en el resto de lenguajes de .NET, todos los arrays deben tener como índice inferior el valor cero. Para que quede claro que el límite inferior debe ser cero, en Visual Basic 2010 podemos usar la instrucción 0 To para indicar el valor máximo del índice superior, ya que, tal como podemos comprobar si vemos 0 To 10, quedará claro que nuestra intención es declarar un array con 11 elementos, o al menos nuestro código resultará más legible: Dim nombres(0 To 10) As String Declarar e inicializar un array En Visual Basic 2010 también podemos inicializar un array al declararlo, para ello debemos poner los valores a asignar dentro de un par de llaves, tal como vemos en el siguiente ejemplo: Dim nombres() As String = {"Pepe", "Juan", "Luisa"} Con el código anterior estamos creando un array de tipo String con tres valores cuyos índices van de cero a dos. En este caso, cuando iniciamos el array al declararlo, no debemos indicar el número de elementos que tendrá ese array, ya que ese valor lo averiguará el compilador cuando haga la asignación. Tampoco es válido indicar el número de elementos que queremos que tenga y solo asignarle unos cuantos menos (o más), ya que se producirá un error en tiempo de compilación. Si el array es bidimensional (o con más dimensiones), también podemos inicializarlos al declararlo, pero en este caso debemos usar doble juego de llaves: Dim nombres(,) As String = {{"Juan", "Pepe"}, {"Ana", "Eva"}} En este código tendríamos un array bidimensional con los siguientes valores: nombres(0,0)= Juan nombres(0,1)= Pepe nombres(1,0)= Ana nombres(1,1)= Eva Como podemos ver en la declaración anterior, si definimos arrays con más de una dimensión, debemos indicarlas usando una coma para separar cada dimensión, o lo que es más fácil de recordar: usando una coma menos del número de dimensiones que tendrá el array. En los valores a asignar, usaremos las llaves encerradas en otras llaves, según el número de dimensiones. Aunque, la verdad, es que hay algunas veces hay que hacer un gran esfuerzo mental para asociar los elementos con los índices que tendrán en el array, por tanto, algunas veces puede que resulte más legible si indentamos o agrupamos esas asignaciones, tal como vemos en el siguiente código: Dim nomTri(,,) As String = _ {_ {{"Juan", "Pepe"}, {"Luisa", "Eva"}}, _ {{"A", "B"}, {"C", "D"}} _ } Console.WriteLine(nomTri(0, 0, 0)) ' Juan Console.WriteLine(nomTri(0, 0, 1)) ' Pepe Console.WriteLine(nomTri(0, 1, 0)) ' Luisa Console.WriteLine(nomTri(0, 1, 1)) ' Eva Console.WriteLine(nomTri(1, 0, 0)) ' A Console.WriteLine(nomTri(1, 0, 1)) ' B Console.WriteLine(nomTri(1, 1, 0)) ' C Console.WriteLine(nomTri(1, 1, 1)) ' D Tal como podemos comprobar, asi es más legible. Por suerte tenemos el carácter del guión bajo para continuar líneas de código, aunque esto ya no es necesario como hemos podido ver al principio de este tutorial. Cambiar el tamaño de un array Para cambiar el tamaño de un array, usaremos la instrucción ReDim, esta instrucción solo la podemos usar para cambiar el tamaño de un array previamente declarado, no para declarer un array, ya que siempre hay que declarar previamente los arrays antes de cambiarles el tamaño. Dim nombres() As String ... ReDim nombres(3) nombres(0) = "Juan" nombres(1) = "Pepe" La mayor utilidad de esta instrucción, es que podemos cambiar el tamaño de un array y mantener los valores que tuviera anteriormente, para lograrlo debemos usar ReDim Preserve. ReDim Preserve nombres(3) nombres(2) = "Ana" nombres(3) = "Eva" En este ejemplo, los valores que ya tuviera el array nombres, se seguirían manteniendo, y se asignarían los nuevos. Si bien tanto ReDim como ReDim Preserve se pueden usar en arrays de cualquier número de dimensiones, en los arrays de más de una dimensión solamente podemos cambiar el tamaño de la última dimensión. Eliminar el contenido de un array Una vez que hemos declarado un array y le hemos asignado valores, es posible que nos interese eliminar esos valores de la memoria, para lograrlo, podemos hacerlo de tres formas: 1.Redimensionando el array indicando que tiene cero elementos, aunque en el mejor de los casos, si no estamos trabajando con arrays de más de una dimensión, tendríamos un array de un elemento, ya que, como hemos comentado anteriormente, los arrays de .NET el índice inferior es cero. 2.Usar la instrucción Erase. La instrucción Erase elimina totalmente el array de la memoria. 3.Asignar un valor Nothing al array. Esto funciona en Visual Basic 2010 porque los arrays realmente son tipos por referencia. Los arrays son tipos por referencia Como acabamos de ver, en Visual Basic 2010 los arrays son tipos por referencia, y tal como comentamos anteriormente, los tipos por referencia realmente lo que contienen son una referencia a los datos reales no los datos propiamente dichos. ¿Cual es el problema? Veámoslo con un ejemplo y así lo tendremos más claro. Dim nombres() As String = {"Juan", "Pepe", "Ana", "Eva"} Dim otros() As String otros = nombres nombres(0) = "Antonio" En este ejemplo definimos el array nombres y le asignamos cuatro valores. A continuación definimos otro array llamado otros y le asignamos lo que tiene nombres. Por ultimo asignamos un nuevo valor al elemento cero del array nombres. Si mostramos el contenido de ambos arrays nos daremos cuenta de que realmente solo existe una copia de los datos en la memoria, y tanto nombres(0) como otros(0) contienen el nombre "Antonio". ¿Qué ha ocurrido? Que debido a que los arrays son tipos por referencia, solamente existe una copia de los datos y tanto la variable nombres como la variable otros lo que contienen es una referencia (o puntero) a los datos. Si realmente queremos tener copias independientes, debemos hacer una copia del array nombres en el array otros, esto es fácil de hacer si usamos el método CopyTo. Éste método existe en todos los arrays y nos permite copiar un array en otro empezando por el índice que indiquemos. El único requisito es que el array de destino debe estar inicializado y tener espacio suficiente para contener los elementos que queremos copiar. En el siguiente código de ejemplo hacemos una copia del contenido del array nombres en el array otros, de esta forma, el cambio realizado en el elemento cero de nombres no afecta al del array otros. Dim nombres() As String = {"Juan", "Pepe", "Ana", "Eva"} Dim otros() As String ReDim otros(nombres.Length) nombres.CopyTo(otros, 0) nombres(0) = "Antonio" Además del método CopyTo, los arrays tienen otros miembros que nos pueden ser de utilidad, como por ejemplo la propiedad Length usada en el ejemplo para saber cuantos elementos tiene el array nombres. Para averiguar el número de elementos de un array, (realmente el índice superior), podemos usar la función UBound. También podemos usar la función LBound, (que sirve para averiguar el índice inferior de un array), aunque no tiene ningún sentido en Visual Basic 2010, ya que, como hemos comentado, todos los arrays siempre tienen un valor cero como índice inferior. Para finalizar este tema, solo nos queda por decir, que los arrays de Visual Basic 2010 realmente son tipos de datos derivados de la clase Array y por tanto disponen de todos los miembros definidos en esa clase, aunque de esto hablaremos en la próxima lección, en la que también tendremos la oportunidad de profundizar un poco más en los tipos por referencia y en como podemos definir nuestros propios tipos de datos, tanto por referencia como por valor. Literales de arrays (o matrices) Otra característica de Visual Basic 2010 es la aplicación de los denominados literales de arrays o matrices. La idea es que Visual Basic infiera por nosotros el tipo de dato de forma directa. Esto representa una buena práctica aunque nos impide hacer cosas que antes podíamos hacer sin complicaciones. Por ejemplo, pensemos en el siguiente ejemplo de Visual Basic 2008: Dim ejemploMatriz() = {2009, 2010, 2011, 2012} En este ejemplo, habremos creado una matriz de 4 elementos. Sin embargo, podríamos cambiar uno de sus elementos a otro valor de diferente tipo, como por ejemplo: ejemploMatriz(1) = "s" De esta manera, tendremos un resultado: 2009, "s", 2011, 2012. Esto es así, porque la matriz ejemploMatriz es de tipo Object. Sin embargo, esto ha cambiado. Ahora, podemos declarar literales de matrices, hacienda que estas matrices se declaren de acuerdo al tipo de dato declarado, es decir, infiriendo el tipo de dato en la declaración. Un ejemplo de este uso es el siguiente: Dim ejemploInteger = {2009, 2010, 2011, 2012} En este ejemplo, si tratamos de hacer lo que antes intentábamos mediante la siguiente intrucción: ejemploInteger(1) = "s" La aplicación nos devolverá un error en tiempo de ejecución, ya que la matriz estará inferida por defecto como tipo Integer, y estaremos intentado asignar un valor String a una matriz de tipo Integer. Clases y estructuras Bien pues este tema es el mas central de este libro, en esta lección veremos cómo podemos crear nuestros propios tipos de datos, tanto por valor como por referencia. También tendremos ocasión de ver los distintos niveles de accesibilidad que podemos aplicar a los tipos, así como a los distintos miembros de esos tipos de datos. De los distintos miembros que podemos definir en nuestros tipos, nos centraremos en las propiedades para ver en detalle los cambios que han sufrido con respecto a VB6. También veremos temas relacionados con la programación orientada a objetos (POO) en general y de forma particular los que atañen a las interfaces. Tal como vimos en la lección anterior, los tipos de datos se dividen en dos grupos: tipos por valor y tipos por referencia. Los tipos por referencia realmente son clases, de la cuales debemos crear una instancia para poder usarlas, esa instancia o copia, se crea siempre en la memoria lejana (heap) y las variables lo único que contienen es una referencia a la dirección de memoria en la que el CLR (Common Language Runtime, motor en tiempo de ejecución de .NET), ha almacenado el objeto recién creado. En .NET Framework todo es de una forma u otra una clase, por tanto Visual Basic 2010 también depende de la creación de clases para su funcionamiento, ya que todo el código que escribamos debemos hacerlo dentro de una clase. Antes de entrar en detalles sintácticos, veamos la importancia que tienen las clases en .NET Framework y como repercuten en las que podamos definer nosotros usando Visual Basic 2010. Las clases: el corazón de .NET Framework Prácticamente todo lo que podemos hacer en .NET Framework lo hacemos mediante clases. La librería de clases de .NET Framework es precisamente el corazón del propio .NET, en esa librería de clases está todo lo que podemos hacer dentro de este marco de programación; para prácticamente cualquier tarea que queramos realizar existen clases, y si no existen, las podemos definir nosotros mismos, bien ampliando la funcionalidad de alguna clase existente mediante la herencia, bien implementando algún tipo de funcionalidad previamente definida o simplemente creándolas desde cero. La herencia: Característica principal de la Programación Orientada a Objetos El concepto de Programación Orientada a Objetos (POO) es algo intrínseco al propio .NET Framework, por tanto es una característica que todos los lenguajes basados en este "marco de trabajo" tienen de forma predeterminada, entre ellos el Visual Basic 2010. De las características principales de la POO tenemos que destacar la herencia, que en breve podemos definir como una característica que nos permite ampliar la funcionalidad de una clase existente sin perder la que ya tuviera previamente. Gracias a la herencia, podemos crear una nueva clase que se derive de otra, esta nueva clase puede cambiar el comportamiento de la clase base y/o ampliarlo, de esta forma podemos adaptar la clase, llamémosla, original para adaptarla a nuestras necesidades. El tipo de herencia que .NET Framework soporta es la herencia simple, es decir, solo podemos usar una clase como base de la nueva, si bien, como veremos más adelante, podemos agregar múltiple funcionalidad a nuestra nueva clase. Encapsulación y Polimorfismo La encapsulación y el polimorfismo son otras dos características de la programación orientada a objetos. La encapsulación nos permite abstraer la forma que tiene de actuar una clase sobre los datos que contiene o manipula, para poder lograrlo se exponen como parte de la clase los métodos y propiedades necesarios para que podamos manejar esos datos sin tener que preocuparnos cómo se realiza dicha manipulación. El polimorfismo es una característica que nos permite realizar ciertas acciones o acceder a la información de los datos contenidos en una clase de forma semianónima, al menos en el sentido de que no tenemos porqué saber sobre que tipo objeto realizamos la acción, ya que lo único que nos debe preocupar es que podemos hacerlo, por la sencilla razón de que estamos usando ciertos mecanismos que siguen unas normas que están adoptadas por la clase. Object: La clase base de todas las clases de .NET Todas las clases de .NET se derivan de la clase Object, es decir, lo indiquemos o no, cualquier clase que definamos tendrá el comportamiento heredado de esa clase. El uso de la clase Object como base del resto de las clases de .NET es la única excepción a la herencia simple soportada por .NET, ya que de forma implícita, todas las clases de .NET se derivan de la clase Object independientemente de que estén derivadas de cualquier otra. Definir una clase En Visual Basic 2010, todo el código que queramos escribir, lo tendremos que hacer en un fichero con la extensión .vb, dentro de ese fichero es donde escribiremos nuestro código, el cual, tal como dijimos anteriormente siempre estará incluido dentro de una clase, aunque un fichero de código de VB puede contener una o más clases, es decir, no está limitado a una clase por fichero. En Visual Basic 2010 las clases se definen usando la palabra clave Class seguida del nombre de la clase, esa definición acaba indicándolo con End Class. En el siguiente ejemplo definimos una clase llamada Cliente que tiene dos campos públicos. Class Cliente Public Nombre As String Public Apellidos As String End Class Una vez definida la clase podemos agregar los elementos (o miembros) que creamos conveniente. Una clase especial: Module En Visual Basic 2010 también podemos definir una clase especial llamada Module, este tipo de clase, como veremos, tiene un tratamiento especial. La definición se hace usando la instrucción Module seguida del nombre a usar y acaba con End Module. Cualquier miembro definido en un Module siempre estará accesible en todo el proyecto y para usarlos no tendremos que crear ningún objeto en memoria. Las clases definidas con la palabra clave Module realmente equivalen a las clases en las que todos los miembros están compartidos y por tanto siempre disponibles a toda la aplicación. De todos estos conceptos nos ocuparemos en las siguientes lecciones, pero es necesario explicar que existe este tipo de clase ya que será el tipo de datos que el IDE de Visual Basic 2010 usará al crear aplicaciones del tipo consola, ya que ese será el tipo de proyecto que crearemos para practicar con el código mostrado en este primer módulo. Los miembros de una clase Una clase puede contener cualquiera de estos elementos (miembros): Enumeraciones Campos Métodos (funciones o procedimientos) Propiedades Eventos Las enumeraciones, como vimos en la lección anterior, podemos usarlas para definir valores constantes relacionados, por ejemplo para indicar los valores posibles de cualquier "característica" de la clase. Los campos son variables usadas para mantener los datos que la clase manipulará. Los métodos son las acciones que la clase puede realizar, normalmente esas acciones serán sobre los datos que contiene. Dependiendo de que el método devuelva o no un valor, podemos usar métodos de tipo Function o de tipo Sub respectivamente. Las propiedades son las "características" de las clases y la forma de acceder "públicamente" a los datos que contiene. Por ejemplo, podemos considerar que el nombre y los apellidos de un cliente son dos características del cliente. Los eventos son mensajes que la clase puede enviar para informar que algo está ocurriendo en la clase. Características de los métodos y propiedades Accesibilidad, ámbito y miembros compartidos Aunque estos temas los veremos en breve con más detalle, para poder comprender mejor las características de los miembros de una clase (o cualquier tipo que definamos), daremos un pequeño adelanto sobre estas características que podemos aplicar a los elementos que definamos. Accesibilidad y ámbito son dos conceptos que están estrechamente relacionados. Aunque en la práctica tienen el mismo significado, ya que lo que representan es la "cobertura" o alcance que tienen los miembros de las clases e incluso de las mismas clases que definamos. Si bien cada uno de ellos tienen su propia "semántica", tal como podemos ver a continuación: Ámbito Es el alcance que la definición de un miembro o tipo puede tener. Es decir, cómo podemos acceder a ese elemento y desde dónde podemos accederlo. El ámbito de un elemento de código está restringido por el "sitio" en el que lo hemos declarado. Estos sitios pueden ser: Ámbito de bloque: Disponible únicamente en el bloque de código en el que se ha declarado. Ámbito de procedimiento: Disponible únicamente dentro del procedimiento en el que se ha declarado. Ámbito de módulo: Disponible en todo el código del módulo, la clase o la estructura donde se ha declarado. Ámbito de espacio de nombres: Disponible en todo el código del espacio de nombres. Accesibilidad A los distintos elementos de nuestro código (ya sean clases o miembros de las clases) podemos darle diferentes tipos de accesibilidad. Estos tipos de "acceso" dependerán del ámbito que queramos que tengan, es decir, desde dónde podremos accederlos. Los modificadores de accesibilidad son: Public: Acceso no restringido. Protected: Acceso limitado a la clase contenedora o a los tipos derivados de esta clase. Friend: Acceso limitado al proyecto actual. Protected Friend: Acceso limitado al proyecto actual o a los tipos derivados de la clase contenedora. Private: Acceso limitado al tipo contenedor. Por ejemplo, podemos declarar miembros privados a una clase, en ese caso, dichos miembros solamente los podremos accede desde la propia clase, pero no desde fuera de ella. Miembros compartidos Por otro lado, los miembros compartidos de una clase o tipo, son elementos que no pertenecen a una instancia o copia en memoria particular, sino que pertenecen al propio tipo y por tanto siempre están accesibles o disponibles, dentro del nivel del ámbito y accesibilidad que les hayamos aplicado, y su tiempo de vida es el mismo que el de la aplicación. Del ámbito, la accesibilidad y los miembros compartidos nos ocuparemos con más detalle en una lección posterior, donde veremos ciertas peculiaridades, como puede ser la limitación del ámbito de un miembro que aparentemente tiene una accesibilidad no restringida. Parámetros específicos y parámetros opcionales En Visual Basic 2010, tanto los miembros de una clase, (funciones y métodos Sub), como las propiedades pueden recibir parámetros. Esos parámetros pueden estar explícitamente declarados, de forma que podamos indicar cuantos argumentos tendremos que pasar al método, también podemos declarer parámetros opcionales, que son parámetros que no hace falta indicar al llamar a la función o propiedad, y que siempre tendrán un valor predeterminado, el cual se usará en caso de que no lo indiquemos. Además de los parámetros específicos y opcionales, podemos usar un array de parámetros opcionales, en los que se puede indicar un número variable de argumentos al llamar a la función que los define, esto lo veremos en la siguiente sección. * Sobre parámetros y argumentos Para clarificar las cosas, queremos decir que los parámetros son los definidos en la función, mientras que los argumentos son los "parámetros" que pasamos a esa función cuando la utilizamos desde nuestro código. Con los parámetros opcionales lo que conseguimos es permitir que el usuario no tenga que introducir todos los parámetros, sino solo los que realmente necesite, del resto, (los no especificados), se usará el valor predeterminado que hayamos indicado, porque una de las "restricciones" de este tipo de parámetros, es que siempre debemos indicar también el valor por defecto que debemos usar en caso de que no se especifique. Veamos unos ejemplo para aclarar nuestras ideas: Function Suma(n1 As Integer, Optional n2 As Integer = 15) As Integer Suma = n1 + n2 End Function En este primer ejemplo, el primer parámetro es obligatorio (siempre debemos indicarlo) y el segundo es opcional, si no se indica al llamar a esta función, se usará el valor 15 que es el predeterminado. Para llamar a esta función, lo podemos hacer de estas tres formas: ' 1- indicando los dos parámetros (el resultado será 4= 1 + 3) t = Suma(1, 3) ' 2- Indicando solamente el primer parámetro (el resultado será 16= 1 + 15) t = Suma(1) ' 3- Indicando los dos parámetros, pero en el opcional usamos el nombre t = Suma(1, n2:= 9) El tercer ejemplo solamente tiene utilidad si hay más de un parámetro opcional. Los parámetros opcionales deben aparecer en la lista de parámetros del método, después de los "obligatorios" En el caso hipotético y no recomendable de que no estemos usando Option Strict On, tanto los parámetros normales como los opcionales los podemos indicar sin el tipo de datos, pero si en alguno de ellos especificamos el tipo, debemos hacerlo en todos. Array de parámetros opcionales (ParamArray) En cuanto al uso de ParamArray, este tipo de parámetro opcional nos permite indicar un número indeterminado de parámetros, en Visual Basic 2010 siempre debe ser una array e internamente se trata como un array normal y corriente, es decir, dentro del método o propiedad se accede a él como si de un array se tratara... entre otras cosas, ¡porque es un array! Si tenemos activado Option Strict, el array usado con ParamArray debe ser de un tipo en concreto, si queremos que acepte cualquier tipo de datos, lo podemos declarar con el tipo Object. Si por cualquier razón necesitamos pasar otros valores que no sean de un tipo en concreto, por ejemplo, además de valores "normales" queremos pasar un array, podemos desactivar Option Strict para hacerlo fácil. Por ejemplo, si queremos hacer algo como esto: Function Suma(ParamArray n() As Object) As Integer Dim total As Integer ' For i As Integer = 0 To n.Length - 1 If IsArray(n(i)) Then For j As Integer = 0 To n(i).Length - 1 total += n(i)(j) Next Else total += n(i) End If Next Return total End Function ' Para usarlo: Dim t As Integer Dim a(2) As Integer = {1, 2, 3} t = Suma(a, 4, 5, 6) Console.WriteLine(t) Tal como vemos, el primer argumento que pasamos a la función Suma es un array, después pasamos tres valores enteros normales. El resultado de ejecutar ese código será el valor 21, como es de esperar. Nota: Como Visual Basic 2010 no sabe que tipo contiene n(i), al escribir este código, no nos informará de que ese "objeto" tiene una propiedad llamada Length. Pero como no debemos "acostumbrarnos" a desactivar Option Strict, vamos a ver el código que tendríamos que usar para que también acepte un array como parte de los argumentos indicados al llamar a la función. Function Suma(ByVal ParamArray n() As Object) As Integer Dim total As Integer ' For i As Integer = 0 To n.Length - 1 If IsArray(n(i)) Then For j As Integer = 0 To CType(n(i), Integer()).Length - 1 total += CType(n(i), Integer())(j) Next Else total += CInt(n(i)) End If Next Return total End Function ' Para usarlo: Dim t As Integer Dim a(2) As Integer = {1, 2, 3} t = Suma(a, 4, 5, 6) Console.WriteLine(t) Como podemos comprobar, al tener Option Strict activado, debemos hacer una conversión explícita del array a uno de un tipo en concreto, como es natural, en este código estamos suponiendo que el array pasado como argumento a la función es de tipo Integer, en caso de que no lo fuera, recibiríamos un error en tiempo de ejecución. Para comprobar si el contenido de n(i) es un array, hemos usado la función IsArray definida en el espacio de nombres Microsoft VisualBasic (que por defecto utilizan todas las aplicaciones de Visual Basic 2010), pero también lo podríamos haber hecho más al "estilo .NET", ya que, como sabemos todos los arrays de .NET realmente se derivan de la clase Array: If TypeOf n(i) Is Array Then Nota: Cuando queramos usar ParamArray para recibir un array de parámetros opcionales, esta instrucción debe ser la última de la lista de parámetros de la función (método). Tampoco se permite tener parámetros opcionales y ParamArray en la misma función. Sobrecarga de métodos y propiedades La sobrecarga de funciones (realmente de métodos y propiedades), es una característica que nos permite tener una misma función con diferentes tipos de parámetros, ya sea en número o en tipo. Supongamos que queremos tener dos funciones (o más) que nos permitan hacer operaciones con diferentes tipos de datos, y que, según el tipo de datos usado, el valor que devuelva sea de ese mismo tipo. En este ejemplo, tenemos dos funciones que se llaman igual pero una recibe valores de tipo entero y la otra de tipo decimal: Function Suma(n1 As Integer, n2 As Integer) As Integer Return n1 + n2 End Function Function Suma(n1 As Double, n2 As Double) As Double Return n1 + n2 End Function Como podemos comprobar las dos funciones tienen el mismo nombre, pero tanto una como otra reciben parámetros de tipos diferentes. Con Visual Basic 2010 podemos sobrecargar funciones, pero lo interesante no es que podamos hacerlo, sino cómo podemos usar esas funciones. En el código anterior tenemos dos funciones llamadas Suma, la primera acepta dos parámetros de tipo Integer y la segunda de tipo Double. Lo interesante es que cuando queramos usarlas, no tenemos que preocuparnos de cual vamos a usar, ya que será el compilador el que decida la más adecuada al código que usemos, por ejemplo: ' En este caso, se usará la que recibe dos valores enteros Console.WriteLine(Suma(10, 22) ) ' En este caso se usará la que recibe valores de tipo Double Console.WriteLine(Suma(10.5, 22) El compilador de Visual Basic 2010 es el que decide que función usar, esa decisión la toma a partir de los tipos de parámetros que hayamos indicado. En el segundo ejemplo de uso, el que mejor coincide es el de los dos parámetros de tipo Double. También podemos tener sobrecarga usando una cantidad diferente de parámetros, aunque éstos sean del mismo tipo. Por ejemplo, podemos añadir esta declaración al código anterior sin que exista ningún tipo de error, ya que esta nueva function recibe tres parámetros en lugar de dos: Function Suma(n1 As Integer, n2 As Integer, n3 As Integer) As Integer Return n1 + n2 + n3 End Function Por tanto, cuando el compilador se encuentre con una llamada a la función Suma en la que se usen tres parámetros, intentará usar esta última. Nota! Para que exista sobrecarga, la diferencia debe estar en el número o en el tipo de los parámetros, no en el tipo del valor devuelto. Cuando, desde el IDE de Visual Basic 2010, queremos usar los métodos sobrecargados, nos mostrará una lista de opciones indicándonos las posibilidades de sobrecarga que existen y entre las que podemos elegir. Lista de parámetros soportados por un método Cuando utilicemos parámetros opcionales debemos tener en cuenta que puede que el compilador nos muestre un error, ya que es posible que esa función que declara parámetros opcionales entre en conflicto con una "sobrecargada". Por ejemplo: Function Suma(n1 As Integer, Optional n2 As Integer = 33) As Integer Return n1 + n2 End Function Si tenemos esta declaración además de las anteriores, el programa no compilará, ya que si hacemos una llamada a la function Suma con dos parámetros enteros, el compilador no sabrá si usar esta última o la primera que declaramos, por tanto producirá un error. Parámetros por valor y parámetros por referencia Al igual que tenemos dos tipos de datos diferentes, en los parámetros de las funciones también podemos tenerlos, para ello tendremos que usar ByVal o ByRef para indicar al compilador cómo debe tratar a los parámetros. Cuando un parámetro es por valor (ByVal), el runtime antes de llamar a la función hace una copia de ese parámetro y pasa la copia a la función, por tanto cualquier cambio que hagamos a ese parámetro dentro de la función no afectará al valor usado "externamente". En el caso de que el parámetro sea por referencia (ByRef), el compilador pasa una referencia que apunta a la dirección de memoria en la que están los datos, por tanto si realizamos cambios dentro de la función, ese cambio si que se verá reflejado en el parámetro usado al llamar a la función. Hay que tener en cuenta que si pasamos un objeto a una función, da igual que lo declaremos por valor o por referencia, ya que en ambos casos se pasa una referencia a la dirección de memoria en la que están los datos, porque, como sabemos, las variables de los tipos por referencia siempre contienen una referencia a los datos, no los datos en sí. Cuando en Visual Basic 2010 usamos parámetros en los que no se indica si es por valor (ByVal) o por referencia (ByRef), serán tratados como parámetros por valor. Parámetros opcionales de tipo Nullable En el tradicional Visual Basic, podíamos crear métodos y funciones con parámetros opcionales. Esta característica fue agregada en Visual Basic, y demandada por la comunidad de desarrolladores de C#, ya que en determinadas situaciones, puede resultar realmente útil. De esta manera, hacer lo siguiente en Visual Basic 2008 es completamente válido: Private Function Sumar(Optional ByVal x As Integer = Nothing, Optional ByVal y As Integer = Nothing)As Integer x = IIf(IsNothing(x), 0, x) y = IIf(IsNothing(y), 0, y) Return x + y End Function Podríamos entonces llamar a esa función de la siguiente manera: MessageBox.Show(Sumar(3).ToString()) Función que nos devolvería el valor 3, siendo la suma, 3 + 0, y siendo 3 el valor de x. Ahora bien, en Visual Basic 2010 podemos indicar parámetros opcionales, pero de tipo Nullable. Su funcionamiento es el mismo, con la salvedad de utilizar la variable como variable de tipo Nullable (en el apartado de tipos Nullable se explicaba como funcionaban). Un ejemplo práctico de como funcionan y como utilizar este tipo de parámetros es el que se indica a continuación: Private Function Sumar(Optional ByVal x As Integer? = Nothing, Optional ByVal y As Integer? = Nothing)As Integer x = IIf(IsNothing(x), 0, x) y = IIf(IsNothing(y), 0, y) Return x + y End Function Para ejecutar el método, lanzaremos el mismo procedimiento de ejecución: MessageBox.Show(Sumar(3).ToString()) El resultado que obtenemos en este caso, será el mismo que vimos anteriormente, es decir, el valor 3, pero intente pensar que este es un ejemplo muy básico, y que los tipos Nullable nos permiten indicar valores que no están inicializados y en base a ese valor, realizar una u otra acción. Declarar primero la variable y después instanciarla Lo primero que tenemos que hacer es declarar una variable del tipo que queremos instanciar, esto lo hacemos de la misma forma que con cualquier otro tipo de datos: Dim c As Cliente Con esta línea de código lo que estamos indicando a Visual Basic es que tenemos intención de usar una variable llamada c para acceder a una clase de tipo Cliente. Esa variable, cuando llegue el momento de usarla, sabrá todo lo que hay que saber sobre una clase Cliente, pero hasta que no tenga una "referencia" a un objeto de ese tipo no podremos usarla. La asignación de una referencia a un objeto Cliente la haremos usando la instrucción New seguida del nombre de la clase: c = New Cliente A partir de este momento, la variable c tiene acceso a un nuevo objeto del tipo Cliente, por tanto podremos usarla para asignarle valores y usar cualquiera de los miembros que ese tipo de datos contenga: c.Nombre = "Antonio" c.Apellidos = "Ruiz Rodríguez" Declarar y asignar en un solo paso Con las clases o tipos por referencia también podemos declarar una variable y al mismo tiempo asignarle un nuevo objeto: Dim c As New Cliente O también: Dim c As Cliente = New Cliente Las dos formas producen el mismo resultado, por tanto es recomendable usar la primera. El constructor: El punto de inicio de una clase Cada vez que creamos un nuevo objeto en memoria estamos llamando al constructor de la clase. En Visual Basic 2010 el constructor es un método de tipo Sub llamado New. En el constructor de una clase podemos incluir el código que creamos conveniente, pero realmente solamente deberíamos incluir el que realice algún tipo de inicialización, en caso de que no necesitemos realizar ningún tipo de inicialización, no es necesario definir el constructor, ya que el propio compilador lo hará por nosotros. Esto es así porque todas las clases deben implementar un constructor, por tanto si nosotros no lo definimos, lo hará el compilador de Visual Basic 2010. Si nuestra clase Cliente tiene un campo para almacenar la fecha de creación del objeto podemos hacer algo como esto: Class Cliente Public Nombre As String Public Apellidos As String Public FechaCreacion As Date ' Public Sub New() FechaCreacion = Date.Now End Sub End Class De esta forma podemos crear un nuevo Cliente y acto seguido comprobar el valor del campo FechaCreacion para saber la fecha de creación del objeto. un campo para almacenar la fecha de creación del objeto podemos hacer algo como esto: Class Cliente Public Nombre As String Public Apellidos As String Public FechaCreacion As Date ' Public Sub New() FechaCreacion = Date.Now End Sub End Class De esta forma podemos crear un nuevo Cliente y acto seguido comprobar el valor del campo FechaCreacion para saber la fecha de creación del objeto. En los constructores también podemos hacer las inicializaciones que, por ejemplo permitan a la clase a conectarse con una base de datos, abrir un fichero o cargar una imagen gráfica, etc. Constructores parametrizados De la misma forma que podemos tener métodos y propiedades sobrecargadas, también podemos tener constructores sobrecargados, ya que debemos recordar que en Visual Basic 2010, un constructor realmente es un método de tipo Sub, y como todos los métodos y propiedades de Visual Basic 2010, también admite la sobrecarga. La ventaja de tener constructores que admitan parámetros es que podemos crear nuevos objetos indicando algún parámetro, por ejemplo un fichero a abrir o, en el caso de la clase Cliente, podemos indicar el nombre y apellidos del cliente o cualquier otro dato que creamos conveniente. Para comprobarlo, podemos ampliar la clase definida anteriormente para que también acepte la creación de nuevos objetos indicando el nombre y los apellidos del cliente. Class Cliente Public Nombre As String Public Apellidos As String Public FechaCreacion As Date ' Public Sub New() FechaCreacion = Date.Now End Sub ' Public Sub New(elNombre As String, losApellidos As String) Nombre = elNombre Apellidos = losApellidos FechaCreacion = Date.Now End Sub End Class Teniendo esta declaración de la clase Cliente, podemos crear nuevos clientes de dos formas: Dim c1 As New Cliente Dim c2 As New Cliente("Jose", "Sánchez") Como podemos comprobar, en ciertos casos es más intuitiva la segunda forma de crear objetos del tipo Cliente, además de que así nos ahorramos de tener que asignar individualmente los campos Nombre y Apellidos. Esta declaración de la clase Cliente la podríamos haber hecho de una forma diferente. Por un lado tenemos un constructor "normal" (no recibe parámetros) en el que asignamos la fecha de creación y por otro el constructor que recibe los datos del nombre y apellidos. Por tanto, en lugar de asignar los datos en dos lugares diferentes, podemos hacer esto otro: Class Cliente Public Nombre As String Public Apellidos As String Public FechaCreacion As Date ' Public Sub New() FechaCreacion = Date.Now End Sub ' Public Sub New(elNombre As String, losApellidos As String) Nombre = elNombre Apellidos = losApellidos End Sub End Class Es decir, desde el constructor con argumentos llamamos al constructor que no los tiene, consiguiendo que también se asigne la fecha. Esta declaración de la clase Cliente realmente no compilará. Y no compila por la razón tan "simple" de que aquí el compilador de Visual Basic 2010 no sabe cual es nuestra intención, ya que New es una palabra reservada que sirve para crear nuevos objetos y, siempre, una instrucción tiene preferencia sobre el nombre de un método, por tanto, podemos recurrir al objeto especial Me el cual nos sirve, para representar al objeto que actualmente está en la memoria, así que, para que esa declaración de la clase Cliente funcione, debemos usar Me.New() para llamar al constructor sin parámetros. Nota Importante: El IDE de Visual Basic 2010 colorea las instrucciones y tipos propios del lenguaje, en el caso de Me, lo que no debe confundirnos es que cuando declaramos Sub New, tanto Sub como New se muestran coloreadas, cuando solo se debería colorear Sub; sin embargo cuando usamos Me.New, solo se colorea Me y no New que es correcto, tal como vemos en la figura 2.11, ya que en este caso New es el nombre de un procedimiento y los procedimientos no son parte de las instrucciones y tipos de .NET. Coloreo erróneo de New Cuando Visual Basic 2010 no crea un constructor automáticamente Tal como hemos comentado, si nosotros no definimos un constructor (Sub New), lo hará el propio compilador de Visual Basic 2010, y cuando lo hace automáticamente, siempre es un constructor sin parámetros. Pero hay ocasiones en las que nos puede interesar que no exista un constructor sin parámetros, por ejemplo, podemos crear una clase Cliente que solo se pueda instanciar si le pasamos, por ejemplo el número de identificación fiscal, (NIF), en caso de que no se indique ese dato, no podremos crear un nuevo objeto Cliente, de esta forma, nos aseguramos siempre de que el NIF siempre esté especificado. Seguramente por parámetros, Visual tanto, si definimos también tenga uno ese motivo, si nosotros definimos un constructor con Basic 2010 no crea uno automáticamente sin parámetros. Por un constructor con parámetros en una clase y queremos que sin parámetros, lo tenemos que definer nosotros mismos. El destructor: El punto final de la vida de una clase De la misma forma que una clase tiene su punto de entrada o momento de nacimiento en el constructor, también tienen un sitio que se ejecutará cuando el objeto creado en la memoria ya no sea necesario, es decir, cuando acabe la vida del objeto creado. El destructor de Visual Basic 2010 es un método llamado Finalize, el cual se hereda de la clase Object, por tanto no es necesario que escribamos nada en él. El propio CLR se encargará de llamar a ese método cuando el objeto ya no sea necesario. La forma en que se destruyen los objetos pueden ser de dos formas: Porque los destruyamos nosotros asignando un valor Nothing a la variable que lo referencia, o bien porque el objeto esté fuera de ámbito, es decir, haya salido de su espacio de ejecución, por ejemplo, si declaramos un objeto dentro de un método, cuando ese método termina, el objeto se destruye, (hay algunas excepciones a esta última regla, como puede ser que ese mismo objeto también esté referenciado por otra variable externa al método.) Lo que debemos tener muy presente es que en .NET los objetos no se destruyen inmediatamente. Esto es así debido a que en .NET existe un "sistema" que se encarga de realizar esta gestión de limpieza: El recolector de basura o de objetos no usados (Garbage Collector, GC). Este recolector de objetos no usados se encarga de comprobar constantemente cuando un objeto no se está usando y es el que decide cuando hay que llamar al destructor. Debido a esta característica de .NET, si nuestra clase hace uso de recursos externos que necesiten ser eliminados cuando el objeto ya no se vaya a seguir usando, debemos definer un método que sea el encargado de realizar esa liberación, pero ese método debemos llamarlo de forma manual, ya que, aunque en .NET existen formas de hacer que esa llamada sea automática, nunca tenderemos la seguridad de que se llame en el momento oportuno, y esto es algo que, según que casos, puede ser un inconveniente. Recomendación: Si nuestra clase utiliza recursos externos, por ejemplo un fichero o una base de datos, debemos definir un método que se encargue de liberarlos y a ese método debemos encargarnos de llamarlo cuando ya no lo necesitemos. Por definición a este tipo de métodos se les suele dar el nombre Close o Dispose, aunque este último tiene un significado especial y por convención solo debemos usarlo siguiendo las indicaciones de la documentación. Inicialización directa de objetos De todos los modos, en Visual Basic 2010 se ha agregado una característica adicional que tiene que ver con la inicialización de objetos. Hasta ahora hemos visto como instanciar una clase utilizando su constructor, pero quizás lo que no sabíamos es que en Visual Basic 2010 podemos inicializar la clase a través de su constructor e incluso inicializar directamente las propiedades de la clase. Supongamos por lo tanto el siguiente código fuente: Class Cliente Private m_Nombre As String Public Property Nombre() As String Get Return m_Nombre End Get Set(ByVal value As String) m_Nombre = value End Set End Property Public Sub New() End Sub End Class A continuación instanciaremos la clase y con ello, inicializaremos adicionalmente la propiedad que hemos declarado. El código quedará de la siguiente forma: Dim claseCliente As New Cliente() With {.Nombre = "Pedro"} Esta forma de inicializar objetos nos permite ser más productivos y prácticos y ahorrar tiempo y líneas de código en nuestras aplicaciones. Como podemos apreciar, la forma de inicializar las propiedades o las variables de una clase es utilizando la palabra clave With seguida de llaves, y dentro de las llaves, un punto seguido de la propiedad o variable que queremos inicializar con sus valor de inicialización. Si tenemos más de una variable a inicializar, deberemos separarlas por comas. Intellisense nos ayudará enormemente a inicializar la propiedad o variable que deseemos, ya que vincula de forma directa el código de la clase haciéndonos más fácil el trabajo con los miembros de la clase. Estructuras: Tipos por valor definidos por el usuario De la misma forma que podemos definir nuestros propios tipos de datos por referencia, Visual Basic 2010 nos permite crear nuestros propios tipos por valor. Para crear nuestros tipos de datos por referencia, usamos la "instrucción" Class, por tanto es de esperar que también exista una instrucción para crear nuestros tipos por valor, y esa instrucción es: Structure, por eso en Visual Basic 2010 a los tipos por valor definidos por el usuario se llaman estructuras. Las estructuras pueden contener los mismos miembros que las clases, aunque algunos de ellos se comporten de forma diferente o al menos tengan algunas restricciones, como que los campos definidos en las estructuras no se pueden inicializar al mismo tiempo que se declaran o no pueden contener constructores "simples", ya que el propio compilador siempre se encarga de crearlo, para así poder inicializar todos los campos definidos. Otra de las características de las estructuras es que no es necesario crear una instancia para poder usarlas, ya que es un tipo por valor y los tipos por valor no necesitan ser instanciados para que existan. Definir una estructura Las estructuras se definen usando la palabra Structure seguida del nombre y acaba usando las instrucciones End Structure. El siguiente código define una estructura llamada Punto en la que tenemos dos campos públicos. Structure Punto Public X As Integer Public Y As Integer End Structure Para usarla podemos hacer algo como esto: Dim p As Punto p.X = 100 p.Y = 75 También podemos usar New al declarar el objeto: Dim p As New Punto Aunque en las estructuras, usar New, sería algo redundante y por tanto no necesario. Las estructuras siempre se almacenan en la pila, por tanto deberíamos tener la precaución de no crear estructuras con muchos campos o con muchos miembros, ya que esto implicaría un mayor consumo del "preciado" espacio de la pila. Accesibilidad La accesibilidad es la característica que podemos aplicar a cualquiera de los elementos que definamos en nuestro código. Dependiendo de la accesibilidad declarada tendremos distintos tipos de accesos a esos elementos. Los modificadores de accesibilidad que podemos aplicar a los tipos y elementos definidos en nuestro código pueden ser cualquiera de los mostrados en la siguiente lista: Public: Acceso no restringido. Este es modificador de accesibilidad con mayor "cobertura", podemos acceder a cualquier miembro público desde cualquier parte de nuestro código. Aunque, como veremos, este acceso no restringido puede verse reducido dependiendo de dónde lo usemos. Protected: Acceso limitado a la clase contenedora o a los tipos derivados de esta clase. Este modificador solamente se usa con clases que se deriven de otras. Friend: Acceso limitado al proyecto actual. Visual Basic 2010 aplica este modificador de forma predeterminada a los procedimientos declarados en las clases. Protected Friend: Acceso limitado al proyecto actual o a los tipos derivados de la clase contenedora. Una mezcla de los dos modificadores anteriores. Private: Acceso limitado al tipo contenedor. Es el más restrictivos de todos los modificadores de accesibilidad y en el caso de los campos declarados en las clases (Class) equivale a usar Dim. Estos modificadores de accesibilidad los podemos usar tanto en clases, estructuras, interfaces, enumeraciones, delegados, eventos, métodos, propiedades y campos. Aunque no serán aplicables en espacios de nombres (Namespace) ni clases de tipo Module, en estos dos casos siempre tendrán cobertura pública, si bien no se permite el uso de ningún modificador. Accesibilidad de las variables en los procedimientos Las variables declaradas dentro de un procedimiento solo son accesibles dentro de ese procedimiento, en este caso solo se puede aplicar el ámbito privado, aunque no podremos usar la instrucción Private, sino Dim o Static. Nota: La palabra clave Static, nos permite definir una variable privada (o local) alprocedimiento para que mantenga el valor entre diferentes llamadas a eseprocedimiento; esto contrasta con el resto de variables declaradas en un procedimiento cuya duración es la misma que la vida del propio procedimiento, por tanto, las variables no estáticas pierden el valor al terminar la ejecución del procedimiento. Las accesibilidades predeterminadas La accesibilidad de una variable o procedimiento en la que no hemos indicado el modificador de accesibilidad dependerá del sitio en el que la hemos declarado. Por ejemplo, en las estructuras si definimos los campos usando Dim, estos tendrán un ámbito igual que si le hubiésemos aplicado el modificador Public; sin embargo, esa misma variable declarada en una clase (Class o Module) tendrá una accesibilidad Private. Así mismo, si el elemento que declaramos es un procedimiento y no indicamos el modificador de ámbito, éste tendrá un ámbito de tipo Public si lo definimos en una estructura y si el lugar en el que lo declaramos es una clase (o Module), éste será Friend. La accesibilidad predeterminada de los tipos Tal como podemos ver en la tabla de arriba, la accesibilidad predeterminada, (la que tienen cuando no se indica expresamente con un modificador), de todos los tipos es Friend, es decir, accesible a todo el proyecto, aunque en el caso de las enumeraciones el modificador depende de dónde se declare dicha enumeración, si está declarada a nivel de espacio de nombres será Friend, en el resto de los casos será Public. En la tercera columna tenemos la accesibilidad predeterminada declaramos las variables con Dim, aunque en las interfaces y enumeraciones no se permiten declarer variables. cuando en las La última columna es la correspondiente a los procedimientos, en el caso de las interfaces no se puede aplicar ningún modificador de accesibilidad y de forma predeterminada son públicos. En esta otra tabla tenemos la accesibilidad permitida en cada tipo así como las que podemos indicar en los miembros de esos tipos. Accesibilidades permitidas en los tipos En el caso de las clases e interfaces, los modificadores Protected y Protected Friend solo podremos aplicarlos cuando están declaradas dentro de una clase (Class). Propiedades Las propiedades son los miembros de los tipos que nos permiten acceder a los datos que dicho tipo manipula. Normalmente una propiedad está relacionada con un campo, de forma que el campo sea el que realmente contenga el valor y la propiedad simplemente sea una especie de método a través del cual podemos acceder a ese valor. Debido a que el uso de las propiedades realmente nos permite acceder a los valores de una clase (o tipo), se suelen confundir los campos con las propiedades, de hecho si definimos una variable pública en una clase, ésta se comporta de manera similar, pero realmente un campo (o variable) público no es una propiedad, al menos en el sentido de que el propio .NET Framework no lo interpreta como tal, aunque en la práctica nos puede parecer que es así, ya que se utilizan de la misma forma. Lo primero que debemos tener presente es que gracias a esta diferenciación que hace .NET Framework, podemos poner en práctica una de las características de la programación orientada a objetos: la encapsulación, de forma, que la manipulación de los datos que una clase contiene siempre se deben hacer de forma "interna" o privada a la clase, dejando a las propiedades la posibilidad de que externamente se manipulen, de forma controlada, esos datos. Definir una propiedad Debido a que una propiedad realmente nos permite acceder a un dato que la clase (o estructura) manipula, siempre tendremos un campo relacionado con una propiedad. El campo será el que contenga el valor y la propiedad será la que nos permita manipular ese valor. En Visual Basic 2010, las propiedades las declaramos usando la instrucción Property y la definición de la misma termina con End Property, dentro de ese bloque de código tenemos que definir otros dos bloques: uno se usará a la hora de leer el valor de la propiedad (bloque Get), y el otro cuando queremos asignar un valor a la propiedad (bloque Set). El bloque que nos permite acceder al valor de la propiedad estará indicado por la instrucción Get y acaba con End Get, por otra parte, el bloque usado para asignar un valor a la propiedad se define mediante la instrucción Set y acaba con End Set. Veamos como definir una propiedad en Visual Basic 2010: Public Class Cliente Private _nombre As String Public Property Nombre() As String Get Return _nombre End Get Set(ByVal value As String) _nombre = value End Set End Property End Class Como podemos comprobar tenemos dos bloques de código, el bloque Get que es el que se usa cuando queremos acceder al valor de la propiedad, por tanto devolvemos el valor del campo privado usado para almacenar ese dato. El bloque Set es el usado cuando asignamos un valor a la propiedad, este bloque tiene definido un parámetro (value) que representa al valor que queremos asignar a la propiedad. Propiedades de solo lectura En Visual Basic 2010 podemos hacer que una propiedad sea de solo lectura, de forma que el valor que representa no pueda ser cambiado. Para definir este tipo de propiedades solo debemos indicar el bloque Get de la propiedad, además de indicar de forma expresa que esa es nuestra intención, para ello debemos usar el modificador ReadOnly para que el compilador de Visual Basic 2010 acepte la declaración: Public ReadOnly Property Hoy() As Date Get Return Date.Now End Get End Property Propiedades de solo escritura De igual forma, si queremos definir una propiedad que sea de solo escritura, solo definiremos el bloque Set, pero al igual que ocurre con las propiedades de solo lectura, debemos indicar expresamente que esa es nuestra intención, para ello usaremos la palabra clave WriteOnly: Public WriteOnly Property Password() As String Set(ByVal value As String) If value = "blablabla" Then ' ok End If End Set End Property Diferente accesibilidad para los bloques Get y Set En las propiedades normales (de lectura y escritura), podemos definir diferentes niveles de accesibilidad a cada uno de los dos bloques que forman una propiedad. Por ejemplo, podríamos definir el bloque Get como público, (siempre accesible), y el bloque Set como Private, de forma que solo se puedan realizar asignaciones desde dentro de la propia clase. Por ejemplo, el salario de un empleado podríamos declararlo para que desde cualquier punto se pueda saber el importe, pero la asignación de dicho importe solo estará accesible para los procedimientos definidos en la propia clase: Public Class Empleado Private _salario As Decimal Public Property Salario() As Decimal Get Return _salario End Get Private Set(ByVal value As Decimal) _salario = value End Set End Property End Class Para hacer que el bloque Set sea privado, lo indicamos con el modificador de accesibilidad Private, al no indicar ningún modificador en el bloque Get, éste será el mismo que el de la propiedad. Nota: El nivel de accesibilidad de los bloques Get o Set debe ser igual o inferior que el de la propiedad, por tanto si la propiedad la declaramos como Private, no podemos definir como público los bloques Get o Set. Interfaces Las interfaces son un elemento bastante importante en .NET Framework, ya que de hecho se utiliza con bastante frecuencia, en esta lección veremos que son las interfaces y como utilizarlas en nuestros proyectos, también veremos que papel juegan en .NET y cómo aplicar algunas de las definidas en la biblioteca base. ¿Qué es una interfaz? Las interfaces son una forma especial de una clase, aunque la diferencia principal con las clases es que las interface no contienen código ejecutable, solo definen los miembros. Las interfaces se utilizan para indicar el "comportamiento" que tendrá una clase, o al menos qué miembros debe definir esa clase. Para definir una interfaz en Visual Basic 2010 tenemos que usar la instrucción Interface seguida del nombre de la interfaz y terminar la declaración con End Interface: Public Interface IAnimal '... End Interface Otra Nota Importante: Según las indicaciones de nomenclatura de .NET Framework, se recomienda que todas las interfaces empiecen con una I mayúscula seguida del nombre al que hacer referencia la interfaz. ¿Qué contiene una interfaz? Al principio de esta lección hemos comentado que las interfaces no contienen código, solo define los miembros que contiene. Esa definición la haremos como cualquier otra, con la diferencia de que no incluimos ningún código, solo la "firma" o el prototipo de cada uno de esos miembros. En el siguiente código definimos una interfaz que contiene los cuatros tipos de miembros típicos de cualquier clase: Public Interface IPrueba Sub Mostrar() Function Saludo(ByVal nombre As String) As String Property Nombre() As String Event DatosCambiados() End Interface El primer miembro de esta interfaz, es un método de tipo Sub que no recibe parámetros.   Dos cosas importantes sobre las interfaces: 1- No se pueden definir campos. 2- Los miembros de las interfaces siempre son públicos. Una interfaz es un contrato Siempre que leemos sobre las interfaces, lo primero con lo que nos solemos encontrar es que una interfaz es un contrato. Veamos que nos quieren decir con esa frase. Tal como acabamos de ver, las interfaces solo definen los miembros, pero no el código a usar en cada uno de ellos, esto es así precisamente porque el papel que juegan las interfaces es el de solo indicar que es lo que una clase o estructura puede, o mejor dicho, debe implementar. Usar una interfaz en una clase Para poder utilizar una interfaz en una clase, o dicho de otra forma: para "implementar" los miembros expuestos por una interfaz en una clase debemos hacerlo mediante la instrucción Implements seguida del nombre de la interfaz: Public Class Prueba Implements IPrueba Y como comentábamos, cualquier clase que implemente una interfaz debe definir cada uno de los miembros de esa interfaz, por eso es el propio Visual Basic el encargado de crear automáticamente los métodos y propiedades que la interfaz implementa, aunque solo inserta el "prototipo" de cada uno de esos miembros, dejando para nosotros el trabajo de escribir el código. Usando la definición de la interfaz IPrueba que vimos antes, el código que añadirá VB sera el siguiente: Public Class Prueba Implements IPrueba Public Event DatosCambiados() Implements IPrueba.DatosCambiados Public Sub Mostrar() Implements IPrueba.Mostrar End Sub Public Property Nombre() As String Implements IPrueba.Nombre Get End Get Set(ByVal value As String) End Set End Property Public Function Saludo(ByVal nombre As String) As String _ Implements IPrueba.Saludo End Function End Class Como podemos apreciar, no solo ha añadido las definiciones de cada miembro de la interfaz, sino que también añade código extra a cada uno de esos miembros: la instrucción Implements seguida del nombre de la interfaz y el miembro al que se hará referencia. La utilidad de que en cada uno de los miembros se indique expresamente el método al que se hace referencia, es que podemos usar nombres diferentes al indicado en la interfaz. Por ejemplo, si implementamos esta interfaz en una clase que solo utilizará la impresora, al método Mostrar lo podríamos llamar Imprimir que sería más adecuado, en ese caso simplemente cambiamos el nombre del método de la clase para que implemente el método Mostrar de la interfaz: Public Sub Imprimir() Implements IPrueba.Mostrar End Sub De esta forma, aunque en la clase se llame de forma diferente, realmente hace referencia al método de la interfaz. Acceder a los miembros implementados Una vez que tenemos implementada una interfaz en nuestra clase, podemos acceder a esos miembros de forma directa, es decir, usando un objeto creado a partir de la clase: Dim prueba1 As New Prueba prueba1.Mostrar() O bien de forma indirecta, por medio de una variable del mismo tipo que la interfaz: Dim prueba1 As New Prueba Dim interfaz1 As IPrueba interfaz1 = prueba1 interfaz1.Mostrar() ¿Qué ha ocurre aquí? Como ya comentamos anteriormente, cuando asignamos variables por referencia, realmente lo que asignamos son referencias a los objetos creados en la memoria, por tanto la variable interfaz1 está haciendo referencia al mismo objeto que prueba1, aunque esa variable solo tendrá acceso a los miembros de la clase Prueba que conoce, es decir, los miembros definidos en IPrueba. Si la clase define otros miembros que no están en la interfaz, la variable interfaz1 no podrá acceder a ellos. Saber si un objeto implementa una interfaz Si las interfaces sirven para acceder de forma anónima a los métodos de un objeto, es normal que en Visual Basic tengamos algún mecanismo para descubrir si un objeto implementa una interfaz. Para realizar esta comprobación podemos usar en una expresión If/Then la instrucción TypeOf... Is, de forma que si la variable indicada después de TypeOf contiene el tipo especificado después de Is, la condición se cumple: If TypeOf prueba1 Is IPrueba Then interfaz1 = prueba1 interfaz1.Mostrar() End If De esta forma nos aseguramos de que el código se ejecutará solamente si la variable prueba1 contiene una definición de la interfaz IPrueba. Implementación de múltiples interfaces En Visual Basic 2010, una misma clase puede implementar más de una interfaz. Para indicar que implementamos más de una interfaz podemos hacerlo de dos formas: 1- Usando nuevamente la instrucción Implements seguida del nombre de la interfaz: Public Class Prueba Implements IPrueba Implements IComparable 2- Indicando las otras interfaces en la misma instrucción Implements, pero separándolas con comas: Public Class Prueba Implements IPrueba, IComparable De cualquiera de las dos formas es válido implementar más de una interfaz, aunque en ambos casos siempre debemos definir los miembros de cada una de esas interfaces. Múltiple implementación de un mismo miembro Como acabamos de comprobar, una misma clase puede implementar más de una interfaz, y esto nos puede causar una duda: ¿Qué ocurre si dos interfaces definen un método que es idéntico en ambas? En principio, no habría problemas, ya que el propio Visual Basic crearía dos métodos con nombres diferentes y a cada uno le asignaría la implementación de ese método definido en cada interfaz. Por ejemplo, si tenemos otra interfaz que define el método Mostrar y la implementamos en la clase Prueba, la declaración podría quedar de esta forma: Public Interface IMostrar Sub Mostrar() End Interface Public Sub Mostrar1() Implements IMostrar.Mostrar End Sub Aunque si ambos métodos hacen lo mismo, en este ejemplo mostrar algo, podríamos hacer que el mismo método de la clase sirva para implementar el de las dos interfaces: Public Sub Mostrar() Implements IPrueba.Mostrar, IMostrar.Mostrar End Sub Es decir, lo único que tendríamos que hacer es indicar la otra implementación separándola con una coma. ¿Dónde podemos implementar las interfaces? Para ir acabando este tema nos queda por saber, entre otras cosas, dónde podemos implementar las interfaces, es decir, en que tipos de datos podemos usar Implements. La implementación de interfaces la podemos hacer en las clases (Class), estructuras (Structure) y en otras interfaces (Interface). Debido a que una interfaz puede implementar otras interfaces, si en una clase implementamos una interfaz que a su vez implementa otras, esa clase tendrá definidas cada una de las interfaces, lo mismo ocurre con una clase que "se derive" de otra clase que implementa alguna interfaz, la nueva clase también incorporará esa interfaz. Nota: Cuando una interfaz implementa otras interfaces, éstas no se pueden indicar mediante Implements, en lugar de usar esa instrucción debemos usar Inherits. Public Interface IPrueba2 Inherits IMostrar Si en una clase implementamos una interfaz que a su vez implementa otras interfaces, esa clase tendrá definiciones de todos los miembros de todas las interfaces, por ejemplo, si tenemos la siguiente definición de la interfaz IPrueba2 que "implementa" la interfaz IMostrar: Public Interface IPrueba2 Inherits IMostrar Function Saludo(ByVal nombre As String) As String Property Nombre() As String Event DatosCambiados() End Interface Y la clase Prueba2 implementa IPrueba2, la definición de los miembros quedaría de la siguiente forma: Public Class Prueba2 Implements IPrueba2 Public Sub Mostrar() Implements IMostrar.Mostrar End Sub Public Event DatosCambiados() Implements IPrueba2.DatosCambiados Public Property Nombre() As String Implements IPrueba2.Nombre Get End Get Set(ByVal value As String) End Set End Property Public Function Saludo(ByVal nombre As String) As String _ Implements IPrueba2.Saludo End Function End Class En este código, el método Mostrar se indica mediante la interfaz IMostrar, pero también se puede hacer por medio de IPrueba2.Mostrar, ya que IPrueba2 también lo implementa (o hereda). Si dejamos que Visual Basic cree los miembros, no tendremos problemas a la hora de definirlos. Pero si lo hacemos manualmente, aunque dentro del IDE de Visual Basic, éste nos ayuda indicándonos que interfaces implementamos y qué miembros son los que se adecuan a la declaración que estamos usando. IntelliSense solo muestra los métodos que mejor se adecuan a la declaración Un ejemplo práctico usando una interfaz de .NET Tal como comentamos al principio, el propio .NET está "plagado" de interfaces, cada una de ellas tiene un fin concreto, por ejemplo, si queremos definir una clase que pueda ser clasificada por el propio .NET, esa clase debe implementar la interfaz IComparable, ya que el método Sort, (de la clase que contiene los elementos del tipo definido por nosotros), que es el encargado de clasificar los elementos, hará una llamada al método IComparable.CompareTo de cada uno de los objetos que queremos clasificar, por tanto, si la clase no ha definido esa interfaz, no podremos clasificar los elementos que contenga. En el siguiente código tenemos la definición de una clase llamada Empleado que implementa la interfaz IComparable y en el método CompareTo hace la comprobación de que objeto es mayor o menor, si el de la propia clase o el indicado en el parámetro de esa función: Public Class Empleado Implements IComparable Public Nombre As String Public Sub New(ByVal nombre As String) Me.Nombre = nombre End Sub ' Si el objeto es del tipo Empleado, comparamos los nombres. ' Si no es del tipo Empleado, devolvemos un cero ' que significa que los dos objetos son iguales. Public Function CompareTo(ByVal obj As Object) As Integer _ Implements System.IComparable.CompareTo If TypeOf obj Is Empleado Then Dim e1 As Empleado = CType(obj, Empleado) Return String.Compare(Me.Nombre, e1.Nombre) Else Return 0 End If End Function End Class En el método CompareTo hacemos una comprobación de que el objeto con el que debemos realizar la comparación es del tipo Empleado, en ese caso convertimos el objeto pasado en uno del tipo Empleado y comparamos los nombres. Si el objeto que recibe el método no es del tipo Empleado, devolvemos un cero, para indicar que no haga ninguna clasificación, ya que ese valor indica que los dos objetos son iguales. Esta comparación no es estrictamente necesaria, ya que si no indicamos el valor que debe devolver una función, devolverá un valor cero, al menos en este caso, ya que el tipo a devolver es un número entero. Esta clase la podemos usar de esta forma: ' Una colección de datos del tipo Empleado. Dim empleados As New System.Collections.Generic.List(Of Empleado) ' Añadimos varios empleados a la colección. empleados.Add(New Empleado("Pepe")) empleados.Add(New Empleado("Bernardo")) empleados.Add(New Empleado("Juan")) empleados.Add(New Empleado("Ana")) ' Clasificamos los empleados de la colección. empleados.Sort() ' Un ejemplo muy práctico usando una interfaz de .NET Tal como comentamos al principio, el propio .NET está "plagado" de interfaces, cada una de ellas tiene un fin concreto, por ejemplo, si queremos definir una clase que pueda ser clasificada por el propio .NET, esa clase debe implementar la interfaz IComparable, ya que el método Sort, (de la clase que contiene los elementos del tipo definido por nosotros), que es el encargado de clasificar los elementos, hará una llamada al método IComparable.CompareTo de cada uno de los objetos que queremos clasificar, por tanto, si la clase no ha definido esa interfaz, no podremos clasificar los elementos que contenga. En el siguiente código tenemos la definición de una clase llamada Empleado que implementa la interfaz IComparable y en el método CompareTo hace la comprobación de que objeto es mayor o menor, si el de la propia clase o el indicado en el parámetro de esa función: Public Class Empleado Implements IComparable Public Nombre As String Public Sub New(ByVal nombre As String) Me.Nombre = nombre End Sub ' Si el objeto es del tipo Empleado, comparamos los nombres. ' Si no es del tipo Empleado, devolvemos un cero ' que significa que los dos objetos son iguales. Public Function CompareTo(ByVal obj As Object) As Integer _ Implements System.IComparable.CompareTo If TypeOf obj Is Empleado Then Dim e1 As Empleado = CType(obj, Empleado) Return String.Compare(Me.Nombre, e1.Nombre) Else Return 0 End If End Function End Class En el método CompareTo hacemos una comprobación de que el objeto con el que debemos realizar la comparación es del tipo Empleado, en ese caso convertimos el objeto pasado en uno del tipo Empleado y comparamos los nombres. Si el objeto que recibe el método no es del tipo Empleado, devolvemos un cero, para indicar que no haga ninguna clasificación, ya que ese valor indica que los dos objetos son iguales. Esta comparación no es estrictamente necesaria, ya que si no indicamos el valor que debe devolver una función, devolverá un valor cero, al menos en este caso, ya que el tipo a devolver es un número entero. Esta clase la podemos usar de esta forma: ' Una colección de datos del tipo Empleado. Dim empleados As New System.Collections.Generic.List(Of Empleado) ' Añadimos varios empleados a la colección. empleados.Add(New Empleado("Pepe")) empleados.Add(New Empleado("Bernardo")) empleados.Add(New Empleado("Juan")) empleados.Add(New Empleado("Ana")) ' Clasificamos los empleados de la colección. empleados.Sort() ' Mostramos los datos una vez clasificados. For Each e1 As Empleado In empleados Console.WriteLine(e1.Nombre) Next Manejo de Excepciones En Visual Basic 2010 el tratamiento de errores (excepciones) podemos hacerlo de dos formas distintas, dependiendo de que utilicemos el tratamiento de errores heredado de versiones anteriores o el recomendado para la plataforma .NET: el control de errors estructurado, con idea de hacerlo de una forma más "ordenada". En esta lección solamente veremos cómo tratar los errores de forma estructurada, porque, como hemos comentado es la forma recomendada de hacerlo en .NET Framework. Manejo de excepciones no estructuradas Como acabamos de comentar, no trataremos o explicaremos cómo trabajar con el tratamiento de errores no estructurados, pero al menos queremos hacer una aclaración para que no nos llevemos una sorpresa si nos decidimos a usarlo: No podemos usar los dos sistemas de tratamiento de errores al mismo tiempo, por lo menos en un mismo método o propiedad, o utilizamos On Error o utilizamos Try/Catch. De todas formas, si escribimos nuestro código con el IDE (entorno integrado) de Visual Studio 2010, éste nos avisará de que no podemos hacer esa mezcla. Manejo de excepciones estructuradas Las excepciones en Visual Basic 2010 las podemos controlar usando las instrucciones Try /Catch / Finally. Estas instrucciones realmente son bloques de instrucciones, al estilo de If / Else. Cuando queramos controlar una parte del código que puede producir un error lo incluimos dentro del bloque Try. Si se produce un error, éste lo podemos detectar en el bloque Catch. Por último, independientemente de que se produzca o no una excepción, podemos ejecutar el código que incluyamos en el bloque Finally, para indicar el final del bloque de control de excepciones lo haremos con End Try. Cuando creamos una estructura de control de excepciones no estamos obligados a usar los tres bloques, aunque el primero: Try si es necesario, ya que es el que le indica al compilador que tenemos intención de controlar los errores que se produzcan. Por tanto podemos crear un "manejador" de excepciones usando los tres bloques, usando Try y Catch o usando Try y Finally. Veamos ahora con más detalle cada uno de estos bloques y que es lo que podemos hacer en cada uno de ellos. Bloque Try En este bloque incluiremos el código en el que queremos comprobar los errores. El código a usar será un código normal, es decir, no tenemos que hacer nada en especial, ya que en el momento que se produzca el error se usará (si hay) el código del bloque Catch. Bloque Catch Si se produce una excepción, ésta la capturamos en un bloque Catch. En el bloque Catch podemos indicar que tipo de excepción queremos capturar, para ello usaremos una variable de tipo Exception, la cual pude ser del tipo de error específico que queremos controlar o de un tipo genérico. Por ejemplo, si sabemos que nuestro código puede producir un error al trabajar con ficheros, podemos usar un código como este: Try ' código para trabajar con ficheros, etc. Catch ex As System.IO.IOException ' el código a ejecutar cuando se produzca ese error End Try Si nuestra intención es capturar todos los errores que se produzcan, es decir, no queremos hacer un filtro con errores específicos, podemos usar la clase Exception como tipo de excepción a capturar. La clase Exception es la más genérica de todas las clases para manejo de excepciones, por tanto capturará todas las excepciones que se produzcan. Try ' código que queremos controlar Catch ex As Exception ' el código a ejecutar cuando se produzca cualquier error End Try Aunque si no vamos usar la variable indicada en el bloque Catch, pero queremos que no se detenga la aplicación cuando se produzca un error, podemos hacerlo de esta forma: Try ' código que queremos controlar Catch ' el código a ejecutar cuando se produzca cualquier error End Try Varias capturas de errores en un mismo bloque Try/Catch En un mismo Try podemos capturar diferentes tipos de errores, para ello podemos incluir varios bloques Catch, cada uno de ellos con un tipo de excepción diferente. Es importante tener en cuenta que cuando se produce un error y usamos varios bloques Catch, Visual Basic buscará la captura que mejor se adapte al error que se ha producido, pero siempre lo hará examinando los diferentes bloques Catch que hayamos indicados empezando por el indicado después del bloque Try, por tanto deberíamos poner las más genéricas al final, de forma que siempre nos aseguremos de que las capturas de errors más específicas se intercepten antes que las genéricas. Evaluación condicional en un bloque Catch Además de indicar la excepción que queremos controlar, en un bloque Catch podemos añadir la cláusula When para evaluar una expresión. Si la evaluación de la expresión indicada después de When devuelve un valor verdadero, se procesará el bloque Catch, en caso de que devuelva un valor falso, se ignorará esa captura de error. En el siguiente ejemplo, se evalúa el bloque Catch solo cuando el valor de la variable y es cero, en otro caso se utilizará el que no tiene la cláusula When: Dim x, y, r As Integer Try x = CInt(Console.ReadLine()) y = CInt(Console.ReadLine()) r=x\y Console.WriteLine("El resultado es: {0}", r) Catch ex As Exception When y = 0 Console.WriteLine("No se puede dividir por cero.") Catch ex As Exception Console.WriteLine(ex.Message) End Try Bloque Finally En este bloque podemos indicar las instrucciones que queremos que se ejecuten, se produzca o no una excepción. De esta forma nos aseguramos de que siempre se ejecutará un código, por ejemplo para liberar recursos, se haya producido un error o no. Nota: Hay que tener en cuenta de que incluso si usamos Exit Try para salir del bloque de control de errores, se ejecutará el código indicado en el bloque Finally. Captura de errores no controlados Como es lógico, si no controlamos las excepciones que se puedan producir en nuestras aplicaciones, estas serán inicialmente controladas por el propio runtime de .NET, en estos casos la aplicación se detiene y se muestra el error al usuario. Pero esto es algo que no deberíamos consentir, por tanto siempre deberíamos detectar todos los errores que se produzcan en nuestras aplicaciones, pero a pesar de que lo intentemos, es muy probable que no siempre podamos conseguirlo. Por suerte, en Visual Basic 2010 tenemos dos formas de interceptar los errores no controlados: La primera es iniciando nuestra aplicación dentro de un bloque Try/Catch, de esta forma, cuando se produzca el error, se capturará en el bloque Catch. La segunda forma de interceptar los errores no controlados es mediante el evento: UnhandledException, disponible por medio del objeto My.Application. Nota: De los eventos nos ocuparemos en la siguiente lección, pero como el evento UnhandledException está directamente relacionado con la captura de errores, lo mostramos en esta, aunque recomendamos al lector que esta sección la vuelva a leer después de ver todo lo relacionado con los eventos. Atributos Los atributos son etiquetas descriptivas que proporcionan información adicional sobre elementos de programación como tipos, campos, métodos y propiedades. Otras aplicaciones, como el compilador de Visual Basic, pueden hacer referencia a la información adicional en atributos para determinar cómo pueden utilizarse estos elementos. En esta lección veremos algunos ejemplos de cómo usarlos en nuestras propias aplicaciones y, aunque sea de forma general, cómo usar y aplicar algunos de los atributos definidos en el propio .NET Framework, al menos los que más directamente nos pueden interesar a los desarrolladores de Visual Basic. De hecho en cualquier aplicación que creemos con Visual Basic 2010 estaremos tratando con atributos, aunque nosotros ni nos enteremos, ya que el propio compilador los utiliza para generar los metadatos del ensamblado, es decir, la información sobre todo lo que contiene el ejecutable o librería que hemos creado con Visual Basic 2010. Por otra parte, el uso de los atributos nos sirve para ofrecer cierta funcionalidad extra a nuestro código, por ejemplo, cuando creamos nuestros propios controles, mediante atributos podemos indicarle al diseñador de formularios si debe mostrar ciertos miembros del control en la ventana de propiedades, etc. Tipos de atributos que podemos usar en una aplicación Como hemos comentado, existen atributos que son globales a toda la aplicación y otros que podremos aplicar a elementos particulares, como una clase o un método. Atributos globales a la aplicación Estos se indican usando Assembly: en el atributo y los podremos usar en cualquier parte de nuestro código, aunque lo habitual es usarlos en el fichero AssemblyInfo.vb. Atributos particulares a las clases o miembros de las clases Estos atributos solo se aplican a la clase o al miembro de la clase que creamos conveniente, el formato es parecido a los atributos globales, ya que se utilizan los signos de menor y mayor para encerrarlo, con la diferencia de que en este tipo de atributos no debemos usar Assembly:, ya que esta instrucción indica que el atributo es a nivel del ensamblado. <Microsoft.VisualBasic.HideModuleName()>  _   Module  MyResources     Atributos personalizados En el siguiente código tenemos la declaración de una clase que se utilizará como atributo personalizado, notamos que, por definición las clases para usarlas como atributos deben terminar con la palabra Attribute después del nombre "real" de la clase, que como veremos en el código que utiliza ese atributo, esa "extensión" al nombre de la clase no se utiliza. Veamos primero el código del atributo personalizado: <AttributeUsage(AttributeTargets.All)> _ Public Class AutorAttribute Inherits System.Attribute ' Private _ModificadoPor As String Private _Version As String Private _Fecha As String ' Public Property ModificadoPor() As String Get Return _ModificadoPor End Get Set(ByVal value As String) _ModificadoPor = value End Set End Property ' Public Property Version() As String Get Return _Version End Get Set(ByVal value As String) _Version = value End Set End Property ' Public Property Fecha() As String Get Return _Fecha End Get Set(ByVal value As String) _Fecha = value End Para usar este atributo lo podemos hacer de la siguiente forma: <Autor(ModificadoPor:="Guillermo 'guille'", _ Version:="1.0.0.0", Fecha:="13/Abr/2005")> _ Public Class PruebaAtributos Nota: Cuando utilizamos el atributo, en el constructor que de forma predeterminada crea Visual Basic, los parámetros se indican por el orden alfabético de las propiedades, pero que nosotros podemos alterar usando directamente los nombres de las propiedades, tal como podemos ver en el código de ejemplo anterior. Atributos específicos de Visual Basic Visual Basic utiliza una serie de atributos para indicar ciertas características de nuestro código, en particular son tres: COMClassAttribute Este atributo se utiliza para simplificar la creación de componentes COM desde Visual Basic. VBFixedStringAttribute Este atributo se utiliza para crear cadenas de longitud fija en Visual Basic 2010. Habitualmente se aplica a campos o miembros de una estructura, principalmente cuando queremos acceder al API de Windows o cuando queremos usar esa estructura para guardar información en un fichero, pero utilizando una cantidad fija de caracteres. VBFixedArrayAttribute Este atributo, al igual que el anterior, lo podremos usar para declarar arrays de tamaño fijo, al menos si las declaramos en una estructura, ya que por defecto, los arrays de Visual Basic son de tamaño variable. Bien una vez estudiados los conceptos veremos un par de ejemplos explicados paso a paso en este libro los cuales son utilizados y pueden ser mejorados. Pondremos definiciones de MySql Server 5.0 de los cuales tocaremos en el siguiente bloque, donde utilizamos un modulo de consultas a la base de datos de MySql Server. Ejemplo 1 Desarollo de Addenda . Bien pues ahora con este ejemplo vamos ya que explico la teoría con un ejemplo real que actualmente funciona, tendrá errores pero de eso se trata de mencionarlos y así corregir, veremos conceptos múltiples en el desarrollo de esta pequeña aplicación de escritorio. Englobaremos los conceptos principales utilizados en el funcionamiento de la aplicación, como el consumo de Web Service, Bases de Datos, Usuarios remotos en MySql Server, algunos conceptos de POO, el cual también es objetivo de este libro, algunas clases, módulos, servicios de referencia, etc. En este caso describo las partes que forman esta aplicación que esta a prueba en producción aun, quiere decir que esta sujeta a mejoras futuras, para facilitar mas aun las tareas al usuario en su interfaz, en código mas optimizado para nosotros. Esta aplicación contendrá un login, un Menú Inicial (pantalla), la forma que contiene las funciones principales de esta aplicación, herramientas de consulta y un manual de usuario, estas actualmente ya que anteriormente se describieron. Bien a continuación empezáremos el desarrollo de nuestra aplicación en Visual Basic Net 2010, comenzando con crear nuestro proyecto, ponerle un nombre y guardarlo en alguna dirección local de nuestro ordenador, selección de un menú de inicio login, Menú Principal, un Modulo para conexión, otros ítems para lo que se requiera. Ahora Iniciamos Visual Estudio 2010 y creamos un nuevo proyecto, le colocamos un nombre y seleccionamos un directorio local donde se almacenara nuestra solución y demás archivos que le acompañan y son creados por defecto por Visual Basic 2010. Figura 1 Le colocamos un nombre en este caso se llamara CFDI, ya que es por utilizar facturas electrónicas de CFDI v3.2, no entraremos en detalles con nuestro nombre pero si debe tener uno con referencia al proyecto. Figura 2 Una vez hecho lo anterior nos quedara nuestra pantalla o espacio de trabajo por default, ahora procedemos a añadir los ítems a utilizar y algunos otros conforme los vayamos requiriendo en el desarrollo. En este caso añadimos un Login Form, un MDI Parent Form, About Box, Modulo, un par de Form, entre algunos mas. Ver Figura 3. Figura  3   Seguimos con el MDI Parent Form, y Form, el cual son importantes en todos los sistemas.   Figura  4   Figura  5   Figura  6   Figura  7   Ahora pasamos a la fase inicial del diseño y desarrollo de la aplicación, en este caso crearemos un login el cual se conecte a la base de datos MySql Server, donde una vez validado el usuario y password este nos mostrara una pantalla principal con los menús en los cuales trabajaremos uno a uno después, así que primero codificaremos el login. Creación del Modulo Conexión “modCN.vb” Figura  8   En el modulo creado y nombrado respectivamente, donde se observa en la parte derecha del panel soluciones le daremos doble clic o clic derecho-ver código, o simplemente F7, primero vamos a observar en la parte superior del editor que tenemos algunas librerías declaradas que son parte de MySql, como Imports MySql.Data.MySqlClient, MySql.Data, etc. Pues bien esas librerías se van a agregar desde nuestro menú Project – Add Reference, la buscamos desde su directorio si no la han agregado antes, para encontrar dicha referencia debemos descargar* el conector Net desde www.mysql.com/downloads/connector/net/ la versión mas reciente en mi caso utilizo v6.4, una vez descargada la instalan, dejar el directorio por defecto para poderla encontrar en “C:\Program Files\MySQL\MySQL Connector Net 6.6.4\Assemblies\v4.0” y así seleccionarla después de instalar el conector y solo agregar la referencia al proyecto y utilizarla durante el desarrollo. Una vez agregadas procedemos a declararlas como se muestra en la figura siguiente y poder hacer la conexión a nuestra Base de Datos para accesos, transacciones y demás tareas. Figura  9   Ahora veremos que al declarar las librerías de MySql las cuales utilizaremos para este modulo, nos servirá para conectar a la base de datos de MySql server para validar os datos introducidos por el usuario desde la aplicación y esta se comunicara a través de una cadena de conexión por medio del conector net a la Base de Datos y así validara si son correctos procederá al siguiente paso, de lo contrario volverá a pedir al usuario corrija los datos de ingreso. Si observamos nuestro Modulo Inicio-Fin con un color Azul diferencia del Nombre, este se encuentra color verde agua . Seguido de esto realizaremos la declaración de algunas variables a utilizar en este modulo de conexión, una variable de tipo comando, uno de lectura y otra de conexión al servidor. ‘Librerias Imports System.Data Imports Mysql.Data Imports Mysql.Data.MysqlClient Bien ahora se escribe el codigo para el modulo de conexion, declaramos las variables antes mencionadas documentando para su uso. En este caso objConex es una varialbe de objeto MySqlConnection, si fuese string colocariamos prefijo strConex, es necesario documentar para que al leer la variable con su prefijo se tenga una idea que tipo de variable. '----Conexion Publica---'Variable para la Conexion, puede ser cualquier nombre que ustedes identifiquen a la hora de programar. Public objConex As New MySqlConnection 'Declaro Variable para Comandos Sql Public objCmd As New MySqlCommand 'Declaro Variable para lectura de Datos Public objDReader As MySqlDataReader Declaramos una SubRutina que sera para abrir las conexiones en cada transaccion. 'Declaro mi subrutina publica para poderla utilizar durante todo el proyecto Addenda. Public Sub SubConexOpen() 'Captura el Error de la conexion On Error GoTo ErrSubConexionOpen 'Preparamos Cadena de Conexion objConex.ConnectionString = "server=000.000.00.00;userid=UserApp;password=AdminApp;database=xml;port=3306" 'Abre a la Base de Datos objConex.Open() 'Aqui finalize la Subrutina Exit Sub 'Despliega el Mensaje cuando aun esta abierta la conexion. ErrSubConexionOpen: 'Despliega el Mensaje de Error capturado al hacer conexion a BD. MsgBox("SubConexionOpen:" + Err.Description) End Sub 'Una subrutina para cerrar la conexion despues de alguna transaccion. Sub SubConexClose() 'Cierra la Conexión objConex.Close() End Sub Bien acabamos de hacer el modulo de conexión de nuestra aplicación de Visual Basic a la Base de Datos MySql Server. Hasta aquí hemos visto como conectar la Base de Datos con nuestra aplicación, la Base de Datos antes creada atraves de MySql Workbench o bien PhpMyAdmin. Formulario de Acceso Creación del el Formulario de Acceso para interactuar con la aplicación Addenda para la que se desarrolla el código paso a paso. Ahora seleccionar el formulario de acceso para trabajarlo, dando clic derecho – ver diseñador, o bien doble clic cobre el formulario de acceso y quedara de la siguiente manera (ver Figura 10). Figura  10   Para este formulario añadimos un LoginForm1.vb desde Project-Windows Forms, para reafirmar. Ahora pondremos el código de el botón “OK”, el cual valida el acceso al sistema o aplicación conectando a la base de datos del mismo. Para esto daremos doble clic en el botón Ok para entrar a vista de código. Figura 11 Librerias Las librerías MySql.Data, MySql.Data.MySqlClient, CFDI.modCN, las importamos a nuestro formulario con la declaración Imports donde su función es importar todos o los elementos especificados al archivo actual. La explicación de los namespaces esta anteriormente explicada o podemos ir a su pagina oficial* y ver su concepto, en cuanto a CFDI.modCN es la clase que contiene la cadena conexión a la Base de Datos para conectar desde la Visual Basic 2010 al servidor de MySql Server 5.9. Ahora realizamos una subrutina para limpiar los controles del LoginForm1.vb, como se observa en la imagen. El nombre de la subrutina en esta ocasión se llama sub subCleanLogin(). Figura 12 Subrutina SubCleanLogin. El Siguiente codigo es para el Boton Aceptar   'Boton  OK          Private  Sub  butOK_Click(ByVal  sender  As  System.Object,  ByVal  e  As   System.EventArgs)  Handles  butOK.Click                  'Muestra  Paneld  espues  de  validar  el  usuario  y  password!!!                  Dim  verifica  As  String  =  txtUser.Text  &  txtPass.Text                  '**********                  'POSIBLE  CONEXION                  '**********                                'Crear  commando  para  SELECT  al  usuariod  e  la  BD  creada.                  Dim  Comando  As  New  MySqlCommand("SELECT  *  FROM  usuariosaddenda  WHERE         NumUser=  '"  &  txtUser.Text  &  "'  AND  CveUser=  '"  &  txtPass.Text  &  "'",  objConex)                    'Creamos  un  datareader                  Dim  DataReader  As  MySqlDataReader                                      DataReader  =  Comando.ExecuteReader()          'Obtiene  solo  el  DataReader                  'Recorre  las  filas                  While  DataReader.Read()                          lblInicio.Text  =  DataReader("NumUser")  &  ""  &  DataReader("CveUser")                  End  While                  DataReader.Close()                  'objConex.Close()                    'verifica  datos  con  mysql                  If  verifica  =  lblInicio.Text  Then                          MDIni.Show()                          'Llamadas                          subCleanLogin()                          Me.Hide()                    Else                          MsgBox("Codigo  y  Usuario  no  existen,  Verifiquelo  por  favor",   MsgBoxStyle.Information  +  MsgBoxStyle.OkOnly,  "Validacion")                  End  If            End  Sub   Figura 13. Veremos el Load del form y el botón salir o cancelar. Bien una vez pasado el LoginForm procedemos a cargar un Menú inicio el cual tomamos un MDI Parent. Modificamos los menús como los requieran, en este caso quedara así como acontinuacion, borramos todo el contenido del MDI, solo dejamos algunos menús para renombrarlos. Este contiene varios objetos como se muestra en la parte inferior del MDI, vienen por defecto, por la función a cumplir. Ver Figura 14. Formulario del MDI. Ver Figura 15. Menú de la Addenda Soriana Reverse. Ver Figura 16. Menú Consulta Ordenes. Ver Figura 17. Menú Salir – básico. *oficial = www.mysql.com Tambien utilizamos los siguientes controles: 1.- Texbox1.text = txtUsuario 2.- Texbox2.text = txtPasswod 3.- Label1.text = lblUsuario Text= Usuario 4.- Label1.text = lblPassword Text= Password 5.- Button1.text = butOk Text= OK 6.- Button1.text = butCancel Text= Cancel Creación del Formulario Principal Conexión “Form1.vb” Creación de el Form1.vb donde se realizara la comunicación de nuestra aplicación con el Web Service de Soriana, donde antes y después de hacer esa operación hay mas operaciones que deberán realizarse. Agregamos un Form1.vb, menú Project-Windows Form, dejar el nombre por defecto y diseñamos el Form e iniciaremos a programar los botones. Controles a utilizar: Seccion grabar Addenda Label1.text Text=Proveedor Label2.text Text=Carge u factura aqui Label3.text Text=Leer aqui Label4.text Text=Guardar con prefijo Label5.text Text=y/o Addenda Label6.text Text=Seleccionar el XMLAddenda en Label7.text Text=Controles Label8.text Text=Remision Electronica Reverse Tiendas Soriana Seccion Remision Label9.text Text=Proveedor Label10.text Text=Remision Label11.text Text=Consecutivo Label12.text Text=FechaRemision Label13.text Text=Tienda Label14.text Text=TipoMoneda Label15.text Text=TipoBulto Label16.text Text=EntregaMercancia Label17.text Text=CumpleRegFiscales Label18.text Text=CantidadBultos Label19.text Text=Total Label20.text Text=IVA Label21.text Text=OtrosImpuestos Label22.text Text=CantidadPedidos Seccion Pedido Label23.text Text=FolioPedido Label24.text Text=CantidadArticulos   Seccion Articulos Label25.text Text=Codigo Label26.text Text=CantidadUnidadCompra Label27.text Text=CostoUnidadCompra Textbox1.text = txtLoad Textbox2.text = txtGuardaA Textbox3.text = txtAddendaXml Textbox4.text = txtXmlWS Textbox5.text = txtProv Textbox6.text = txtRem Textbox7.text = dtpFecRem Textbox8.text = txtCantPed Textbox9.text = txtFolPed Textbox10.text = txtCUC 4 GroupBox ComboBox1.text = ComboBox1.text = ComboBox1.text = ComboBox1.text = ComboBox1.text = ComboBox1.text = ComboBox1.text = ComboBox1.text = cboConsec cboTienda cboTipoMon cboTipoBul cboEntMerc cboCumpReq cboCantArt txtCodigo MaskedTexBox1.text = mtbSubTotal MaskedTexBox1.text = mtbIva MaskedTexBox1.text = mtbCNUC NumericUpDown = nudCantBul Button1.Text = butNuevo Text = Nuevo Button2.text = butGenA Text = Generar Addenda Button3.text = butGrabar Text = Grabar Button4.text = butEnviar Text = Enviar a Soriana Button5.text = butSalir Text = Salir OpenFileDialog1.text = dlgOpen Esos son los controles a utilizar en el formulario principal por el cual realizamos este libro, este contiene mas formularios para otras actividades, como Obtener la respuesta del Web Service de Soriana, Almacenar las ordenes en una Base de Datos MySql Server, un MDIParent, el cual Fungirá como Menú Principal del programa. Añadiendo el Form1.vb Windows Form y realizado el diseño del formulario, como se puede observar en las capturas Figura 1 y Figura 1. Ver Figura Ver Figura Ahora Iniciaremos a programar el formulario iniciando en vista código y agregando las siguientes librerías. Ver Figura 17. Declaracion de Liberias Iniciamos con los Botones con los que vamos a interactuar: 1.- Iniciamos con el codigo de Nuevo: 'Limpia  y  prepara  controles                  Call  subPreparaControles()                  Call  subFormateaControles()   Contiene dos SubRutinas, definiremos con el codigo una a una, colocaremos comentarios en el codigo para entender lo que realiza, es importante documentar, para cuando se hagan modificaciones a mejorar localizemos rapido la parte del codigo a Actualizar. Rutina para Preparar los controles: Sub  subPreparaControles()                  txtProv.Clear()                  txtRem.Clear()                  txtIeps.Clear()                  txtOtrosImp.Text  =  "0"                    txtCantPed.Clear()                  'txtCita.Clear()                  'txtFolNotaEnt.Clear()                  'txtProv2.Clear()                  'txtRem2.Clear()                  txtFolPed.Clear()                  'txtTienda.Clear()                  'txtProv3.Clear()                  'txtRem3.Clear()                  'txtFolPed3.Clear()                  txtCodigo.Text  =  ""                  txtLoad.Clear()                    cboConsec.Text  =  ""                  cboTienda1.Text  =  ""                  cboTipoMon.Text  =  ""                  cboTipoBul.Text  =  ""                  cboEntMerc.Text  =  ""                  cboCumpReq.Text  =  ""                  cboCantArt.Text  =  ""                                      dtpFecRem.Mask  =  "9999-­‐99-­‐99T99:99:99"                      nudCantBul.Value  =  0                    mtbSubTotal.Mask  =  "99999.99"                  mtbIva.Mask  =  "99999.99"                  mtbTotal.Mask  =  "99999.99"                  mtbCNUC.Mask  =  "99999.99"                                                        txtProv.Focus()              End  Sub   Rutina para Formatear controles: Sub  subFormateaControles()                  txtProv.Text  =  "26740"                  txtRem.Text  =  "CRT-­‐"                  txtIeps.Text  =  "0"                  txtOtrosImp.Text  =  "0"                  txtCantPed.Text  =  "1"                  'txtCita.Clear()                  'txtFolNotaEnt.Clear()                  '  txtProv2.Text  =  "26740"                  'txtRem2.Text  =  "CRT-­‐"                  txtFolPed.Clear()                  'txtTienda.Text  =  "2282"                  'txtProv3.Text  =  "26740"                  'txtRem3.Text  =  "CRT-­‐"                  'txtFolPed3.Clear()                  txtCodigo.Text  =  "9771870230002"                  txtCUC.Clear()                  txtGuardarA.Text  =  "C:\XML\A\CRT"                  txtAddendaXml.Text  =  "_0.xml"                  txtLoad.Text  =  ""                  txtXmlWS.Text  =  ""                    cboConsec.Text  =  "0"                  cboTienda1.Text  =  "2282"                  cboTipoMon.Text  =  "1"                  cboTipoBul.Text  =  "1"                  cboEntMerc.Text  =  "1"                  cboCumpReq.Text  =  "true"                  cboCantArt.Text  =  "1"                  'cboPedEmitProv.Text  =  "SI"                  'cboTienda3.Text  =  "2282"                    'dtpFecRem.Mask  =  "9999-­‐99-­‐99T99:99:99"                  dtpFecRem.Text  =  "2012-­‐11-­‐00T00:00:00"                  'dtpFecEntMerc.Mask  =  "9999-­‐99-­‐99T99:99:99"                  'dtpFecEntMerc.Text  =  "2012-­‐11-­‐00T00:00:00"                    nudCantBul.Value  =  0                    mtbIva.Mask  =  "9.99"                  mtbIva.Text  =  "0.00"                  mtbTotal.Clear()                  mtbSubTotal.Clear()                  mtbCNUC.Mask  =  "99.99"                  mtbCNUC.Text  =  "09.15"                  'mtbPieps.Mask  =  "9"                  'mtbPieps.Text  =  "0"                  'mtbPiva.Mask  =  "9.99"                  'mtbPiva.Text  =  "0.00"                    txtProv.Focus()            End  Sub   Algunos estan comentados porque fueron sustituidos por un control repetido en las 3 secciones, ya que esta addenda cuenta con 3 regiones importantes: como son Remision, Pedido, Articulos, los cuales se observan en el Form1 que funge como principal en este Proyecto. 2.- Boton Generar Addenda: Private  Sub  butGenA_Click(ByVal  sender  As  System.Object,  ByVal  e  As   System.EventArgs)  Handles  butGenA.Click                  'Llama  la  subrutina  a  crear  el  Nodo  Addenda                  Call  subGeneraAddenda()          End  Sub   Colocamos la subrutina: Esta consta de varias partes, definiremos en el camino. 'SUBRUTINA  Crear  captura  de  datos  para  Generar  el  **NODO**  Addenda.XML          Sub  subGeneraAddenda()                  Try                                      'Verifica  que  este  llena  la  Caja  de  texto  de  la  URL    LEER  –  Contiene  una  Funcion  que  comprueba                      que  los  controles  tengan  el  texto,  una  function  de  tipo  Booleana  FnBoolDatosCorrectos.                  If  (FnBoolDatosCorrectos())  Then                          'Declaro  variable  array  para  el  objeto  Array                          Dim  objAddendas  As  New  ArrayList                          Dim  oAddenda  As  New  stcAddenda                            'Variable  para  el  Archivo  Xlml  en  directorio  Fisico  -­‐  generada                          Dim  A  As  XmlTextWriter  =  New  XmlTextWriter("C:\XML\Addenda.xml",  System.Text.UTF8Encoding.UTF8)                            'Para  Nodo  <Remision>                          'Añado  algunos  libros  de  la  estructura  arriba  definida  Llamada  “oAddenda”                          oAddenda.Proveedor  =  CInt(txtProv.Text)                          oAddenda.Remision  =  txtRem.Text                          oAddenda.Consecutivo  =  CShort(cboConsec.Text)                          oAddenda.FechaRemision  =  dtpFecRem.Text                        'Se  modifico  a  String                          oAddenda.Tienda  =  CShort(cboTienda1.Text)                          oAddenda.TipoMoneda  =  CShort(cboTipoMon.Text)                          oAddenda.TipoBulto  =  CShort(cboTipoBul.Text)                          oAddenda.EntregaMercancia  =  cboEntMerc.Text                          oAddenda.CumpleReqFiscales  =  "true"                                'Se  modifico  a  String                          oAddenda.CantidadBultos  =  CDec(CStr(nudCantBul.Text))                          oAddenda.Subtotal  =  CDec(mtbSubTotal.Text)                          oAddenda.IEPS  =  CDec(txtIeps.Text)                          oAddenda.IVA  =  CDec(mtbIva.Text)                          oAddenda.OtrosImpuestos  =  CDec(txtOtrosImp.Text)                          oAddenda.Total  =  CDec(mtbTotal.Text)                          oAddenda.CantidadPedidos  =  CInt(txtCantPed.Text)                          oAddenda.FechaEntregaMercancia  =  dtpFecRem.Text  'Se  modifico  a  String                            'oAddenda.Cita  =  CInt(txtCita.Text)      -­‐  Se  sustituyen  por  datos  0                          'oAddenda.FolioNotaEntrada  =  CInt(txtFolNotaEnt.Text)  -­‐  0                            'Para  Nodo  <Proveedor>                          oAddenda.Proveedor2  =  CInt(txtProv.Text)                          oAddenda.Remision2  =  txtRem.Text                          oAddenda.FolioPedido  =  CInt(txtFolPed.Text)                          oAddenda.Tienda2  =  CShort(cboTienda1.Text)                          oAddenda.CantidadArticulos  =  CInt(cboCantArt.Text)                          'oAddenda.PedidoEmitidoProveedor  =  cboPedEmitProv.Text                            'Para  Nodo  <Articulos>                          oAddenda.Proveedor3  =  CInt(txtProv.Text)                          oAddenda.Remision3  =  txtRem.Text                          oAddenda.FolioPedido2  =  CInt(txtFolPed.Text)                          oAddenda.Tienda3  =  CShort(cboTienda1.Text)                          oAddenda.Codigo  =  CDec(txtCodigo.Text)                          oAddenda.CantidadUnidadCompra  =  CDec(txtCUC.Text)                          oAddenda.CostoNetoUnidadCompra  =  CDec(mtbCNUC.Text)                          oAddenda.PorcentajeIEPS  =  CDec(txtIeps.Text)                          oAddenda.PorcentajeIVA  =  CDec(mtbIva.Text)                            'Agrego  a  la  Colección  –  se  creo  un  objeto  para  los  valores  obtenidos  de  la  estructura  oAddenda                          objAddendas.Add(oAddenda)                            'Formatea  indentado  el  archivo                          A.Formatting  =  System.Xml.Formatting.Indented                            'Si  escribe  la  inicializacion  del  Archivo                          A.WriteStartDocument(True)                            'Escribe  un  Comentario                          'A.WriteComment("Esto  es  un  comentario")                            'Crear  el  elemento  principal  del  documento                          A.WriteStartElement("Addenda")                          'A.WriteAttributeString("tipo",  "version")                          'Ciclo  para  incluir  los  elementos  de  la  colección                          For  Each  oNodoAddenda  As  stcAddenda  In  objAddendas                                    'A.WriteStartElement("cfdi:Addenda")                                    'Escribe  el  Titulo                                  A.WriteStartAttribute("xsi:schemaLocation")                                  A.WriteValue("http://www.sat.gob.mx/cfd/3   http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                    'Escribe  el  Titulo                                  A.WriteStartAttribute("xmlns:cfdi")                                  A.WriteValue("http://www.sat.gob.mx/cfd/3")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                    'Escribe  el  Titulo                                  A.WriteStartAttribute("xmlns:xsi")                                  A.WriteValue("http://www.w3.org/2001/XMLSchema-­‐instance")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                    'Escribe  el  Titulo                                  A.WriteStartAttribute("version")                                  A.WriteValue("3.2")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                  '************************************************                                  '                              TERMINA  ELEMENTO  CFDI:ADDENDA                                    '*************************************************                                  'Crear  un  elemento  llamado  'Nodo  Principal  Addenda'  con  un  nodo  de  texto                                  A.WriteStartElement("cfdi:Addenda")                                  'Crear  un  elemento  llamado  'DSCargaRemisionProv'  con  un  nodo  de  texto                                  A.WriteStartElement("DSCargaRemisionProv")                                    'Escribe  el  Titulo  Sirven  1                                  A.WriteStartAttribute("xmlns:xsi")                                  A.WriteValue("http://www.w3.org/2001/XMLSchema-­‐instance")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                  'Escribe  el  Titulo                                  'A.WriteStartAttribute("xmlns:xsi")                                  'A.WriteValue("http://www.sat.gob.mx/cfd/3")                                  'A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                    'Escribe  el  Titulo  Sirven  2                                  A.WriteStartAttribute("xmlns:xsd")                                  A.WriteValue("http://www.w3.org/2001/XMLSchema")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                      'Escribe  el  Titulo                                  A.WriteStartAttribute("tipo")                                  A.WriteValue("REVERSE")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                    'Escribe  el  Titulo                                  A.WriteStartAttribute("version")                                  A.WriteValue("1.0")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO  DE    ELEMENTO  'AddendaCFDSoriana-­‐Reverse'                                        '************************************************                                  '                            INICIA  NODO  REMISION                                    '*************************************************                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("Remision")                                      'Escribe  el  Titulo                                  A.WriteStartAttribute("Id")                                  A.WriteValue("Remision1")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                    'Escribe  el  Titulo                                  A.WriteStartAttribute("RowOrder")                                  A.WriteValue("0")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                      'Crear  un  elemento  llamado  'Proveedor'  con  un  nodo  de  texto                                  A.WriteStartElement("Proveedor")                                  'Escribe  el  Valor                                  A.WriteString("26740")                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("Remision")                                  'Escribe  el  Titulo                                  A.WriteString(oNodoAddenda.Remision)                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("Consecutivo")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.Consecutivo))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("FechaRemision")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.FechaRemision))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("Tienda")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.Tienda))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("TipoMoneda")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.TipoMoneda))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("TipoBulto")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.TipoBulto))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("EntregaMercancia")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.EntregaMercancia))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("CumpleReqFiscales")                                  'Escribe  el  Titulo                                  A.WriteString(cboCumpReq.Text)                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("CantidadBultos")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.CantidadBultos))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'Impuestos'  con  un  nodo  de  texto                                  'PARA  CREAR  ELEMENTO                                  'Crear  un  elemento  llamado  'SubTotal'  con  un  nodo  de  texto                                  A.WriteStartElement("Subtotal")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.Subtotal))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'SubTotal'  con  un  nodo  de  texto                                  A.WriteStartElement("IEPS")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.IEPS))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                  'Crear  un  elemento  llamado  'SubTotal'  con  un  nodo  de  texto                                  A.WriteStartElement("IVA")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.IVA))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'SubTotal'  con  un  nodo  de  texto                                  A.WriteStartElement("OtrosImpuestos")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.OtrosImpuestos))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'SubTotal'  con  un  nodo  de  texto                                  A.WriteStartElement("Total")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.Total))                                  'Cierra  el  elemento.                                  A.WriteEndElement()  'TERMINA  ATRIBUTO                                    'Cierra  el  elemento  Impuestos                                  'A.WriteEndElement()                                      'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("CantidadPedidos")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.CantidadPedidos))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("FechaEntregaMercancia")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.FechaEntregaMercancia))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  'A.WriteStartElement("Cita")                                  'Escribe  el  Titulo                                  'A.WriteString(CStr(oNodoAddenda.Cita))                                  'Cierra  el  elemento.                                  'A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  'A.WriteStartElement("FolioNotaEntrada")                                  'Escribe  el  Titulo                                  'A.WriteString(CStr(oNodoAddenda.FolioNotaEntrada))                                  'Cierra  el  elemento.                                  'A.WriteEndElement()                                  'Cerrar  el  elemento  2.                                  A.WriteEndElement()                                      'Listo                                      '++++++++++++++++++++++++++++++++++++++++++++                                  '                    INICIA  ELEMENTO  NODO  PEDIDOS                                  '++++++++++++++++++++++++++++++++++++++++++++                                  'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("Pedidos")                                      'Escribe  el  Titulo                                  A.WriteStartAttribute("Id")                                  A.WriteValue("Remision1")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                    'Escribe  el  Titulo                                  A.WriteStartAttribute("RowOrder")                                  A.WriteValue("1")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                          'Crear  un  elemento  llamado  'Proveedor'  con  un  nodo  de  texto                                  A.WriteStartElement("Proveedor")                                  'Escribe  el  Valor                                  A.WriteString("26740")                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                  'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("Remision")                                  'Escribe  el  Titulo                                  A.WriteString(oNodoAddenda.Remision2)                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("FolioPedido")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.FolioPedido))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("Tienda")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.Tienda2))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("CantidadArticulos")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.CantidadArticulos))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  'A.WriteStartElement("PedidoEmitidoProveedor")                                  'Escribe  el  Titulo                                  'A.WriteString(oNodoAddenda.PedidoEmitidoProveedor)                                  'Cierra  el  elemento.                                  'A.WriteEndElement()                                  'Cerrar  el  elemento  2.                                  A.WriteEndElement()                                            '&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&                                  '                          INICIA  ELEMENTO  NODO  DE  ARTICULOS                                                            '&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&                                  'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("Articulos")                                      'Escribe  el  Titulo                                  A.WriteStartAttribute("Id")                                  A.WriteValue("Remision1")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                    'Escribe  el  Titulo                                  A.WriteStartAttribute("RowOrder")                                  A.WriteValue("1")                                  A.WriteEndAttribute()  'TERMINA  ATRIBUTO                                          'Crear  un  elemento  llamado  'Proveedor'  con  un  nodo  de  texto                                  A.WriteStartElement("Proveedor")                                  'Escribe  el  Valor                                  A.WriteString("26740")                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("Remision")                                  'Escribe  el  Titulo                                  A.WriteString(oNodoAddenda.Remision3)                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("FolioPedido")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.FolioPedido2))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("Tienda")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.Tienda3))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("Codigo")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.Codigo))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("CantidadUnidadCompra")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.CantidadUnidadCompra))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("CostoNetoUnidadCompra")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.CostoNetoUnidadCompra))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                      'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("PorcentajeIEPS")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.PorcentajeIEPS))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Crear  un  elemento  llamado  'title'  con  un  nodo  de  texto                                  A.WriteStartElement("PorcentajeIVA")                                  'Escribe  el  Titulo                                  A.WriteString(CStr(oNodoAddenda.PorcentajeIVA))                                  'Cierra  el  elemento.                                  A.WriteEndElement()                                    'Finalizan  los  Nodos  –  Termina  de  generar  el  XML  correctamente  de  los  nodos.                                    A.WriteEndElement()  'Cierra  el  elemento  <cfdi:Addenda>  Segundo                                    A.WriteEndElement()  ''Cierra  el  elemento  DSCargaRemisionProv.                                    A.WriteEndElement()  'Para  Elemento  principal  Inicial  de  URL  SAT  <cfdi:Addenda>                          Next                            'Forza  grabación  a  Disco  –  aun  existente.                          A.Flush()                            'Cierra  el  Archivo                          A.Close()                                                      MsgBox("Se  genero  Nodo  Addenda",  MsgBoxStyle.OkOnly)                            'Con  uno  es  suficiente                          MsgBox("AHORA  debe  Cargar  el  Archivo  XML  Generado  Para  Grabar  Addenda  (Nombre  +  pref  de  Addenda   .",  MsgBoxStyle.Information)     End  If                  Catch  ex  As  Exception   'Podemos  poner  que  cachen  el  error.                  End  Try          End  Sub   Procedemos a poner la Funcion FnBoolDatosCorrectos()  utilizada, Estructura y objeto.   Function  FnBoolDatosCorrectos()  As  Boolean                    'Declara  Variables                  Dim  strMensaje  As  String                    'Inicializa  Variables                  strMensaje  =  vbNullString                    'Valida  captura  de  los  datos  Remision                    If  txtRem.Text  =  ""  Then                          If  (strMensaje  =  "")  Then                                  txtRem.Focus()                          End  If                          strMensaje  =  strMensaje  +  "La  Fecha  Remision  "  +  Constants.vbCr                  End  If                  'Valida  captura  de  Consec                  If  cboConsec.Text  =  ""  Then                          If  (strMensaje  =  "")  Then                                  cboConsec.Focus()                          End  If                          strMensaje  =  strMensaje  +  "El  Consec  =  0  "  +  Constants.vbCr                  End  If                  'Valida  captura  de  Tienda1                  If  cboTienda1.Text  =  ""  Then                          If  (strMensaje  =  "")  Then                                  cboTienda1.Focus()                          End  If                          strMensaje  =  strMensaje  +  "Tienda  "  +  Constants.vbCr                  End  If                  'Valida  captura  de  SubTotal                  If  Not  IsNumeric(mtbSubTotal.Text)  Then                          If  (strMensaje  =  "")  Then                                  mtbSubTotal.Focus()                          End  If                          strMensaje  =  strMensaje  +  "SubTotal  "  +  Constants.vbCr                  End  If                  'Valida  captura  de  Total                  If  Not  IsNumeric(mtbTotal.Text)  Then                          If  (strMensaje  =  "")  Then                                  mtbTotal.Focus()                          End  If                          strMensaje  =  strMensaje  +  "Total  "  +  Constants.vbCr                  End  If                  'Valida  captura  de  CantPedidos                  If  txtCantPed.Text  =  ""  Then                          If  (strMensaje  =  "")  Then                                  txtCantPed.Focus()                          End  If                          strMensaje  =  strMensaje  +  "CantPed  "  +  Constants.vbCr                  End  If                                      'Valida  captura  de  FolioPedido                  If  txtFolPed.Text  =  "1000000"  Then                          If  (strMensaje  =  "")  Then                                  txtFolPed.Focus()                          End  If                          strMensaje  =  strMensaje  +  "FolPedido  7  Caracteres  "  +  Constants.vbCr                  End  If                  'Valida  captura  de  Cantidad  Articulos                  If  cboCantArt.Text  =  ""  Then                          If  (strMensaje  =  "")  Then                                  cboCantArt.Focus()                          End  If                          strMensaje  =  strMensaje  +  "CantidadArticulos  "  +  Constants.vbCr                  End  If                                      'Valida  captura  de  CUC                  If  txtCUC.Text  =  ""  Then                          If  (strMensaje  =  "")  Then                                  txtCUC.Focus()                          End  If                          strMensaje  =  strMensaje  +  "CUC"  +  Constants.vbCr                  End  If                  'Valida  captura  de  CNUC                  If  mtbCNUC.Text  =  ""  Then                          If  (strMensaje  =  "")  Then                                  mtbCNUC.Focus()                          End  If                          strMensaje  =  strMensaje  +  "CNUC"  +  Constants.vbCr                  End  If                  'Valida  captura  de  FecRem                  If  dtpFecRem.Text  =  ""  Then                          If  (strMensaje  =  "")  Then                                  dtpFecRem.Focus()                          End  If                          strMensaje  =  strMensaje  +  "La  Fecha  Remision  "  +  Constants.vbCr                  End  If                                      'Verifica  si  hay  datos  que  capturar                  If  (strMensaje  <>  vbNullString)  Then                          MsgBox("Debes  de  capturar  los  siguientes  datos:"  +  Constants.vbCr  +   strMensaje)                          FnBoolDatosCorrectos  =  False                  Else                          FnBoolDatosCorrectos  =  True                  End  If            End  Function   Estructura oAddenda: 'Variables  a  capturar          Structure  stcAddenda                  '<Remision>                  Public  Proveedor  As  Integer                  Public  Remision  As  String                  Public  Consecutivo  As  Short                  Public  FechaRemision  As  String  'DateTime                  Public  Tienda  As  Short                  Public  TipoMoneda  As  Short                  Public  TipoBulto  As  Short                  Public  EntregaMercancia  As  Short                  Public  CumpleReqFiscales  As  Boolean                  Public  CantidadBultos  As  Decimal                  Public  Subtotal  As  Decimal                  Public  IEPS  As  Decimal                  Public  IVA  As  Decimal                  Public  OtrosImpuestos  As  Decimal                  Public  Total  As  Decimal                  Public  CantidadPedidos  As  Integer                  Public  FechaEntregaMercancia  As  String  '  DateTime                  Public  Cita  As  Integer                  Public  FolioNotaEntrada  As  Integer                    'Public  xsd  As  String                  '<Pedidos>                  Public  Proveedor2  As  Integer                  Public  Remision2  As  String                  Public  FolioPedido  As  Integer                  Public  Tienda2  As  Short                  Public  CantidadArticulos  As  Integer                  Public  PedidoEmitidoProveedor  As  String                    '<Articulos>                  Public  Proveedor3  As  Integer                  Public  Remision3  As  String                  Public  FolioPedido2  As  Integer                  Public  Tienda3  As  Short                  Public  Codigo  As  Decimal                  Public  CantidadUnidadCompra  As  Decimal                  Public  CostoNetoUnidadCompra  As  Decimal                  Public  PorcentajeIEPS  As  Decimal                  Public  PorcentajeIVA  As  Decimal              End  Structure   3.- Boton Grabar Addenda: Ahora procedemos a programar el boton magico, el que une el XML generado que lo utilizaremos como nodo y lo insertaremos en un XML que ya ha sido timbrado y sellado por el SAT, asi que con “NO” modificar nada de la cadena original podemos jugar con el XML sellado y aprobado, en este caso insertaremos el nodo <cfdi:Addenda> generado anteriormente. PEGA  O  GRABA  LA  ADDENDA  EN  XML  TIMBRADO          Private  Sub  butGrabA_Click(ByVal  sender  As  System.Object,  ByVal  e  As         System.EventArgs)  Handles  butGrabA.Click                    'Llamada  a  Cargar  factura  original  y  Nodo  Addenda                  Call  subPegaAddenda()            End  Sub   Codigo de la subrutina subPegaAddenda(),     ya   que   en   imagen   no   se   logra   observer  para  quien  quiera  implementar.     'SUBRUTINA  Lee  XML  a  cargar,  Lee  XML  Nodo  Addenda  creado              'Y  lo  Inserta  en  elXML  leido,  para  ser  guardado  Nuevamente          'con  nuevo  prefijo.          Sub  subPegaAddenda()                      'Create  the  XmlDocument.  Funcion  booleana  FnBoolDatosCorrectosII                  If  (FnBoolDatosCorrectosII())  Then                          '1.  Cargo  atravez  de  txtLoad  la  URL  de  la  Factura  Timbrada  y  sellada   por  SAT  desde  un  directorio                          Dim  docXmlF  As  XmlDocument  =  New  XmlDocument()                          docXmlF.Load(txtLoad.Text)                            '2.  Crear  en  otro  XmlDocument  el  Nodo  a  Insertar  Este  lo  cargo   directamende  del  directorio,  es  el  nodo  Addenda  capturado.                            Dim  docXmlA  As  New  XmlDocument()                          docXmlA.Load("C:\XML\Addenda.xml")                            '3.  Import  el  nodo  Addenda  dedocXmlA  en  el  documento  Original  docXmlF.                            Dim  Addenda  As  XmlNode  =   docXmlF.ImportNode(docXmlA.DocumentElement.LastChild,  True)                          docXmlF.DocumentElement.AppendChild(Addenda)                            '  4.  Save  the  modified  file  XML  a  formato  UTF8.                          docXmlF.PreserveWhitespace  =  True                          Dim  wrtr  As  XmlTextWriter  =  New  XmlTextWriter(txtGuardarA.Text  +   txtAddendaXml.Text,  System.Text.Encoding.UTF8)                          docXmlF.WriteTo(wrtr)                          wrtr.Close()                          '5.  Guardo  y  Senalo  la  Direccion  fisica                          docXmlF.Save(Console.Out)                          Console.WriteLine("C:\XML\CTT  +  .xml  is  created")                          Console.ReadLine()                          Console.WriteLine("Mostrando  que  se  ha  modificado  el  XML...")                          MsgBox("Se  genero  Addenda  Completa"  &  _                                        "        en"  &  _                                        "  C:\XML\CTT  +  Folio  .xml  is  created  XDXDXD...",   MsgBoxStyle.OkOnly)                    End  If   'Fin   End  Sub     Codigo de la function Booleana que comprueba espacios vacios: 'Evaluo  si  Esta  lleno  el  TxtLoad  para  "Pegar  La  addenda"  al  XML  Timbrado          Function  FnBoolDatosCorrectosII()  As  Boolean                    'Declara  Variables                  Dim  strMensaje  As  String                    'Inicializa  Variables                  strMensaje  =  vbNullString                  If  txtLoad.Text  =  ""  Then                          If  (strMensaje  =  "")  Then                                  txtLoad.Focus()                          End  If                          strMensaje  =  strMensaje  +  "Tu  Factura    en  Carge  su  factura   aqui..  "  +  Constants.vbCr                  End  If                  'Verifica  si  hay  datos  que  capturar                  If  (strMensaje  <>  vbNullString)  Then                          MsgBox("Debes  de  seleccionar  los  siguientes  datos:"  +   Constants.vbCr  +  strMensaje)                          FnBoolDatosCorrectosII  =  False                  Else                          FnBoolDatosCorrectosII  =  True                  End  If            End  Function   4.- Boton Enviar a Soriana: Seguimos con el Boton Enviar el cual es un boton donde aprenderemos a consumer un Webservice desde una aplicacion escritorio en este Lenguaje, ademas de enviarlo a travez de este como cadena. Pondremos Como agregar la Referencia de servicio de este WebService. Primero vamos al sitio official, donde veremos la siguiente URL del servicio: http://www.soriana.com/RecibeCFD/wseDocRecibo.asmx?op=RecibeCFD   Agregamos  la  referencia  de  Soriana,  verificamos  que  sirva  el  URL  del  Servicio.     Ver  Figura  19.  URL  del  Web  Service  al  que  consumiremos.                                                   Procedemos a ir a la interfaz de Visual Estudio 2010 donde desplegaremos el menu Proyecto y en Service Reference. Ver Figura 20. Menu Proyecto. Ahora en la parte avanzado, es mas recommendable ya que podemos ver los metodos que contiene este servicio. Ver Figura 21. Ir a advanced y colocar la URL del Web Service. Ver Figura 22, 23. Colocar URL para comprobar el funcionamiento (si exite y metodos que contiene).                     Ver  Figura  24,  25.  Se  Busca  el  WebService  y  se  Remobra.                                 Figura   25   agrega   la   referencia   al   Proyecto.   En   Mi   caso   coloque   el   Nombre   WSoriana.         Ver  Figura  26.  Aqui  se  ve  agregada   la  Referencia  con  el  nombre  a  uti-­‐   lizer  durante  el  desarrollo  y  fun-­‐   cionamiento  del  poryecto.                                                           Ver  Figura  27.  Agregamos  una  variable  que  utilizaremos  para  invocar  uno  de  sus   metodos  y  porceder  a  consumer  el  Web  Service.                                                       Procedemos a Mostrar el codigo de el Boton con el cual utilizaremos el evento click de este para enviar el xml complete en foato cadena como lo solicitan.   'BOTON  ENVIAR  WEB  SERVICE  SORIANA          Private  Sub  butEnviar_Click(ByVal  sender  As  System.Object,  ByVal  e  As   System.EventArgs)  Handles  butEnviar.Click                  'Compruebo  que  Selecione  el  XMl  a  Enviar                  Call  subEnvioXMLWS()          End  Sub   El codigo de la subrutina es el siguiente, describe en los comentarios, para no repetir: '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@          '4.-­‐          Para  enviarle  al  WS  un  String          '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@          Sub  subEnvioXMLWS()                  'Comprobar  si  esta  seleccionado  el  XMl  a  Enviar  –  Utilizamos  otra  function  Boolena  que  cuida  que   los  texbox’s  a  utilizer  tengan  contenido.                  If  (FnBoolDatosCorrectosIII())  Then                          Try                                    'Primero  pasar  el  XML  a  string                                  Dim  XMLWS  As  XmlDocument  =  New  XmlDocument()                                  XMLWS.Load(txtXmlWS.Text)                                  Dim  XMLCFD  As  [String]  =  XMLWS.OuterXml                                    'CONVIERTO  A  UTF8                                  '-­‐-­‐-­‐-­‐-­‐>INICIO                                    'Obtengo  el  XML  en  String  en  otra  variable  String  para  pasarlo  a  unicode.                                  Dim  StrMsg1  As  String  =  XMLCFD                                    '  We  can  convert  directly  a  byte  array                                  Dim  UTF8  As  New  System.Text.UTF8Encoding()                                  Dim  BytesMessage  As  [Byte]()  =  UTF8.GetBytes(StrMsg1)                                    'Mi  cadena                                  Dim  StrMsg2  As  [String]  =  UTF8.GetString(BytesMessage)                                  '-­‐-­‐-­‐-­‐-­‐>  FIN                                  'Instancias  el  WS  de  Soriana,  referencia  web  WSoriana                                  Dim  ServicioSoriana  As  New  WSoriana.wseDocReciboSoapClient()                                  'Haces  la  peticion  y  cachas  la  respuesta.                                  Dim  Respuesta  As  [String]  =  ServicioSoriana.RecibeCFD(StrMsg2)                                    'Trato  de  obtener  respuesta  Visible                                    Dim  XMLAceptado  As  String  =  Respuesta                                    'frmRespuestaWS.Text=                                  If  XMLAceptado  =  Respuesta  Then                                            'txtXmlWS.Text  =  Respuesta                                          frmRespuestaWS.Show()                                          frmRespuestaWS.rtbEditor.Text  =  Respuesta                                    Else                                          MsgBox("Hubo  Error  en  WS,  reportarlo  a  Depto.  Sistemas",  MsgBoxStyle.OkOnly)                                    End  If  '  FIn  de  XML  If-­‐Aceptado                            Catch  ex  As  Exception                            End  Try                    End  If            End  Sub   Procedemos a colocar el codigo de la function booleana, el cual verifica que el texbox txtXmlWS.txt contenga la url de la path donde toma el xml a convertir a cadena: 'Para  Verificar  antes  de  Envio  al  "Web  Service  Soriana"          Function  FnBoolDatosCorrectosIII()  As  Boolean                    'Declara  Variables                  Dim  strMensaje  As  String                    'Inicializa  Variables                  strMensaje  =  vbNullString                  If  txtXmlWS.Text  =  ""  Then                          If  (strMensaje  =  "")  Then                                  txtXmlWS.Focus()                          End  If                          strMensaje  =  strMensaje  +  "Tu  XML    en  Selecciones  XMLAddenda..  "  +   Constants.vbCr                  End  If                  'Verifica  si  hay  datos  que  capturar                  If  (strMensaje  <>  vbNullString)  Then                          MsgBox("Debes  de  Seleccionar  los  siguientes  datos:"  +  Constants.vbCr  +   strMensaje)                          FnBoolDatosCorrectosIII  =  False                  Else                          FnBoolDatosCorrectosIII  =  True                  End  If            End  Function     5.- Boton Salir: Por ultimo el Boton cerras o salir, el nombre de los controles pueden ponerlo a su disposicion.      'SALIR  DEL  PROGRAMA          Private  Sub  butSalir_Click(ByVal  sender  As  System.Object,  ByVal  e  As   System.EventArgs)  Handles  butSalir.Click                              'Finaliza  el  programa                  Me.Close()            End  Sub   Finalizo el desarrollo del formulario principal, ahora pondremos el formulario que recibe la Respuesta y como procedemos a guarder el registro de los XML enviados y recibidos, mediante la Respuesta que nos arroja el Web Service. Al presionar el boton Enviar a Soriana nos aparecera con el mensaje siguiente, el cual se genera en esta parte del codigo de la subrutina. 'SALIR  DEL  PROGRAMA          Private  Sub  butSalir_Click(ByVal  sender  As  System.Object,  ByVal  e  As   System.EventArgs)  Handles  butSalir.Click                              'Finaliza  el  programa                  Me.Close()          End  Sub   Ver Figura 28. Formulario que obtiene la Respuesta en texto plano como Respuesta del Web Service. Figura 28. Asi es como obetiene una Respuesta una vez enviado el archivo xml con la Addenda. Ver Figura 29. Obetiendo una respuesta del Web Service Soriana. Utilizamos un XML falso por tal motivo nos da Respuesta de Rechazada la factura. Adelante mostramos el error por el cual no fue aceptada “ACCEPTED”. Una vez hecho esto veremos el codigo de este formulario el cual solo es el boton Guardar, como su nombre dice, toma la Respuesta REJECT o ACCEPTED, del Fomr1.vb toma el numero de folio, Numero de Pedido, codigo del prooducto. Ver Figura 31. Mensaje al guardarlo en la Base de Datos de MySql Server, y despues cerramos el formulario Respuesta. Veamos el boton Guardar:          Private  Sub  butSave_Click(ByVal  sender  As  System.Object,  ByVal  e  As   System.EventArgs)  Handles  butSave.Click                              Call  subGuardaOrden()          -­‐-­‐-­‐Llamar  a  subrutina              End  Sub   El codigo de la subrutina subGuardaOrden():     'Subrutina  para  Insertar  La  N.  Orden  de  Soriana  en  MySql                        Public  Sub  subGuardaOrden()                          Try                                                          'Referencia  a  la  base  de  datos                          Dim  sql  As  String  =  "INSERT  INTO   xmladdenda(NFact,Codigo,NOrden,Enviado)  VALUES   (?NFact,?Codigo,?NOrden,?Enviado)"                          'Conexion  al  objeto  Cadena  de  MySql  Server                          Dim  CmdAccion  As  New  MySqlCommand(sql,  objConex)                                    '                                    'procedo  a  pasar  los  datos  de  los  textbox  a  la                                      variable  para  guarder.                                    'Para  elEnumerable  Insertar  Orden  en  BD  MySql                            Dim  NFact  As  String                          Dim  Codigo  As  String                          Dim  NOrden  As  String                          Dim  Enviado  As  String  'Para  status  de  la  Addenda                                'Para  Obtener  Accepted  o  Reject                                  'Inicia  -­‐-­‐-­‐-­‐-­‐-­‐-­‐>                                  Dim  texto  As  String  =  rtbEditor.Text                                If  texto.Contains("ACCEPTED")  =  True  Then                                  '....                                    texto  =  "ACCEPTED"                            ElseIf  texto.Contains("REJECT")  =  True  Then                                  '....                                  texto  =  "REJECT"                            ElseIf  texto.Contains("La  orden  ya  ha  sido  documentada  en  otra   factura")  =  True  Then                                  'NO  SE  ENCONTRO  NINGUNA  DE  LAS  2  PALABRAS                                  MsgBox("La  orden  ya  ha  sido  documentada  en  otra  factura,O   Verifique  error  <text>",  MsgBoxStyle.OkOnly)                            End  If                                  'Termina  -­‐-­‐-­‐-­‐-­‐-­‐-­‐>                              'Asignamos  valores  a  las  variables  obtenidas  para  insertar                                      NFact  =  CFDI.Form1.txtRem.Text                                  Codigo  =  CFDI.Form1.txtCodigo.Text                                  NOrden  =  CFDI.Form1.txtFolPed.Text                                  Enviado  =  texto                          'Pasamos  la  variable  a  Alias  de  MySql  DB                            CmdAccion.Parameters.AddWithValue("?NFact",  NFact)                          CmdAccion.Parameters.AddWithValue("?Codigo",  Codigo)                          CmdAccion.Parameters.AddWithValue("?NOrden",  NOrden)                          CmdAccion.Parameters.AddWithValue("?Enviado",  Enviado)                                    'ABRE  CONEXION  MYSQL  -­‐  Testea                                                    If  objConex.State  =  ConnectionState.Open  Then                                  CmdAccion.ExecuteNonQuery()                                  MsgBox("Se  guardo  correctamente  la  ORDEN  en  la  BD")                          Else                                  MsgBox("No  se  pudo  Guardar  la  Orden,  Ya  existe")                                  objConex.Close()                          End  If                                    'CIERRA  CONEXION  MYSQL                                    'ERROR  DE  BD  MYSQL                          Catch  ex  As  Exception                                  MsgBox("No  es  posible  Guardar,  Verifique!  "  &  ex.Message,   MsgBoxStyle.Critical,  "Error")                          objConex.Close()                            End  Try                        End  Sub   En el Load del formulario colocamos un par de subrutinas que nos daran function cuando guardamos un registro.                Private  Sub  frmRespuestaWS_Load(ByVal  sender  As  System.Object,  ByVal  e  As       System.EventArgs)  Handles  MyBase.Load                  'Inicializamos  Controles                  Call  SubInicializaCtrles()                    'Abre  Conexion                  Call  SubConexOpen()                End  Sub   Subrutina que inicia los controles cuando queremos que no aparezcan algunos. Como Minimizar, Maximizar, entre otros.            Sub  SubInicializaCtrles()                    'La  Forma                  Me.MinimizeBox  =  False                  Me.MaximizeBox  =  False                  'Me.CenterToScreen()                  Me.CancelButton  =  butExit                  'Me.AcceptButton  =  btnAceptar                    End  Sub   Ahora veamos la subrutina que abre nuestra conexion a la base de datos MySql Server 5.0 cuando deseamos hacer una transaccion.                Public  Sub  SubConexOpen()                    'Captura  el  Error                  On  Error  GoTo  ErrSubConexionOpen                    'Preparamos  Cadena  de  Conexion  de  DB,  User,  pass,  puerto  que  podemos  con  default.                              objConex.ConnectionString  =   "server=IP.FIJA;userid=usermysqlremoto;password=pass;database=xml;port=8869"                    'Abre  la  Base  de  Datos                  objConex.Open()                    Exit  Sub       ErrSubConexionOpen:                    'Despliega  el  Mensaje  de  Error                  MsgBox("SubConexionOpen:"  +  Err.Description)                  End  Sub   En el Boton Salir pondremos la subrutina que cierra nuestra conexcion al a Base de datos para cuando se utilize este disponible.        Sub  SubConexClose()                    'Cierra  la  Conexión                  objConex.Close()            End  Sub     Esta subrutina al igual la que habre la conexion se encuentran en el modulo de conexion que al Inicio se codifico. Cuando Insertamos o guardamosla Respuesta podemos verificarla en nuestra Base de Datos a travez de nuestro formulario de consulta, el cual contiene un boton de busqueda y otro para eliminar alguno que se haya insertado mal. Ver Figura 32. Menu de acceso al Formulario de consulta de Ordenes. Ver figura 33. Formulario de consulta de Ordenes. Como vemos anteriormente describimos los controles a utlizar a lo largo del Proyecto. En este caso en el formulario Consulta de Ordenes, utilizamos 4 commandbutton, un Combobox, un gropubox, y un datagridview. Bien ahora veremos el codigo de este formulario de consultas, el boton buscar ejecuta una subrutina de busqueda de folios como se muestra en la figura siguiente. Ver Figura 34. Busqueda de un Folio. Ver Figura 35. Codigo del Boton Buscar. Antes en la parte superior de la ventana codigo agregar las lineas correspondientes a MySql Server, eso siempre debemos agregar una vez que vayamos a utilizer alguna transaccion a la Base de datos.   Imports  MySql.Data   Imports  MySql.Data.MySqlClient                  Private  Sub  butBuscar_Click_1(ByVal  sender  As  System.Object,  ByVal  e  As   System.EventArgs)  Handles  butBuscar.Click                  'Busca  el  Texto  Indicado  en  el  Grid                  Call  SubBuscar(cboOrdenes.Text,  True,  dgvOrdenes)                  'Focus                  cboOrdenes.Focus()                  End  Sub   Subrutina para obtener el Folio en el combobox y con este dato localiza en el DataGridview recorriendo filas y columnas, tambien se puede hacer busqueda a travez de consulta en la Base de Datos, este caso es diferente. 'Para  Buscar  en  el  Grid  –  Boton  Busqueda                            Sub  SubBuscar(ByVal  pStrTextoBuscar  As  String,  ByVal  pBoolSubCadena  As   Boolean,  ByRef  pDataGridView  As  DataGridView)                    'Valida  que  traiga  algo  el  texto  a  Buscar                  If  pStrTextoBuscar  <>  String.Empty  Then                            'Validamos  que  haya  renglones                          If  pDataGridView.RowCount  >  0  Then                                    'Limpia  la  selección  previa                                  pDataGridView.ClearSelection()                                    'Ciclo  para  recorrer  cada  row                                  For  Each  row  As  DataGridViewRow  In  pDataGridView.Rows                                            'Ciclo  de  las  Celdas                                          For  Each  cell  As  DataGridViewCell  In  row.Cells                                                    'Valida  que  la  celda  no  este  vacía                                                  If  Not  IsNothing(cell.Value)  Then                                                            'Aca  entra  cuando  la  celda  tiene  algo                                                'Valida  si  es  busqueda  por  SubCadena                                              If  (pBoolSubCadena)  Then                                                  If  InStr(cell.Value.ToString,  pStrTextoBuscar)  >  0  Then                                                                          row.Selected  =  True                                                                  End  If                                                                    Else                                                  If  cell.Value.ToString()  =  pStrTextoBuscar  Then                                                  row.Selected  =  True                                                                  End  If                                                                      End  If                                                    End  If                                          Next                                  Next                          End  If                    End  If            End  Sub   Colocamos el codigo del Boton Eliminar, donde se hacen llamadas a subrutinas mencionadas en el formulario de Consulta. Este codigo va dentro del boton Eliminar, aqui realizamos una consulta a la Base de Datos y si se encuentra el registroentonces realiza la transaccion Delete.         'Creamos  variable  a  utilizer  como  Pregunta  para  determiner  si  procede  o  no  a   eliminar  el  registro.                  Dim  eliminar  As  New  MsgBoxResult                    eliminar  =  MsgBox("¿Estas  seguro  de  querer  borrar  la  ORDEN?",   MsgBoxStyle.YesNo,  "Confirmacion")                    Dim  CMD  As  New  MySqlCommand("DELETE  FROM  xmladdenda  WHERE  NOrden='"  &   cboOrdenes.Text  &  "'",  CN)                    If  eliminar  =  MsgBoxResult.Yes  Then                            CN.Open()                          CMD.ExecuteNonQuery()                          CN.Close()                          ‘Mensaje  de  operacion  exitosa                          MsgBox("EL  REGISTRO  SE  A  ELIMINADO")                  Else                          ‘Mensaje  de  operacion  cacelada                          MsgBox("Operacion  Cancelada  por  Usuario")                    End  If                    'PROCEDIMIENTO  DE  LIMPIAR                    Call  subCargar()                  Call  Mostrar()                  cboOrdenes.Focus()     Definimos las subrutinas que se observan al final del proceso, como son subCargar() y Mostrar(). Codigo para subrutina subCargar(): 'PARA  CARGAR  CBOS  EN  LISTAS          Sub  subCargar()                    Dim  DA  As  New  MySqlDataAdapter("SELECT  *  FROM  xmladdenda",  CN)                  Dim  DS  As  New  DataSet                  DA.Fill(DS,  "xmladdenda")                  'Mostrar  la  tabla  en  el  datagridview                  cboOrdenes.DataSource  =  DS.Tables("xmladdenda")                  cboOrdenes.DisplayMember  =  "NOrden"                  cboOrdenes.Focus()          End  Sub   Codigo para subrutina Mostrar(): 'Conexion  a  mysql  para  desplegar  archivos  insertados          Public  Sub  Mostrar()                  Dim  DA  As  New  MySqlDataAdapter("SELECT  *  FROM  xmladdenda",  objConexion)                  Dim  DS  As  New  DataSet                  DA.Fill(DS,  "xmladdenda")                  'Mostrar  la  tabla  en  el  datagridview                  dgvOrdenes.DataSource  =  DS.Tables("xmladdenda")                  'dgvUsers.Focus()          End  Sub   Codigo del Boton Actualizar. Aqui pondremos las siguientes subrutinas que realizaran el trabajo cada vez que se invoque el formulario. Las subrutinas son las anterior mencionadas. 'Actualiza  El  DatagridView  –  Este  codigo  se  coloca  en  el  boton  Actualizar.                  Call  Mostrar()                  Call  subCargar()   Ver Figura 37. Codigo del Boton Salir. En el evento click del boton Salir procedemos a poner el codigo basico para salir de la forma solamente. 'Cierra  la  forma                    Me.Close()   Bien hasta aqui finalize nuestro Ejemplo utilizado en la realidad, cumple la function y se encuentra en mejora, como optimizacion de codigo, diseno, recuerden ”las cosas aparte de hacerlas bien hay que hacerlas con estilo”. Ahora maestro como generar o construir el Producto para procederlo a instalar. Debemos ir a propiedades del Proyecto en el menu descrito para seleccionar la opcion Publish y en prerequisitos seleccionar que utilize .Net Framework v4, ya sea para x86 o x64 bits. Si no lo tiene el ordenador que sera el que lo utilize debera de instslarse para su funcionamiento. Ver Figura 38. Propiedades del Proyecto antes de publicar. En este caso para genera un Proyecto podemos ver la F.A.Q., en nuestro foro en el siguiente url, http://www.hackxcrack.es/forum/index.php?topic=16676.0 que es donde explica como publicar el proyeco para produccion. Dejo captura de como quedan el Proyecto generado. Son los archivos en un directorio, podemos generarlo en un website, ftp, etc, en mi caso lo genero de forma local. Ver Figura 39. Archivos del directorio publicado. Y al ejecutar el archive setup.exe si tenemos el .Net Framework v4.0 en nuestra version una vez instalado tendremos la pantalla final de logeo al Proyecto. Ver Figura 40. Pantalla de Inicio del aplicativo (Addenda Reverse). Finalizado el aplicativo ejemplar, dicto en breve que se cito de forma resumida algunos temas descritos en teoria al Inicio, ya que no podemos crear algo sin analizar los conceptos base de este lenguaje como cualquier otro, pues se dice libro por lo cual dejo mucha informacion que seleccione de la web para que e’ste los llene de conocimientos un poco mas acerca de lo que abarca este Lenguaje Visual Basic 2010. Agradecimientos Este libro lo realize con el fin compartir una experiencia cuando recien inicie en el mundo de la programación como todos, por gusto, uso en el trabajo, diversion, etc., cual sea el motive, siempre nos da frutos positivos. Esta expuesto a correction de errors para poder corregirlos y proceder a subir al aire un Segundo tomo de este Lenguaje que sera continuacion, para avanzar juntos en el aprendizaje de Visual Basic 2010. Cada vez mejorando en el estilo de programación a lo largo de este camino. La idea es tener un Segundo libro Orientado a Base de datos SQL Server y VB.NET 2010 con estilo de programación recien adquirido, el cual muchos deben dominar, es llamado Programación por Capas. Siendo mis palabras que me despiden y esperando sea de su agrado: Cordiales Saludos y hasta la proxima. Microsoft Visual Basic 2010 Realizando por : NetFcruz