Click here to load reader

Ejemplo de Acceso a Datos Con Una Base de Access

  • View
    421

  • Download
    6

Embed Size (px)

Text of Ejemplo de Acceso a Datos Con Una Base de Access

Ejemplo de acceso a datos con una base de AccessPublicado: 13/Jun/2002 Actualizado: 19/Abr/2003

En este ejemplo veremos cmo acceder a una base de datos de Access, usando los objetos del espacio de nombres OLEDB. Los conceptos que se tratarn sern los siguientes: - Crear una conexin a la base de datos. - Mostrar las tablas de la base de datos indicada. - Mostrar las columnas (o campos) de una tabla. - Crear un DataAdapter para acceder a los datos devueltos por una consulta. - Crear un DataSet basado en los datos asociados al DataAdapter. - Crear nuevos registros. - Modificar registros. - Eliminar registros. - Mostrar el contenido de la tabla en un control ListView.

Nota del 20/Jul/2002: He recibido varios mensajes diciendo que les daba error el ejemplo aqu puesto, he probado y efectivamente, me da error... le he puesto una captura (en el mtodo Conecta) y me muestra un error de que la cadena SQL no es vlida, pero si continuo, funciona bien. Aunque, he de aclarar que ese error se produce en el cdigo del ejemplo adjunto, si se deja el texto que por defecto tiene la caja de textos en la que se indica la cadena SQL, si se deja en blanco, no se produce error. He modificado el cdigo aqu mostrado, el cual puedes ver pulsando este link. Nota del 06/Ene/2006: Si este ejemplo te parece muy complicado, puedes ver otro ms simple.

Los objetos a usar en el proyecto.Los objetos que vamos a usar en este ejemplo, en su gran mayora residen en el espacio de nombres System.Data.OleDb, aunque tambin se usarn objetos genricos (DataSet, DataRow, DataColumn ) que residen en System.Data. Para que nos sea ms fcil declarar esos objetos, importaremos el espacio de nombres System.Data.OleDb y dado que usaremos procedimientos genricos, estos los incluiremos en un mdulo, al que llamaremos: ADONETUtil, veamos el cdigo con las declaraciones de los objetos que usaremos en el proyecto:

'----------------------------------------------------------------------------' Prueba de acceso a base de tipo Access con ADO.NET (25/May/02) ' Mdulo con las declaraciones de objetos ' ' Guillermo 'guille' Som, 2002 '-----------------------------------------------------------------------------

Imports System.Data.OleDb

Module ADONETUtil Friend dbConnection As OleDbConnection ' Friend dbDataTable As Data.DataTable Friend dbDataSet As Data.DataSet Friend dbDataAdapter As OleDbDataAdapter ' Friend CadenaConexion As String Friend CadenaSelect As String ' Friend ArchivoDatos As String Friend NombreTabla As String = "Tabla1" ' La variable CadenaConexion ser la cadena con la que conectaremos a la base de datos. La variable CadenaSelect ser el cdigo SQL que usaremos para acceder a la tabla de esa base de datos. La variable ArchivoDatos ser el nombre completo de la base de datos (Path incluido). La variable NombreTabla ser el nombre que usaremos para identificar a los datos que cargaremos en el objeto DataAdapter, ese nombre no tiene nada que ver con el nombre de la tabla a la que vamos a acceder, es slo un nombre que usaremos con los distintos objetos de ADO.NET.

Conectar a una base de datos del tipo AccessPara conectar a la base de datos y crear los objetos que cargarn la tabla (definida en la consulta SQL contenida en la variable CadenaSelect), vamos a crear un procedimiento en el mismo mdulo ADONETUtil:

Friend Sub Conectar( Optional ByVal nombreBaseDatos As String = "", _ Optional ByVal commandString As String = "")

If nombreBaseDatos = "" Then nombreBaseDatos = ArchivoDatos End If ArchivoDatos = nombreBaseDatos If ArchivoDatos = "" Then Exit Sub End If ' If CadenaSelect = "" Then CadenaSelect = "SELECT * FROM Table1" End If If commandString = "" Then commandString = CadenaSelect End If CadenaSelect = commandString ' CadenaConexion = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" ArchivoDatos ' Try dbConnection = New OleDbConnection(CadenaConexion) Catch e As Exception MessageBox.Show( "Error al crear la conexin:" & vbCrLf & e.Message) Exit Sub End Try ' dbConnection.Open() ' dbDataSet = New Data.DataSet() ' dbDataAdapter = New OleDbDataAdapter(CadenaSelect, dbConnection) ' &

Dim commandBuilder As New OleDbCommandBuilder(dbDataAdapter) ' dbDataAdapter.MissingSchemaAction = MissingSchemaAction.AddW ithKey 'dbDataAdapter.Fill(dbDataSet, NombreTabla) ' Cambio para comprobar que funciona, (20/Jul/02) ' En la versin Architect me da error, pero continua funcionando. ' Aunque el error lo da si se pasa una es correcta, cadena SQL que no

