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