Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
.NET
1. INTRODUCCIN
Cuando se construye software como producto empresarial o comercial, se llevan
a cabo varias tcnicas de manera que el desarrollo se haga en forma ordenada
y as poder asegurar un avance continuo del proyecto, un producto final de
calidad, y adems realizar posteriores mejoras sea una tarea ms fcil.
Existen muchas prcticas de programacin, dependiendo del tipo de software
que se va a desarrollar y de la disciplina o disciplinas de programacin que se
utilicen en el desarrollo del producto. Una de las ms utilizadas se llama la
programacin por capas, que consiste en dividir el cdigo fuente segn su
funcionalidad principal.
La programacin para lograr sacarle el mayor provecho a la programacin por
capas se necesita seguir una serie de pasos complejos los cuales primeramente
deben ser definidos para cada proyecto en especfico, luego deben ser
revisados para asegurarse de que el modelo adoptado cumpla con las normas
necesarias para que la aplicacin sea del agrado del usuario, y por ltimo debe
ser implementado por el grupo de desarrollo encargado para tal fin, los cuales
siguiendo el modelo propuesto obtienen una herramienta til para facilitar la
labor de programacin dividiendo la aplicacin en mdulos y capas fcil es de
pulir.
Vb.
Por otra parte, otra caracterstica importante de recalcar es la facilidad para las
actualizaciones de la aplicacin. En este aspecto, la programacin en capas
juega un papel de suma importancia ya que sigue un estndar conocido en el
ambiente de desarrollo de aplicaciones, lo cual da al programador una gua para
hacer mejoras a la aplicacin sin que esto sea una tarea tediosa y desgastante,
siguiendo el estndar establecido para tal fin y dividiendo las tareas en partes
especficas para cada capa del proyecto.
Las principales capas que siempre deben estar en este modelo son:
2.1.
Vb.
2.3.
CAPA DE DATOS
3. VENTAJAS Y DESVENTAJAS
La programacin en capas no es una tcnica rgida que debe implementarse
solamente de una forma, sino que los desarrolladores de proyectos tienen
mltiples maneras de implementarla segn las tecnologas y tendencias que se
utilicen.
La satisfaccin de los requerimientos del usuario es la base para escoger el
modelo de implementacin a seguir. La tendencia a utilizar el modelo de
programacin en capas es grande cuando se trata principalmente de
aplicaciones empresariales donde se deben manejar gran cantidad de
subsistemas y mdulos, as como generar reportes lo suficientemente complejos
como para necesitar un orden estricto a la hora de desarrollar el proyecto.
Dentro del concepto de programacin en capas, existen dos trminos esenciales
para el mejor entendimiento de los conceptos relativos a esta metodologa, es
aqu donde radica la importancia de la cohesin y el acoplamiento dentro de
una aplicacin generada mediante este mtodo.
Cohesin:
Este trmino es utilizado para describir el comportamiento que deben tener los
mdulos y objetos de un sistema o subsistema, comportamiento que describe la
forma en que deben trabajar los objetos y mdulos entre s, con alta cohesin
para que trabajando en conjunto los mdulos y objetos puedan alcanzar un solo
propsito de manera ms eficaz y rpida.
Determina que las operaciones de un objeto deben trabajar en conjunto para
alcanzar un propsito comn. Es deseable que haya alta cohesin.
Acoplamiento:
Se refiere al grado de dependencia que existe entre los mdulos. Este grado de
dependencia debe ser considerablemente bajo ya que el trabajo se divide en
mdulos para que cada uno tenga un funcionamiento especfico y puede ser
ms factible la implementacin por separado de cada uno. En caso de haber
alto acoplamiento entre mdulos no se estara alcanzando el principal objetivo
de este modelo, el cual es dividir una tarea grande en varias pequeas, ya que
los mdulos actuaran como uno solo al estar altamente acoplados entre s y se
perdera el objetivo primordial de dividir el proyecto.
3.1.
VENTAJAS
Vb.
3.2.
DESVENTAJAS
4. CONCLUSIONES
La programacin en capas ha sido una de las ltimas tendencias en cuanto a
software comercial se refiere, es una tendencia que bien aplicada puede
resultar en un desarrollo de
software eficiente.
Sin embargo, no todos los equipos ni empresas desarrolladoras usan un
sistema rgido, ni existe una forma estricta en la que tenga que
implementarse el modelo de capas, cada quin debe hacerlo segn sus
necesidades, alcances y lo ms importante; las tendencias y nuevas
tecnologas que vayan surgiendo.
Es importante tener en cuenta que no importa el lenguaje de programacin
usado, o el tipo de implementacin que se le d al modelo; se debe buscar
una alta cohesin y un bajo acoplamiento dentro de los objetos y capas para
lograr que la aplicacin sea fcilmente desarmable y sea ms sencillo
realizar mejoras y actualizaciones al sistema.
Vb.
Vb.
Donde:
conexionbd: biblioteca donde se creara una clase en la cual definamos
nuestra conexin a la base de datos con MSQLSERVER 2008.
Vb.
Biblioteca entidades
Nos ubicamos en la biblioteca entidades, damos clic derecho y agregamos
una clase vb y le ponemos como nombre producto.
Vb.
Biblioteca datos
Agregamos una clase del tipo vb, con el nombre de
ProductoDAO y ahora si nos ponemos a programar todos los
metodos que necesitemos para que la aplicacin funcione.
NOTA
Recordar que las clases que creamos en la biblioteca datos deben
hacer referencia a las bibliotecas conexionbd y entidades
Vb.
Vb.
Vb.
lector = cmdProducto.ExecuteReader
If lector.Read Then
Vb.
objProducto.IdProducto = lector(0)
objProducto.NombreProducto = lector(1)
objProducto.PCProducto = lector(2)
objProducto.PVproducto = lector(3)
objProducto.StockProducto = lector(4)
objProducto.FechaActProducto = lector(5)
objProducto.MarcaProducto = lector(6)
objProducto.UnidMedProducto = lector(7)
End If
Return objProducto
End Function
Public Function llenarComboProducto() As Producto
Dim lista As New List(Of Producto)
Dim lector As SqlDataReader
Dim objProducto As Producto
objProducto = New Producto
Dim objProducto1 As New Producto
cmdProducto = New SqlCommand("SP_Combo_Producto",
objConexion.obtenerconexion) If objConexion.obtenerconexion.State =
ConnectionState.Open Then
objConexion.obtenerconexion.Close()
Else
objConexion.obtenerconexion.Open()
End If
lector = cmdProducto.ExecuteReader
If lector.Read Then
objProducto.IdProducto = lector(0)
objProducto.NombreProducto = lector(1)
End If
Return objProducto
End Function
Public Function codProducto() As Integer
Dim codigo As Integer
Dim lector As SqlDataReader
cmdProducto = New SqlCommand("SP_Generar_Codigo_Producto",
objConexion.obtenerconexion) lector = cmdProducto.ExecuteReader
If lector.Read Then
codigo = lector(0)
End If
Return codigo
End Function
End Class
7. Capa negocio
Agregamos una clase con el nombre de ProductoNE y ahora si nos ponemos a
invocar los mtodos implementados en la biblioteca de datos.
Imports Datos
Imports Entidades
Public Class ProductoNE
Private objProductoDAO As ProductoDAO
Public Sub New()
objProductoDAO = New ProductoDAO
End Sub
Public Function AgregarProducto(ByVal objProductoE As Producto) As String
Return objProductoDAO.AgregarProductos(objProductoE)
End Function
Public Function ActualizarProducto(ByVal objProductoE As Producto) As String
Return objProductoDAO.ActualizarProductos(objProductoE)
End Function
Public Function CodProducto() As Integer
Return objProductoDAO.codProducto()
End Function
Public Function listarProductos() As List(Of Producto)
Vb.
Return objProductoDAO.listarProductos
End Function
Public Function listarProducto(ByVal codigo As Integer) As Producto
Return objProductoDAO.listarProducto(codigo)
End Function
Public Function llenarComboProducto() As Producto
Return objProductoDAO.llenarComboProducto
End Function
End Class
8. Capa Presentacin
Finalmente llegamos a la capa de presentacin, donde disearemos el formulario
que nos permita dar mantenimiento a los datos de la Tabla Productos, Adems
de un Formulario Principal que tenga las opciones de men.
8.1. Diseo de formulario FrmProducto
8.2.
Imports Entidades
Imports Negocio
Public Class FrmProducto
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles MyBase.Load
Dim objProductoNE1 As ProductoNE
objProductoNE1 = New ProductoNE
Sub
dgvProductos.DataSource = objProductoNE1.listarProductos
ConfigurarDataGrid()
BuscarProductos(1)
HabilitarCajas(False)
habilitarBotones(True, False, False, False) End
Vb.
8.7.
Botn Buscar
End Try
End Sub
8.8.
Evento CellClick del DataGriView dgvProductos
Private Sub dgvProductos_CellClick(ByVal sender As Object, ByVal e As
System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvProductos.CellClick
Vb.
Else
Me.txtMarca.Text = dgvFila.Cells(6).Value
Me.txtUnidMed.Text = dgvFila.Cells(7).Value
Else
Vb.
Me.dtpFechAct.Value = Now
End Sub
8.12. Procedimiento para habilitar controles que tienen los datos del Producto.
Sub HabilitarCajas(ByVal estado)
Me.txtCodigo.Enabled = False
Me.txtDescripcion.Enabled = estado
Me.txtPC.Enabled = estado
Me.txtPV.Enabled = estado
Me.txtStock.Enabled = estado
Me.txtUnidMed.Enabled = estado
Me.txtMarca.Enabled = estado
Me.dtpFechAct.Enabled = estado
Me.txtDescripcion.Focus()
End Sub
End Sub
idProducto = objProductoNE.CodProducto() - 1 If
codigo > idProducto Then
MsgBox("Registros no encontrado")
Else
objProductoE = objProductoNE.listarProducto(codigo)
Me.txtCodigo.Text = objProductoE.IdProducto
Me.txtDescripcion.Text = objProductoE.NombreProducto
Me.txtPC.Text = objProductoE.PCProducto Me.txtPV.Text =
objProductoE.PVproducto Me.txtStock.Text =
objProductoE.StockProducto Me.txtMarca.Text =
objProductoE.MarcaProducto Me.txtUnidMed.Text =
objProductoE.UnidMedProducto Me.dtpFechAct.Value =
objProductoE.FechaActProducto
End If
habilitarBotones(False, False, True, True)
HabilitarCajas(True)
End
Sub End
Class
Vb.
8.16.
Vb.
Net
mLogin =
value End Set
End Property
Public Property Password() As String
Get
Return
mPassword End Get
Set(ByVal value As String)
mPassword = value
End Set
End Property
End Class
Clase UsuarioDAO
Imports Conexionbd
Imports Entidades
Imports System.Data
Imports System.Data.SqlClient
Public Class UsuarioDAO
Public daUsuario As SqlDataAdapter
Public cmdUsuario As New SqlCommand
Public dsUsuario As DataSet
Public drUsuario As SqlDataReader
Dim objConexion As New Conexion
Public Function listarUsuario(ByVal login As String) As Usuario
Dim lector As SqlDataReader
Dim objUsuario As Usuario
objUsuario = New Usuario
cmdUsuario.CommandType = CommandType.StoredProcedure
'Nombre procedimiento almacenado
cmdUsuario.CommandText = "SP_Listar_Usuarios"
'obtener la conexion con la base de datos
cmdUsuario.Connection = objConexion.obtenerconexion
With cmdUsuario.Parameters
.Add("@login", SqlDbType.VarChar).Value = login
End With
If objConexion.obtenerconexion.State = ConnectionState.Open Then
objConexion.obtenerconexion.Close()
Else
Vb.
Net
objConexion.obtenerconexion.Open()
End If
lector = cmdUsuario.ExecuteReader
If lector.Read Then
objUsuario.IdUsuario = lector(0)
objUsuario.Login = lector(1)
objUsuario.Password = lector(2)
objUsuario.IdVendedor = lector(3)
End If
Return objUsuario
End Function
End Class
Clase UsuarioNE
Imports Datos
Imports Entidades
Public Class UsuarioNE
Private objUsuarioDAO As UsuarioDAO
Public Sub New()
objUsuarioDAO = New UsuarioDAO
End Sub
Public Function listarUsuario(ByVal login As String) As Usuario Return
objUsuarioDAO.listarUsuario(login)
End Function
End Class
Vb.
Net
Procedimiento AutenticacionUusuario
Sub AutenticacionUsuarios()
Try
Dim objUsuarioE = New Usuario
Dim objUsuarioNE = New
UsuarioNE Dim login As String
login = Me.txtUsuario.Text
Static cuenta As Integer
objUsuarioE = objUsuarioNE.listarUsuario(login)
FrmGenerarPedido.idVendedor = objUsuarioE.IdVendedor
If objUsuarioE.Login = Trim(Me.txtUsuario.Text) And
objUsuarioE.Password = Trim(Me.txtPassword.Text) Then
' el contenido la variable usuario podras utilizarla en cualquier form del
' sistema, para que veas el usuario que ingreso al sistema, por citar un
' ejemplo u otros usos que se le puede dar
MsgBox("Esta Usted ingresando como Operador: " & objUsuarioE.Login)
Me.Hide()
Dim frm As New MDIPrincipal ' luego deber ser FrmPrincipal
frm.Show()
Else
cuenta = cuenta + 1
If cuenta = 3 Then
End Class
Vb.
Vb.
Vb.
End Class
Vb.
Vb.
End Property
End Class
Clase FacturaDAO
Imports Conexionbd
Imports Entidades
Imports System.Data
Imports System.Data.SqlClient
Public Class FacturaDAO
Public daFactura As SqlDataAdapter
Public cmdFactura As New SqlCommand
Public dsFactura As DataSet
Public drFactura As SqlDataReader
Dim objConexion As New Conexion
Public Function AgregarFacturas(ByVal objFacturaE As Facturas) As String
Dim mensaje As String
cmdFactura.CommandType = CommandType.StoredProcedure
cmdFactura.CommandText = "SP_GrabarFactura"
cmdFactura.Connection = objConexion.obtenerconexion
If objConexion.obtenerconexion.State = ConnectionState.Open Then
objConexion.obtenerconexion.Close()
Else
objConexion.obtenerconexion.Open()
End If
With cmdFactura.Parameters
.Add("@Num_Fact", SqlDbType.Int).Value = objFacturaE.Num_Fact
.Add("@IdVendedor", SqlDbType.Int).Value = objFacturaE.IdVendedor
.Add("@IdCliente", SqlDbType.Int).Value = objFacturaE.IdCliente
.Add("@Sub_Total", SqlDbType.Decimal).Value = objFacturaE.Sub_Total
.Add("@Igv", SqlDbType.Decimal).Value = objFacturaE.Igv
.Add("@total", SqlDbType.Decimal).Value = objFacturaE.Total
.Add("@fecha", SqlDbType.Date).Value = objFacturaE.Fecha
.Add("@FgEli", SqlDbType.Bit).Value = 1
End With
Dim registros As Integer
registros = cmdFactura.ExecuteNonQuery()
If registros = 1 Then
mensaje = "Registro guardado correctamente"
Return mensaje
Else
mensaje = "Error en la transaccion"
Return mensaje
End If
cmdFactura.Parameters.Clear()
objConexion.obtenerconexion.Close()
End Function
Public Function listarFacturas() As List(Of Facturas)
Dim lista As New List(Of Facturas)
Dim lector As SqlDataReader
Dim objFactura As Facturas
cmdFactura = New SqlCommand("Sp_ListFacturas", objConexion.obtenerconexion)
lector = cmdFactura.ExecuteReader
While lector.Read
objFactura = New Facturas
objFactura.Num_Fact = lector(0)
objFactura.IdVendedor = lector(1)
objFactura.IdCliente = lector(2)
objFactura.Sub_Total = lector(3)
objFactura.Igv = lector(4)
objFactura.Total = lector(5)
Vb.
Net
objFactura.Fecha = lector(6)
lista.Add(objFactura)
End While
Return lista
End Function
Public Function codFactura() As Integer
Dim codigo As Integer
Dim lector As SqlDataReader
cmdFactura = New
SqlCommand("SP_Generar_Codigo_Factura",
objConexion.obtenerconexion)
lector = cmdFactura.ExecuteReader If
lector.Read Then
codigo = lector(0)
End If
Return codigo
End Function
End Class
Clase DetalleDAO
Imports Conexionbd
Imports Entidades
Imports System.Data
Imports System.Data.SqlClient
Public Class DetalleDAO
Public cmdDetalle As New SqlCommand
Public drDetalle As SqlDataReader
Dim objConexion As New Conexion
Public Function AgregarDetalles(ByVal objDetalleE As Detalle) As String Dim
mensaje As String
cmdDetalle.CommandType =
CommandType.StoredProcedure
cmdDetalle.CommandText = "Sp_GrabarDetalle_Venta"
cmdDetalle.Connection = objConexion.obtenerconexion
If objConexion.obtenerconexion.State = ConnectionState.Open Then
objConexion.obtenerconexion.Close()
Else
objConexion.obtenerconexion.Open()
End If
With cmdDetalle.Parameters
.Add("@Num_Fact", SqlDbType.Int).Value = objDetalleE.Num_Fact
.Add("@IdProducto", SqlDbType.Int).Value = objDetalleE.IdProducto
.Add("@CantidadVenta", SqlDbType.Int).Value = objDetalleE.CantidadVenta
.Add("@PrecioVenta", SqlDbType.Decimal).Value = objDetalleE.PrecioVenta
.Add("@Importe", SqlDbType.Decimal).Value = objDetalleE.Importe
End With
Dim registros As Integer
registros = cmdDetalle.ExecuteNonQuery() If
registros > 0 Then
Else
Vb.
Net
Else
objConexion.obtenerconexion.Open()
End If
Clase FacturaNE
Vb.
Imports Datos
Imports Entidades
Public Class FacturaNE
Private objFacturaDAO As FacturaDAO
Public Sub New()
objFacturaDAO = New FacturaDAO
End Sub
Public Function AgregarFactura(ByVal objFacturaE As Facturas) As
String
Return objFacturaDAO.AgregarFacturas(objFacturaE) End
Function
Clase DetalleNE
Imports Datos
Imports Entidades
Public Class DetalleNE
Private objDetalleDAO As DetalleDAO
Public Sub New()
objDetalleDAO = New DetalleDAO
End Sub
Public Function AgregarDetalles(ByVal objDetalleE As Detalle) As
String
Return objDetalleDAO.AgregarDetalles(objDetalleE) End
Function
Vb.
Imports vb = Microsoft.VisualBasic
Imports Entidades
Imports Negocio
Imports Conexionbd
Imports System.Data.SqlClient
Public Class FrmGenerarPedido
Dim objFacturaE As New Facturas
Dim objFacturaNE As New FacturaNE
Dim objDetalleEn As New List(Of Detalle)
Dim objDetalleNE As New DetalleNE
Dim objProducto As List(Of Producto)
Dim objProductoNE As ProductoNE
Dim objClienteNE As ClienteNE
Dim idFactura As Integer
Dim Facturas, DetalleFac As Boolean
Dim objConexion As New Conexion
Public idVendedor As Integer
Sub cargarProducto()
Dim producto1 As New Producto
objProducto = New List(Of Producto)
objProductoNE = New ProductoNE
objProducto = objProductoNE.listarProductos
cboProducto.DataSource = Nothing
cboProducto.DataSource = objProducto
cboProducto.DisplayMember = "NombreProducto"
cboProducto.ValueMember = "IdProducto"
End Sub
Sub BuscarCliente(ByVal codigo As String)
Dim objClienteNE As ClienteNE
Vb.
Net
objClienteE = objClienteNE.listarClienteDNI(codigo) If
objClienteE.idCliente > 0 Then
Me.txtIdCliente.Text = objClienteE.idCliente
Me.txtDNIC.Text = objClienteE.DNICliente
Me.txtRUC.Text = objClienteE.RUCCliente
Me.txtDireccion.Text = objClienteE.DireccionCliente
MsgBox("Datos No
encontradosss")
Me.txtDNIC.Clear()
Me.txtDNIC.Focus()
End If
End Sub
Vb.
txtIdCliente.Focus()
ElseIf txtCodVendedor.Text = "" Then
MessageBox.Show("Ingrese la Direccin del Cliente", "Atencin", MessageBoxButtons.OK,
MessageBoxIcon.Information)
txtCodVendedor.Focus()
ElseIf Me.dgvDetallePedido.RowCount = 0 Then
MessageBox.Show("Ingrese Productos a la Lista", "Atencin", MessageBoxButtons.OK,
MessageBoxIcon.Information)
txt_cantidad.Focus()
ElseIf
MessageBox.Show("Desea Guardar la Venta?", "Confirmar", MessageBoxButtons.YesNo,
MessageBoxIcon.Information) = Windows.Forms.DialogResult.Yes Then
Try
objFacturaE.Num_Fact = CInt(txtNumFac.Text)
Dim numFacturas As Integer = CInt(txtNumFac.Text)
objFacturaE.IdCliente = CInt(txtIdCliente.Text)
objFacturaE.IdVendedor = CInt(txtCodVendedor.Text)
objFacturaE.Sub_Total = CDec(lbl_vVenta.Text)
objFacturaE.Igv = CDec(lbl_Igv.Text) objFacturaE.Total =
CDec(lbl_pVenta.Text) objFacturaE.Fecha =
CDate(lblFechaVenta.Text)
Next
salidadLista = objDetalleNE.AgregarDetalles1(objDetalleEn)
MsgBox(salidadLista)
'dgvDetallePedido.Rows.Clear()
'dgvDetallePedido.DataSource = objDetalleEn
Btn_Eliminar.Enabled = False
Btn_Limpiar.Enabled = False
Btn_Guardar.Enabled = False
Btn_Imprimir.Enabled = True
MessageBox.Show("Venta Guardado Correctamente", "Felicitaciones", MessageBoxButtons.OK,
MessageBoxIcon.Information) : Exit Sub
Catch ex As Exception
MessageBox.Show("Error al Guardar los Datos" & ex.Message.ToString, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error) : Exit Sub
Finally
End Try
End If
End Sub
Private Sub Verificar_Cajas()
If txt_cantidad.Text = "" Then
txt_cantidad.Focus()
Exit Sub
ElseIf Trim(txt_Descripcion.Text) = "" Then
txt_Descripcion.Focus()
Exit Sub
ElseIf Trim(txt_precio.Text) = "" Then
txt_precio.Focus()
Exit Sub
ElseIf vb.Right(Me.txt_precio.Text, 1) = "." Then
MessageBox.Show("Esto no es un Precio Vlido!!!", "Atencin", MessageBoxButtons.OK,
MessageBoxIcon.Information)
txt_precio.Focus()
Exit Sub
ElseIf Buscar_Producto_Gridview() = False Then
Vb.
Net
MessageBox.Show("El Producto que intenta Agregar ya existe en la Lista" & Chr(13) & "Item
Seleccionado en la Lista", "Atencin", MessageBoxButtons.OK, MessageBoxIcon.Information)
Me.txt_Descripcion.Focus()
Else
Me.dgvDetallePedido.Rows.Add(Me.txtIdProducto.Text, Trim(Me.txt_Descripcion.Text),
txt_cantidad.Text, Me.txt_precio.Text)
Realizar_Calculo()
Limpiar()
Me.txt_cantidad.Focus()
End If
End Sub
Me.dgvDetallePedido.Rows(n).Cells(4).Value = Total.ToString("##,##0.00")
MTotal += Total
Next
lbl_vVenta.Text = MTotal.ToString("##,##0.00")
IGV = (MTotal * Val(txt_igvM.Text)) / 100
lbl_Igv.Text = IGV.ToString("##,##0.00") Total =
MTotal + IGV
lbl_pVenta.Text = Total.ToString("##,##0.00")
'Convertir_Letras()
End Sub
Private Sub FrmGenerarVenta_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles MyBase.Load
lblFechaVenta.Text = Now
txtCodVendedor.Text = idVendedor.ToString
cargarVendedor(CInt(txtCodVendedor.Text))
cargarProducto()
End Sub
Vb.
Else
MsgBox("Ingrese el DNI del cliente")
End If
Catch ex As Exception
MsgBox("Dato no encontrado")
End Try
End Sub
Private Sub btnNuevo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
btnNuevo.Click
Try
Dim objFacturaNE = New FacturaNE
Me.txtNumFac.Text = objFacturaNE.CodFactura()
Catch ex As Exception
MsgBox(ex.Message
)
End Try
End Sub
End Class
Vb.
Vb.
1
2
Vb.