' por ejemplo, cuando se inicia la aplicacin y se deja el texto por defecto. Try dbDataAdapter.Fill(dbDataSet, NombreTabla) Catch ex As Exception MessageBox.Show("Error en Fill:" & vb CrLf & ex.Message) End Try ' End Sub A este procedimiento se le pueden indicar dos parmetros: El primero indicar el nombre de la base de datos (path incluido), mientras que el segundo ser la instruccin SQL que nos permitir acceder a la tabla. Cuando veamos el cdigo del formulario, tendremos ocasin de ver cmo se llama a este procedimiento. Lo que aqu tenemos que destacar es lo siguiente: La cadena de conexin que tenemos que usar para conectar con la base de datos es igual que la usada en las versiones anteriores de ADO, en esto no ha cambiado nada; se le indica el tipo de proveedor y el nombre de la base de datos. Creamos un nuevo objeto del tipo DataSet, que ser el que nos permita acceder a los datos. Creamos un objeto del tipo DataAdapter, este ser el que realmente nos permita acceder a los datos fsicos de la base de datos, primero para rellenar el DataSet y posteriormente para actualizar los cambios realizados en la base de datos. Es importante saber que los datos contenidos en el objeto DataSet estn en memoria y se acceden y manipulan de forma independiente, sin ninguna relacin directa con la base de datos original. Para que los cambios realizados en memoria se puedan reflejar de forma permanente en la base de datos, tenemos que usar el objeto DataAdapter. Una vez creado el DataAdapter, al que se le indica la cadena de seleccin y la cadena de conexin o el objeto del tipo Connection. En este caso, le he indicado el objetoConnection, pero si no queremos crear una conexin permanente, tambin podemos usar la misma cadena de conexin usada para crear el objeto Connection en lugar de ese objeto.

Para poder realizar cambios en la base de datos, hay que indicarle al DataAdapter los comandos SQL que habra que usar para aadir, modificar y eliminar, pero esos comandos se pueden crear de forma automtica creando un nuevo objeto del tipo CommandBuilder, al que se le pasar como parmetro el adaptador que usar dichos comandos, en realidad el objeto CommandBuilder no se usa nada ms que para que de esta forma se asignen dichos comandos de actualizacin de datos. Si la tabla a la que queremos acceder tiene clave principal (cosa que es comn o debera serlo en todas las tablas), le indicamos mediante la asignacin a la propiedadMissingSchemaAction el valor de aadir con clave. Si no hacemos esta asignacin y la tabla tiene un campo que se incrementa automticamente, no podramos crear varios registros (o filas) en memoria y despus actualizar esas nuevas filas de forma permanente, ya que nos dara un error de que hay duplicidad en el campo (o columna) autoincremental. Por ltimo, llenamos el objeto DataSet con los datos del DataAdapter, el segundo parmetro es el nombre que le vamos a dar a la tabla virtual (la que se crea en memoria), si no le damos un nombre a esa tabla virtual del DataSet, se asignar de forma predeterminada con el nombre Table. Es conveniente asignar un nombre, ya que un objeto DataSet permite tener en memoria distintos datos, de la misma o de otras tablas o consultas. Ese nombre ser el que usaremos para acceder a esos datos en memoria, ya que todos los accesos al contenido del DataSet, como he comentado antes, se realizan de forma desconectada, es decir sin relacin ninguna con la base de datos fsica.

Los nombres de las tablas de una base de datosVamos a crear una funcin que devuelva una matriz (o array) del tipo String, con los nombres de las tablas de la base de datos.

Friend Function NombresTablas() As String() Dim nomTablas() As String Dim dataTable As Data.DataTable Dim dbNull As System.DBNull Dim restrictions() As Object = {dbNull, dbNull, dbNull, "TABLE"} Dim i As Integer ' If dbConnection Is Nothing Then dbConnection = New Data.OleDb.OleDbConnection(CadenaConexion) End If If dbConnection.State ConnectionState.Open Then dbConnection.Open() End If

' dataTable = dbConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, restrictions) i = dataTable.Rows.Count - 1 If i > -1 Then ReDim nomTablas(i) For i = 0 To dataTable.Rows.Count - 1 nomTablas(i) = dataTable.Rows(i).Item( "TABLE_NAME" ).ToString() Next End If ' Return nomTablas End Function Antes de llamar a esta funcin tendremos que tener asignada la cadena de conexin o, mejor an, creada la conexin a la base de datos. Eso es lo que se hace en las primeras lneas, si el objeto del tipo Connection no est creado, se crea un nuevo objeto, usando la cadena de conexin. En caso de que est creado el objeto, se comprueba si est abierta dicha conexin, de no ser as, se abre. A continuacin asignamos un objeto del tipo DataTable con el "esquema" de las tablas contenidas en la base de datos a la que apunta el objeto Connection. El "truco" para conseguir los nombres de las tablas, est en el array restrictions, particularmente en el cuarto elemento: "TABLE". Recorremos el contenido del objeto DataTable y accedemos a cada una de las filas cuyo elemento contenga la cadena "TABLE_NAME", el cual nos dar el nombre de cada una de las tablas. Ese nombre lo asignamos a cada uno de los elementos del array que estamos usando de forma interna, el cual ser el que la funcin devuelva.

Los nombres de los campos (o columnas) de una tablaPara saber los nombres de los campos o columnas de una tabla, usaremos el contenido del objeto DataSet que hace referencia a la tabla que hemos cargado mediante elDataAdapter, aunque tambin podra servirnos para acceder a cualquier tabla virtual contenida en el DataSet. Tambin vamos a crear una funcin que devuelva una matriz del tipo String:

Friend Function NombresColumnas() As String() Dim columna As Data.DataColumn

Dim i, j As Integer Dim nomCol() As String ' j = dbDataSet.Tables(NombreTabla).Columns.Count - 1 ReDim nomCol(j) For i = 0 To j columna = dbDataSet.Tables(NombreTabla).Columns(i) nomCol(i) = columna.ColumnName Next Return nomCol End Function Creo que el cdigo es bastante auto-explicativo y no necesita ms aclaracin.

Asignar la cabecera de un control ListView con los nombres de las columnas o campos de una tablaPara terminar con el cdigo del mdulo ADONETUtil, vamos a ver unos mtodos que usaremos para asignar las columnas (o cabecera) de un ListView con los nombres de las columnas o campos de la tabla que vamos a utilizar. El mtodo se llama AsignarCabeceraLista y tendr dos implementaciones, una indicando slo el nombre del ListView y la otra en la que adems se indicar un controlComboBox en el cual se asignarn tambin esos nombres de las columnas de la tabla.

Friend Sub AsignarCabece raLista(ByVal ListView1 As ListView) Dim columna As Data.DataColumn Dim i, j As Integer ' With ListView1 .View = View.Details .FullRowSelect = True .GridLines = True .LabelEdit = False .HideSelection = False .Columns.Clear()

End With ' Dim lasColumnas() As String lasColumnas = NombresColumnas() ' If Not lasColumnas Is Nothing Then For i = 0 To lasColumnas.Length - 1 ListView1.Columns.Add(lasColumnas(i), 100, HorizontalAlignment.Left) Next End If ' End Sub

Friend Sub AsignarCabeceraLista( ByVal ListView1 As ListView, _ ByVal cboCampos As ComboBox) Dim i As Integer ' AsignarCabeceraLista(ListView1) cboCampos.Items.Clear() For i = 0 To ListView1.Columns.Count - 1 cboCampos.Items.Add(ListView1.Columns(i).Text) Next ' If cboCampos.Items.Count > 0 Then cboCampos.SelectedIndex = 0 End If End Sub Creo que tampoco necesita explicacin, ya que lo nico que se hace es llamar a la funcin NombresColumnas y el contenido de ese array es el que se asigna a la cabecera del ListView que se ha indicado en el parmetro. En cuanto a la segunda implementacin, se asigna al control ComboBox pasado como parmetro esos mismos nombres. Cuando veamos el cdigo de los formularios, sabremos cuando usar una u otra versin de este mtodo.

Llenar un ListView con el contenido de una tabla

El siguiente mtodo del mdulo ADONETUtil rellenar un control ListView con los datos de la tabla cargada en el objeto DataSet.

Friend Sub LLenarLista( ByVal unListView As ListView) Dim i As Integer Dim lwItem As ListViewItem Dim fila As Data.DataRow ' unListView.Items.Clear() ' For Each fila In dbDataSet.Tables(NombreTabla).Rows For i = 0 To unListView.Columns.Count - 1 If i = 0 Then lwItem = unListView.Items.Add(fila(i).ToString) lwItem.Tag = fila Else lwItem.SubItems.Add(fila(i).ToString) End If Next Next End Sub El cdigo es tambin bastante simple, slo quiero aclarar un detalle: La asignacin del objeto fila al TAG del elemento del ListView. Realmente no es necesario, pero yo lo utilizo esa fila para acceder a cada uno de los registros de la tabla, ya que al modificar los datos, slo los reflejaremos en el contenido del ListView y de esa forma sabremos a que fila estamos accediendo. Cuando actualicemos los datos, usaremos el objeto que hemos guardado en la propiedad Tag del objetoListViewItem, y ese mismo objeto ser el que usaremos para eliminar una fila del DataSet.

Para terminar con el cdigo del mdulo, una funcin que usaremos para mostrar informacin de la base de datos a la que estamos accediendo. En este caso es una funcin que recibe como parmetro un path completo y devuelve slo el nombre de la base de datos:

Friend Function NombreBase( ByVal path As String) As String

' Devolver slo el nombre de la base de datos Dim i As Integer ' i = path.LastIndexOf( "\") If i > -1 Then Return path.Substring(i + 1) End If End Function Aqu se podran haber usado funciones "clsicas" de Visual Basic, como InStr o Mid, pero he preferido usar sus equivalentes de VB.NET, entre otras cosas porque forman parte del objeto String. En el caso de LastIndexOf, busca la ltima ocurrencia de la cadena indicada en el parmetro, si dicha cadena no forma parte del objeto, (en este caso la variable path), se devuelve un valor -1 y en caso de que si est, se devuelve la posicin, pero hay que tener en cuenta que la primera posicin est representada por el valor cero.

El formulario principalEste es el aspecto del formulario principal (Form1) en tiempo de diseo:

El formulario principal en tiempo de diseo Este formulario permitir que se arrastre una base de datos y ese nombre se asignar a la caja de textos del nombre de la base de datos. Los controles tienen asignados los valores de la propiedad Anchor para que se ajusten al tamao que el usuario quiera darle al formulario, esos detalles podremos verlo en el cdigo completo, ya que aqu slo mostrar la parte

que realmente interesa, es decir lo que est relacionado con el acceso a la base de datos. Empecemos por el cdigo del botn " Mostrar tablas" y el evento producido cuando se selecciona una tabla del ComboBox:

Private Sub btnAbrirBase_Click( ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnAbrirBase.Click ' Conectar(txtNombreBase.Text, txtSelect.Text) ' ' Dim nomTablas() As String Dim i As Integer ' nomTablas = NombresTablas() cboTablas.Items.Clear() If Not nomTablas Is Nothing Then For i = 0 To nomTablas.Length - 1 cboTablas.Items.Add(nomTablas(i)) Next End If If cboTablas.Items.Count > 0 Then cboTablas.SelectedIndex = 0 End If End Sub

Private Sub cboTablas_SelectedIndexChanged( ByVal sender As System.Object, _ ByVal e As System.EventA rgs) _ Handles cboTablas.SelectedIndexChanged txtSelect.Text = "SELECT * FROM " & cboTablas.Text ' '' Si se quieren mostrar individualmente los nombres de los campos 'Dim lasColumnas() As String

'Dim s As String, i As Integer '' 'CadenaSelect = txtSelect.Text 'lasColumnas = NombresColumnas() 'For i = 0 To lasColumnas.Length - 1 ' s &= lasColumnas(i) & ", "

'Next '' Quitar la ltima coma 'i = s.LastIndexOf(", ") 's = s.Substring(0, i) 's = "SELECT " & s & " FROM " & cboTablas.Text 'txtSelect.Text = s End Sub El primer procedimiento intercepta la pulsacin en el botn y asigna los nombres de las tablas en el combo. El segundo, simplemente crea la cadena SQL que se usar para acceder a dicha tabla. El cdigo que est comentado sirve para mostrar los nombres de los campos o columnas de forma individual. Cuando pulsamos en el botn " Mostrar", se muestra el contenido de la tabla indicada, informacin que se obtiene del DataSet que contiene los datos en memoria. Aunque, el cdigo mostrado, realmente refresca esa informacin, esto lo he hecho as para que al volver de modificar los datos, se pueda comprobar que los datos realmente se han guardado en la base de datos.

Private Sub btnMostrar_Click( ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnMostrar.Click ' With ListView1 .View = View.Details .FullRowSelect = True .GridLines = True .LabelEdit = False .HideSelection = False .Columns.Clear() End With

' ' Volver a reconectar para actualizar los datos desde la base If Not dbConnection Is Nothing Then dbConnection.Close() End If Conectar(txtNombreBase.Text, txtSelect.Text) ' AsignarCabeceraLista(ListView1) LLenarLista(ListView1) End Sub Como podemos comprobar, aqu se llaman a los mtodos del mdulo ADONETUtil, por tanto al principio del cdigo del formulario debemos hacer la importacin del espacio de nombres de ese mdulo para no tener que especificarlo cada vez que queramos acceder a cualquiera de los procedimientos o variables en el declarado: ' Importamos el mdulo con las declaraciones de los objetos a usar Imports ADONET1.ADONETUtil ADONET1 es el nombre del "espacio de nombres" (Namespace) de este proyecto. Para acabar con el cdigo de este formulario, veamos los eventos que se producen al cargarse el formulario (Load) y al cerrarse (Closing), adems del evento producido al pulsar en el botn " Mostrar", el cual mostrar el formulario en el que se editan los datos de la tabla indicada.

Private Sub Form1_Load( ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load Me.txtNombreBase.Text = "E:\gsCodigo\Vb6\Pruebas\Bases\db2000NET.mdb" ' ArchivoDatos = txtNombreBase.Text CadenaConexion = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" ArchivoDatos ' With ListView1 .View = View.Details &

.FullRowSelect = True .GridLines = True .LabelEdit = False End With ' cboTablas.Text = "" End Sub

Private Sub Form1_Closing( ByVal sender As Object, _ ByVal e As System.ComponentModel.CancelEventArgs) _ Handles MyBase.Closing ' Cerrar la conexin Try If dbConnection.State = ConnectionState.Open Then dbConnection.Close() End If Catch End Try End Sub

Private Sub btnModificar_Click( ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnModificar.Click Dim f2 As New Form2() With f2 .DataSource = txtNombreBase.Text .CommandString = txtSelect.Text .ShowDialog() End With btnMostrar_Click(btnMostrar, e) End Sub En el evento Load, asignamos los valores iniciales, en el evento Closing, comprobamos si tenemos la conexin abierta y de ser as la cerramos, debido a que puede ser que se cierre el formulario sin necesidad de haber creado dicho objeto, interceptamos el error que se pudiera producir. Por otro lado, cuando pulsamos en el botn Modificar, creamos una nueva instancia del formulario en el que modificaremos la informacin y

asignamos los valores de la base de datos y la cadena SQL que usaremos para conectar, esto lo hago as por si se pulsa en dicho botn sin haber creado la conexin.

El formulario de edicin de datosPara terminar con este ejemplo de acceso a datos usando ADO.NET, veamos el formulario que usaremos para modificar la informacin de la base de datos. El aspecto del formulario (FORM2) ser el mostrado en la siguiente imagen:

El formulario de introduccin de datos En este formulario, los controles tambin estn "anclados" para que se adapten al tamao que el usuario quiera darle al formulario. Empecemos por las variables o propiedades que este formulario expone al mundo externo:

' Importamos el mdulo con las declaraciones de los objetos a usar Imports ADONET1.ADONETUtil

Public Class Form2 Inherits System.Windows.Forms.Form

Friend DataSource As String Friend CommandString As String '

Private lwItemActual As ListViewItem Tambin usamos el Imports para poder usar los procedimientos del mdulo ADONETUtil y declaramos dos propiedades: DataSource y CommandString, las cuales usaremos para acceder a la base de datos. La variable lwItemActual har referencia al elemento del ListView que est actualmente seleccionado. En el evento Load del formulario, se asignarn algunos valores por defecto y se mostrar el contenido de la tabla indicada en el ListView:

Private Sub Form2_Load( ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load Me.txtCampo1.Text = "" ' ' para usar este formulario como formulario inicial If DataSource = "" Then DataSource = "E:\gsCodigo\Vb6\Pruebas\Bases\db2000NET.mdb" End If If CommandString = "" Then CommandString = "SELECT * FROM Table1" End If ' lblInfo.Text = "Base: " & NombreBase(DataSource) & ", Select: " & CommandString ' If dbConnection Is Nothing Then Conectar(DataSource, CommandString) End If ' AsignarCabeceraLista(ListView1, cboCampos) LLenarLista(ListView1) ' Me.AcceptButton = btnAsignar End Sub

Cuando seleccionamos un nuevo elemento del ListView, se asigna la variable que contiene el elemento actual y se muestra la informacin o datos de dicha fila.

Private Sub ListView1_SelectedIndexChanged( ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles ListView1.SelectedIndexChanged Try lwItemActual = ListView1.SelectedItems(0) Catch End Try End Sub Private Sub ListView1_Click( ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles ListView1.Click, cboCampos.SelectedIndexChanged Try lwItemActual = ListView1.SelectedItems(0) MostrarCampo() Catch End Try End Sub Como podemos comprobar, el procedimiento ListView1_Click realmente intercepta dos eventos, el evento Click del ListView y el evento SelectedIndexChanged del Combo, de forma que se muestre la informacin del campo seleccionado en el ComboBox. De eso se encarga el procedimiento MostrarCampo:

Private Sub MostrarCampo() Dim i As Integer ' Try i = cboCampos.SelectedIndex If i = 0 Then txtCampo1.Text = lwItemActual.Text ElseIf i > -1 Then

txtCampo1.Text = lwItemActual.SubItems(i).Text End If Catch End Try End Sub Este procedimiento simplemente muestra el contenido del campo que est seleccionado en el control ComboBox.

Asignar los datosCuando pulsamos en el botn Asignar, el cual hemos asignado como botn "Aceptar" del formulario, es decir el que tomar el foco cuando pulsemos la tecla Intro, se asignarn los cambios realizados al campo (o columna) que estamos editando:

Private Sub AsignarCampo( ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnAsignar.Click ' Asignar al ListView el campo modificado Dim i As Integer ' i = cboCampos.SelectedIndex If i = 0 Then lwItemActual.Text = txtCampo1.Text ElseIf i > -1 Then lwItemActual.SubItems(i).Text = txtCampo1.Text End If End Sub

Eliminar una filaCuando pulsamos en el botn Eliminar, borramos la fila seleccionada del ListView y tambin esa misma fila del DataSet, y como coment anteriormente, en la propiedad Tagdel elemento del ListView tenemos una referencia a la fila de datos, por tanto usamos ese objeto para eliminar la

fila de la coleccin Rows del objeto DataSet, ya que el mtodo Remove de la coleccin Rows acepta como parmetro un objeto del tipo DataRow:

Private Sub btnEliminar_Click( ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnEliminar.Click ' Eliminar la fila indicada Dim fila As Data.DataRow ' fila = CType(ListView1.SelectedItems(0).Tag, Data.DataRow) dbDataSet.Tables(NombreTabla).Rows.Remove(fila) ListView1.Items.Remove(ListView1.SelectedItems(0)) End Sub

Crear una nueva fila (o registro)Para crear un nuevo registro (o fila), tendremos que asignar unos valores nulos o por defecto a una nueva fila creada en la memoria, despus esa fila la aadiremos a la tabla que mantenemos en el DataSet. Debido a que algunos campos no permiten valores nulos, tendremos que tener ese detalle en cuenta y de ser as, asignaremos un valor adecuado al tipo de datos de cada una de las columnas (o campos) del registro que hemos creado, esto lo conseguimos comprobando el tipo de datos de cada una de las columnas de la nueva fila. Hay que tener en cuenta que los tipos de datos se guardan usando el que se define en .NET Framework, no los tipos que utiliza Visual Basic, por tanto, para saber si el tipo de una columna es del tipo Integer, tendremos que usar System.Int32, de todas formas, para saber el tipo de dato, (que lo da la propiedad DataType del objeto DataColumn), he utilizado la conversin a cadena generada por ToString, por lo que dicho tipo se convierte en el formato "System.Tipo", veamos el cdigo para aclarar todo este lo:

Private Sub btnNuevo_Click( ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnNuevo.Click ' Aadir una nueva fila (o registro)

Dim fila As Data.DataRo w Dim i As Integer Dim lwItem As ListViewItem Dim columna As Data.DataColumn ' fila = dbDataSet.Tables(NombreTabla).NewRow fila.BeginEdit() For i = 0 To dbDataSet.Tables(NombreTabla).Columns.Count columna = dbDataSet.Tables(NombreTabla).Columns(i) 'Debug.WriteLine(columna.DataType.ToString) If columna.AutoIncrement = False Then Select Case columna.DataType.ToString Case "System.String" fila(i) = columna.ColumnName Case "System.Boolean" fila(i) = False Case "System.Byte" , "System.SByte" fila(i) = CByte(0) Case "System.Char" fila(i) = " "c Case "System.DateTime" , "System.TimeSpam" fila(i) = Now Case "System.Decimal" , "System.Double" , "System.Single" fila(i) = 0 Case Else 'Case "System.Int32","System.UInt32" ' fila(i) = 0 - 1

If columna.DataType.ToString.IndexOf( "System.Int" ) > -1 Then fila(i) = 0 ElseIf columna.DataType.ToString.IndexOf( "System.UInt" ) > -1 Then fila(i) = 0 End If End Select End If

Next fila.EndEdit() ' Aadir la fila a la tabla dbDataSet.Tables(NombreTabla).Rows.Add(fila) ' ' Mostrar la nueva fila en el ListView For i = 0 To ListView1.Columns.Count - 1 If i = 0 Then lwItem = ListView1.Items.Add(fila(i).ToString) lwItem.Tag = fila Else lwItem.SubItems.Add(fila(i).ToString) End If Next ' End Sub Lo que en este evento hacemos es crear una nueva fila mediante el mtodo NewRow, asignamos los campos (o columnas) de dicha fila y la aadimos a la coleccin Rows de la tabla. Hay que tener en cuenta que al crear una nueva fila con NewRow no se aade a la coleccin de filas (o registros), simplemente se devuelve un objeto que est preparado para que se le asignen los datos correspondientes. Antes de asignar cada una de las columnas, comprobamos si dicha columna est marcada como autoincremental, de ser as, no asignamos nada, ya que es el propio DataAdapter el que se encarga de asignar el valor de dicha columna. En este punto quiero hacer una aclaracin, debido a que los datos los estamos asignando a un objeto que mantiene la informacin en la memoria, si existen varias aplicaciones que acceden a la misma base de datos y cada una de ellas crea nuevas filas, el valor asignado al campo (o columna) AutoIncrement puede que no sea el que definitivamente tenga en la base de datos. Por tanto, debemos tener esto presente si el valor asignado a esa columna lo utilizamos para otros menesteres. Una vez que hemos aadido la nueva fila a la tabla, asignamos el contenido de la misma al ListView y tambin asignamos a la propiedad Tag una referencia a dicha fila.

Guardar la informacin en la base de datosPor ltimo vamos a ver cmo pasar la informacin mantenida en la memoria a la base de datos, con idea de que los cambios realizados se

queden guardados permanentemente. Esto lo hacemos cuando el usuario pulsa en el botn de " Actualizar Base" y el cdigo usado es el siguiente:

Private Sub btnActualizarBase_Click( ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnActualizarBase.Click ' Actualizar la base de datos con los cambios realizados Dim fila As Data.DataRow Dim i, j As Integer Dim lwItem As ListViewItem Dim columna As Data.DataColumn ' lblInfo.Tag = lblInfo.Text lblInfo.Text = "Actualizando los datos..." lblInfo.Refresh() Try For i = 0 To ListView1.Items.Count - 1 lwItem = ListView1.Items(i) fila = CType(ListView1.Items(i).Tag, Data.DataRow) fila.BeginEdit() j = 0 For Each columna In dbDataSet.Tables(NombreTabla).Columns If j = 0 Then If columna.AutoIncrement = False Then fila(j) = lwItem.Text End If Else If columna.AutoIncrement = False Then fila(columna.ColumnName) = lwItem.SubItems(j).Text End If End If ' j += 1

Next fila.EndEdit() Next ' ' dbDataAdapter.Update(dbDataSet, NombreTabla) dbDataSet.AcceptChanges() ' ' lblInfo.Text = CStr(lblInfo.Tag) Catch errActualizar As Exception lblInfo.Text = errActualizar.Message MsgBox(errActualizar.Message) End Try End Sub En este procedimiento actualizamos la informacin de cada una de las filas, para ello usamos el objeto almacenado en la propiedad Tag de cada uno de los elementos delListView que como recordars era en realidad una referencia a cada una de las filas de la tabla, (realmente un objeto del tipo DataRow). Recorremos cada una de las columnas y asignamos slo los datos si no es una columna del tipo AutoIncrement. La llamada a los mtodos BeginEdit y EndEdit de cada fila es para que no se produzcan los eventos asociados a un objeto de este tipo, no son realmente necesarios para poder cambiar los contenidos de las columnas. Una vez que hemos asignado todos los datos del ListView, llamamos al mtodo Update del DataAdapter, este mtodo es el que realmente hace que los datos se guarden fsicamente en la base de datos. Despus llamamos al mtodo AcceptChanges del objeto DataSet para que "sepa" que hemos aceptado la nueva informacin y marque la informacin de forma que sean iguales a los datos que tiene l a base de datos real. Y esto es todo... que no es poco... en otras ocasiones veremos cmo acceder a los datos de una base de datos mediante controles enlazados y con un DataGrid que es en realidad la forma ms fcil de hacerlo. Realmente si hubisemos usado ese control, no tendramos que haber escrito la mayora del cdigo que he mostrado, pero como se que hay gente que le gusta tener un control "casi" total sobre cmo se accede a la informacin... pues eso, que aqu est la forma "difcil" de hacerlo y ya habr ocasin de ver la forma "fcil". En otra ocasin, veremos este mismo cdigo aplicado a una base de datos de SQL Server. Nota 19/Abr/2003: Esa ocasin ya ha llegado, sigue este link para el ejemplo de SQL Server.

Nos vemos. Guillermo Introducir datos desde un textbox a una base access en vb.net

La idea basica es utilizar un 'bindingsource' y un commandbuilder para tu adataptador de datos, a partir de este concepto es tan simple como aadir un 'datarow' o registro a tu tabla de datos 'datatable' cada vez que pulsamos 'enter' y la longitud de los datos introducidos es mayor de cero. Posteriormente para actualizar o aadir los registros del 'datatable' a la BD de access utilizaremos el mandato 'update' (al pulsar un boton en nuestro caso), o asociado al momento que consideres oportuno. Puedes descargarte este ejemplo haciendo click en 'attachments'Imports System.Data.OleDb Imports System.Data.DataRow Public Class Form1 Private MiConexion As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=|DataDirectory|\bd1.mdb") Private MiAdaptador As New OleDbDataAdapter("SELECT * FROM Nombres", MiConexion) Private MiDataSet As New DataSet() Private MiEnlazador As New BindingSource Private Sub Form1_KeyPress(ByVal sender As Object, ByVal e As System.Windows. Forms.KeyPressEventArgs) Handles Me.KeyPress If (e.KeyChar = Chr(Keys.Enter)) And (Me.TextBox1.Text.Length > 0) Then Dim nombre As DataRow nombre = MiDataSet.Tables(0).NewRow() nombre("Nombre") = TextBox1.Text MiDataSet.Tables(0).Rows.Add(nombre) Me.TextBox1.Text = "" Me.ComboBox1.SelectedIndex = Me.ComboBox1.Items.Count - 1 End If End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.Event Args) Handles MyBase.Load Dim commandbuilder As New OleDb.OleDbCommandBuilder(Me.MiAdaptador) MiConexion.Open() MiAdaptador.Fill(MiDataSet) MiEnlazador.DataSource = MiDataSet.Tables(0) Me.ComboBox1.DataSource = MiEnlazador Me.ComboBox1.DisplayMember = "Nombre" Me.ComboBox1.ValueMember = "Id" Me.TextBox1.Select() End Sub Private Sub Guardar(ByVal sender As System.Object, ByVal e As System.EventArgs ) Handles Button1.Click Me.MiAdaptador.Update(CType(Me.MiEnlazador.DataSource, DataTable)) End Sub

Es

Line With Band DemoNOTE: The code on this page is for ZedGraph version 5. You can view the code for version 4 here.

Sample Code in C#// Call this method from the Form_Load method, passing your ZedGraphControl public void CreateChart( ZedGraphControl zgc ) { GraphPane myPane = zgc.GraphPane; // Set the title and axis myPane.Title.Text = "Line myPane.XAxis.Title.Text = myPane.YAxis.Title.Text = // Enter double[] double[] double[] labels Graph with Band Demo"; "Sequence"; "Temperature, C";

s ssome random data values y = { 100, 115, 75, 22, 98, 40, 10 }; y2 = { 90, 100, 95, 35, 80, 35, 35 }; y3 = { 80, 110, 65, 15, 54, 67, 18 };

double[] x = { 100, 200, 300, 400, 500, 600, 700 }; // Fill the axis background with a color gradient myPane.Chart.Fill = new Fill( Color.FromArgb( 255, 255, 245 ), Color.FromArgb( 255, 255, 190 ), 90F ); // Generate a red curve with "Curve 1" in the legend LineItem myCurve = myPane.AddCurve( "Curve 1", x, y, Color.Red ); // Make the symbols opaque by filling them with white myCurve.Symbol.Fill = new Fill( Color.White ); // Generate a blue curve with "Curve 2" in the legend myCurve = myPane.AddCurve( "Curve 2", x, y2, Color.Blue ); // Make the symbols opaque by filling them with white myCurve.Symbol.Fill = new Fill( Color.White ); // Generate a green curve with "Curve 3" in the legend myCurve = myPane .AddCurve( "Curve 3", x, y3, Color.Green ); // Make the symbols opaque by filling them with white myCurve.Symbol.Fill = new Fill( Color.White ); // Manually set the x axis range myPane.XAxis.Scale.Min = 0; myPane.XAxis.Scale.Max = 800; // Display the Y axis grid lines myPane.YAxis.MajorGrid.IsVisible = true; myPane.YAxis.MinorGrid.IsVisible = true; // Draw a box item to highlight a value range BoxObj box = new BoxObj( 0, 100, 1, 30, Color.Empty, Color.FromArgb( 150, Color.LightGreen ) ); box.Fill = new Fill( Color.White, Color.FromArgb( 200, Color.LightGreen ), 45.0F ); // Use the BehindAxis zorder to draw the highlight beneath the grid lines box.ZOrder = ZOrder.E_BehindCurves; // Make sure that the boxObj does not extend outside the chart rect if the chart is zoomed box.IsClippedToChartRect = true; // Use a hybrid coordinate system so the X axis always covers the full x range // from chart fraction 0.0 to 1.0 box.Location.CoordinateFrame = CoordType.XChartFractionYScale; myPane.GraphObjList.Add( box ); // Add a text item to label the highlighted range TextObj text = new TextObj( "Optimal \nRange", 0.95f, 85, CoordType.AxisXYScale, AlignH.Right, AlignV.Center ); text.FontSpec.Fill.IsVisible = false; text.FontSpec.Border.IsVisible = false; text.FontSpec.IsBold = true;

text.FontSpec.IsItalic = true; text.Location.CoordinateFrame = CoordType.XChartFrac tionYScale; text.IsClippedToChartRect = true; myPane.GraphObjList.Add( text ); // Fill the pane background with a gradient myPane.Fill = new Fill( Color.WhiteSmoke, Color.Lavender, 0F ); // Calculate the Axis Scale Ranges zgc.AxisChange(); }

S

l

i VB

' Call this method from the Form_Load method, passing your ZedGraphControl Public Sub CreateChart(ByVal zgc As ZedGraphControl) Dim myPane As GraphPane = zgc.GraphPane ' Set the title and axis lab els myPane.Title.Text = "Line Graph with Band Demo" myPane.XAxis.Title.Text = "Sequence" myPane.YAxis.Title.Text = "Temperature, C" ' Enter Dim Dim Dim Dim some random data values y() As Double = {100, 115, y2() As Double = {90, 100, y3() As Double = {80, 110, x() As Double = {100, 200,

75, 22, 98, 40, 10} 95, 35, 80, 35, 35} 65, 15, 54, 67, 18} 300, 400, 500, 600, 700}

' Fill the axis background with a color gradient myPane.Chart.Fil l = New Fill(Color.FromArgb(255, 255, 245), Color.FromArgb(255, 255, 190), 90.0F) ' Generate a red curve with "Curve 1" in the legend Dim myCurve As LineItem = myPane.AddCurve("Curve 1", x, y, Color.Red) ' Make the symbols opaque by filling them with white myCurve.Symbol.Fill = New Fill(Color.White) ' Generate a blue curve with "Curve 2" in the legend myCurve = myPane.AddCurve("Curve 2", x, y2, Color.Blue) ' Make the symbol s opaque by filling them with white myCurve.Symbol.Fill = New Fill(Color.White) ' Generate a green curve with "Curve 3" in the legend myCurve = myPane.AddCurve("Curve 3", x, y3, Color.Green) ' Make the symbols opaque by filling the m with white myCurve.Symbol.Fill = New Fill(Color.White)

' Manually set the x axis range myPane.XAxis.Scale.Min = 0 myPane.XAxis.Scale.Max = 800 ' Display the Y axis grid lines myPane.YAxis.MajorGrid.IsVisible = Tru e myPane.YAxis.MinorGrid.IsVisible = True ' Draw a box item to highlight a value range Dim box As BoxObj = New BoxObj(0, 100, 1, 30, Color.Empty, Color.FromArgb(150, Color.LightGreen)) box.Fill = New Fill(Color.White, Color.FromArgb(200, Color.LightGreen), 45.0F) ' Use the BehindAxis zorder to draw the highlight beneath the grid lines box.ZOrder = ZOrder.E_BehindCurves ' Make sure that the boxObj does not extend outside the chart rect if the chart is zoomed box.IsClippedToChartRect = True ' Use a hybrid coordinate system so the X axis always covers the full x range ' from chart fraction 0.0 to 1.0 box.Location.CoordinateFrame = CoordType .XChartFractionYScale myPane.GraphObjList.Add(box) ' Add a text item to label the highlighted range Dim Text As TextObj = New TextObj("Optimal \nRange", 0.95F, 85, CoordType.AxisXYScale, AlignH.Right, AlignV.Center) Text.FontSpe c.Fill.IsVisible = False Text.FontSpec.Border.IsVisible = False Text.FontSpec.IsBold = True Text.FontSpec.IsItalic = True Text.Location.CoordinateFrame = CoordType.XChartFractionYScale Text.IsClippedToChartRect = Tru e myPane.GraphObjList.Add(Text) ' Fill the pane background with a gradient myPane.Fill = New Fill(Color.WhiteSmoke, Color.Lavender, 0.0F) ' Calculate the Axis Scale Ranges zgc.AxisChange() End Sub

M lti-YNOTE The .3 here.

6

5

5

4 $"

e

hi

ei

edGraph ersi

. You an i

87 6

3

1" ) ' $" #"! 2 0& ( & %

Go b

k to S

l Graphs

othe ode for ersion

9

Sample Code in C#// Call this method from the Form_Load method, passing your ZedGraphControl instance public void CreateChart( ZedGraphControl z c ) g { // Get a reference to the GraphPane GraphPane myPane = zgc.GraphPane; // Set the titles and axis labels myPane.Title.Text = "Demonstration of Multi Y Graph"; myPane.XAxis.Title.Text = "Time, s"; myPane.YAxis.Title.Text = "Velocity, m/s"; myPane.Y2Axis.Title.Text = "Acceleration, m/s2"; // Make up some data points based on the Sine function PointPairList vList = new PointPairList(); PointPairList aList = new PointPairList(); PointPairList dList = new PointPairList(); PointPairList eList = new PointPairList(); // Fabricate some data values for ( int i=0; i