none
Que control usar para ir insertando registros en una tabla

    Pregunta

  • Buenas,

    Es mi primer post en este foro y trataré de ser  lo más conciso posible. Estoy migrando una aplicacion vb6 a vb.net, lenguaje en el que no soy muy ducho.

    Ahora mismo estoy con el formulario de albaranes y no sé muy bien que control utilizar para que el usuario vaya eligiendo artículos de una listview o datagrid y se vayan añadiendo a otro no sé si datagrid o listview aún. En vb6 lo iba añadiendo a una listview, posteriormente cuando el usuario le daba a guardar barría la listview y todo lo que no estuviera guardado ya(tenía una columna de control con 1 ó 0) lo guardaba mediante  un objeto recordset(ADO).

    Dada mi poca experiencia en .net, había pensado ir metiendolo en un datagrid que se recarga cada vez que el usuario introduce un artículo nuevo. Es decir mediante un comando sql hago el insert en la base de datos (Access por cierto) y para que se actualice en pantalla volver a llenar el grid.

    Este procedimiento que muestro a continuación sería llamado cada vez que se hiciera un insert en la base de datos, a mí no me parece muy buena idea, pero desconozco como hacerlo bien, por eso estoy aquí pidiendo consejo más que una ayuda específica sobre algún error.

    Private Sub LlenaGridAlbaranes(ByVal IdAlbaran As String)

            Dim ds As New DataSet
            Dim strSql As String = ""

            strSql += "SELECT L.NOcurrencia, L.Cantidad, L.IdArticulo, A.DescripcionArticulo, L.Precio, L.STotal, L.TipoIVA, L.PNeto, L.STNeto"
            strSql += " FROM OAlbaran L, Articulos A WHERE L.IDArticulo = A.IdArticulo"
            strSql += " AND L.IdAlbaran = '" & IdAlbaran & "'"
           

            MsgBox(strSql)

            Dim adp As New OleDb.OleDbDataAdapter(strSql, conn)

            Try
                ds.Tables.Add("tabla")
                adp.Fill(ds.Tables("tabla"))

                Me.dgrAlbaranes.DataSource = ds.Tables("tabla")
                Me.dgrAlbaranes.Columns(0).HeaderText = "Línea"
                Me.dgrAlbaranes.Columns(1).HeaderText = "Cantidad"
                Me.dgrAlbaranes.Columns(2).HeaderText = "Id Artículo"
                Me.dgrAlbaranes.Columns(3).HeaderText = "Descripción"
                Me.dgrAlbaranes.Columns(4).HeaderText = "Precio"
                Me.dgrAlbaranes.Columns(5).HeaderText = "SubTotal"
                Me.dgrAlbaranes.Columns(6).HeaderText = "Tipo IVA"
                Me.dgrAlbaranes.Columns(7).HeaderText = "Precio Neto"
                Me.dgrAlbaranes.Columns(8).HeaderText = "SubTotal Neto"

            Catch ex As Exception

                MsgBox(ex.ToString)

            Finally

                ds.Dispose()
                adp.Dispose()

            End Try

    viernes, 30 de septiembre de 2016 15:48

Respuestas

  • "Ramiro Otero" escribió:

    > Dada mi poca experiencia en .net, había pensado ir metiendolo en un datagrid que
    > se recarga cada vez que el usuario introduce un artículo nuevo. Es decir mediante
    > un comando sql hago el insert en la base de datos (Access por cierto) y para que
    > se actualice en pantalla volver a llenar el grid.

    Hola, Ramiro:

    Para insertar nuevos registros en una tabla no hay un control que te permita hacerlo digamos de una manera automática, y menos aún utilizando una consulta SQL de selección de combinación entre dos tablas: OAlbaran y Articulos.

    Si en la consulta de selección utilizaras una única tabla, otro gallo cantaría, porque podrías configurar un objeto OleDbDataAdapter mediante un objeto OleDbCommandBuilder, y llamarías al método Update del adaptador de datos pasándole el objeto DataTable enlazado con el control DataGridView.

    > strSql += "SELECT L.NOcurrencia, L.Cantidad, L.IdArticulo, A.DescripcionArticulo, L.Precio, L.STotal, L.TipoIVA,
    > L.PNeto, L.STNeto"
    > strSql += " FROM OAlbaran L, Articulos A WHERE L.IDArticulo = A.IdArticulo"
    > strSql += " AND L.IdAlbaran = '" & IdAlbaran & "'"

    Por cierto, entiendo que lo suyo sería utilizar una combinación INNER JOIN y utilizar un parámetro de entrada para especificar el valor del campo IdAlbaran:

        strSql = "SELECT L.NOcurrencia, L.Cantidad, L.IdArticulo, A.DescripcionArticulo, L.Precio, " & _
                 "L.STotal, L.TipoIVA, L.PNeto, L.STNeto " & _
                 "FROM OAlbaran L INNER JOIN Articulos A " & _
                 "ON L.IDArticulo = A.IdArticulo " & _
                 "WHERE L.IdAlbaran = @idAlbaran"

    Yo te puedo explicar cómo rellenar un control DataGridView como resultado de ejecutar la consulta SELECT anterior, y como insertar nuevos registros en la tabla OAlbaran.

    Para ello, inserta en tu proyecto el siguiente módulo que te servirá de ayuda para el acceso a datos:

    Imports System.Data.OleDb Friend Module HelperDataAccess Private Function GetConnectionString() As String ' La función devolverá la cadena de conexión utilizada ' por el proyeto, y en ella puedes escribir el código ' fuente necesario para leerla desde el archivo de ' configuración de la aplicación. ' Return "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Mis documentos\Database1.accdb" End Function ''' <summary> ''' Ejecuta la consulta SQL de acción existente en el objeto Command ''' devolviendo el número de registros afectados. ''' </summary> ''' <param name="cmd">objeto OleDbCommand debidamente configurado.</param> ''' <returns></returns> ''' <remarks></remarks> Friend Function ExecuteAction(cmd As OleDbCommand) As Integer If (cmd Is Nothing) Then Throw New ArgumentNullException("cmd") End If Using cnn As New OleDbConnection(HelperDataAccess.GetConnectionString()) cmd.Connection = cnn cnn.Open() Return cmd.ExecuteNonQuery() End Using End Function ''' <summary> ''' Ejecuta la consulta SQL de selección existente en el objeto Command ''' devolviendo un objeto DataTable. ''' </summary> ''' <param name="cmd">objeto Command debidamente configurado.</param> ''' <returns></returns> ''' <remarks></remarks> Friend Function GetData(cmd As OleDbCommand) As DataTable If (cmd Is Nothing) Then Throw New ArgumentNullException("cmd") End If Dim dt As New DataTable() ' Configuramos una conexión con el origen de datos. ' Using cnn As New OleDbConnection(GetConnectionString()) cmd.Connection = cnn Dim da As New OleDbDataAdapter(cmd) ' Añadimos información sobre la clave principal de la tabla. ' da.MissingSchemaAction = MissingSchemaAction.AddWithKey da.Fill(dt)

    ' Si no se va a utilizar el método UpdateData existente
    ' en éste Module, comentar la siguiente línea.
    ' ' En el objeto DataTable guardamos el objeto ' Command utilizado para ejecutar la consulta. ' dt.ExtendedProperties.Add("Command", cmd) End Using Return dt End Function ''' <summary> ''' Actualiza el origen de datos con los datos existentes ''' en el objeto DataTable pasado al procedimiento. ''' </summary> ''' <param name="dt">Objeto DataTable configurado con el objeto Command y la ''' cadena de conexión utilizadas para rellenar el objeto DataTable.</param> ''' <returns></returns> ''' <remarks></remarks> Friend Function UpdateData(dt As DataTable) As Integer If (dt Is Nothing) Then Throw New ArgumentNullException("dt") End If ' Recuperamos el objeto Command almacenado ' en las propiedades extendidas del objeto ' DataTable. ' Dim cmd As OleDbCommand = DirectCast(dt.ExtendedProperties("Command"), OleDbCommand) If (cmd Is Nothing) Then Throw New ArgumentException("No se ha configurado el objeto Command.") End If ' Referenciar el objeto Connection Using cnn As OleDbConnection = cmd.Connection ' Obtener la cadena de conexión cnn.ConnectionString = GetConnectionString() ' Configurar el adaptador de datos. Dim da As New OleDbDataAdapter(cmd) ' Generar automáticamente las propiedades del adaptador de datos, pero ' para ello, la tabla tiene que tener establecida su correspondiente ' clave principal. ' Dim cb As New OleDbCommandBuilder(da) cb.QuotePrefix = "[" cb.QuoteSuffix = "]" With da .InsertCommand = cb.GetInsertCommand() .DeleteCommand = cb.GetDeleteCommand() .UpdateCommand = cb.GetUpdateCommand() End With Return da.Update(dt) End Using End Function End Module


    Modifica la función GetConnectionString para que la misma devuelva la cadena de conexión que estás utilizando en tu proyecto.

    Cuando desees recuperar un objeto DataTable como resultado de ejecutar una consulta SQL de selección, llamarías al método GetData existente en el módulo. Para ello, modificarías tu procedimiento LlenarGridAlbaranes para dejarlo como indico a continuación:

        Private Sub LlenaGridAlbaranes(ByVal IdAlbaran As String)
    
            Try
                Dim cmd As New OleDbCommand()
    
                ' Seleccionamos los registros de la tabla OAlbaran que se
                ' correspondan con el criterio especificado en la cláusula
                ' WHERE.
                '
                cmd.CommandText = "SELECT L.NOcurrencia, L.Cantidad, L.IdArticulo, A.DescripcionArticulo, " & _
                                  "L.Precio, L.STotal, L.TipoIVA, L.PNeto, L.STNeto " & _
                                  "FROM OAlbaran L INNER JOIN Articulos A " & _
                                  "ON L.IDArticulo = A.IdArticulo " & _
                                  "WHERE L.IdAlbaran = @idAlbaran"
             
                ' Añadimos el único parámetro de entrada
                cmd.Parameters.AddWithValue("@idAlbaran", IdAlbaran)
    
                ' Enlazamos el control DataGridView con un objeto DataTable
                Me.dgrAlbaranes.DataSource = HelperDataAccess.GetData(cmd)
    
                Me.dgrAlbaranes.Columns(0).HeaderText = "Línea"
                Me.dgrAlbaranes.Columns(1).HeaderText = "Cantidad"
                Me.dgrAlbaranes.Columns(2).HeaderText = "Id Artículo"
                Me.dgrAlbaranes.Columns(3).HeaderText = "Descripción"
                Me.dgrAlbaranes.Columns(4).HeaderText = "Precio"
                Me.dgrAlbaranes.Columns(5).HeaderText = "SubTotal"
                Me.dgrAlbaranes.Columns(6).HeaderText = "Tipo IVA"
                Me.dgrAlbaranes.Columns(7).HeaderText = "Precio Neto"
                Me.dgrAlbaranes.Columns(8).HeaderText = "SubTotal Neto"
    
            Catch ex As Exception
                ' Se ha producido un error
                MessageBox.Show(ex.Message)
    
            End Try
    
        End Sub

    Y ahora, cuando desees añadir a la tabla OAlbaran nuevos registros, tendrías que configurar un nuevo objeto OleDbCommand para pasárselo al método ExecuteAction existente en el módulo HelperDataAccess. Pero ¡claro! No puedes tomar los datos existentes en el control DataGridView porque se supone que éstos registros ya existen en la tabla OAlbaran, por lo que, o lo duplicarías o recibirías el error oportuno si la tabla tiene su correspondiente clave principal, por tanto, a modo de ejemplo vamos a suponer que los datos de la tabla OAlbaran los tomas de los valores escritos en controles TextBox:

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Try
                Dim cmd As New OleDbCommand()
                cmd.CommandText = "INSERT INTO OAlbaran(NOcurrencia, Cantidad, IdArticulo, Precio, " &
                                                        "STotal, TipoIVA, PNeto, STNeto) " &
                                  "VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)"
    
                ' Añadimos los 8 parámetros de entrada y en el MISMO ORDEN en el
                ' que se encuentran declarados en la consulta INSERT INTO
                '
                cmd.Parameters.AddWithValue("@p1", TextBox1.Text)
                cmd.Parameters.AddWithValue("@p2", TextBox2.Text)
                cmd.Parameters.AddWithValue("@p3", TextBox3.Text)
                cmd.Parameters.AddWithValue("@p4", TextBox4.Text)
                cmd.Parameters.AddWithValue("@p5", TextBox5.Text)
                cmd.Parameters.AddWithValue("@p6", TextBox6.Text)
                cmd.Parameters.AddWithValue("@p7", TextBox7.Text)
                cmd.Parameters.AddWithValue("@p8", TextBox8.Text)
    
                ' Procedemos a insertar el nuevo registro
                HelperDataAccess.ExecuteAction(cmd)
    
            Catch ex As Exception
                ' Se ha producido un error
                MessageBox.Show(ex.Message)
    
            End Try
    
        End Sub

    Fíjate que en el módulo HelperDataAccess existe un método llamada UpdateData que no se utiliza en el ejemplo pero que el día de mañana te puede ser bastante útil, sobre todo para ejecutar lo que comenté más arriba cuando escribí la expresión "otro gallo cantaría". ;-)

    Un saludo


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.


    viernes, 30 de septiembre de 2016 17:47
    Moderador

Todas las respuestas

  • "Ramiro Otero" escribió:

    > Dada mi poca experiencia en .net, había pensado ir metiendolo en un datagrid que
    > se recarga cada vez que el usuario introduce un artículo nuevo. Es decir mediante
    > un comando sql hago el insert en la base de datos (Access por cierto) y para que
    > se actualice en pantalla volver a llenar el grid.

    Hola, Ramiro:

    Para insertar nuevos registros en una tabla no hay un control que te permita hacerlo digamos de una manera automática, y menos aún utilizando una consulta SQL de selección de combinación entre dos tablas: OAlbaran y Articulos.

    Si en la consulta de selección utilizaras una única tabla, otro gallo cantaría, porque podrías configurar un objeto OleDbDataAdapter mediante un objeto OleDbCommandBuilder, y llamarías al método Update del adaptador de datos pasándole el objeto DataTable enlazado con el control DataGridView.

    > strSql += "SELECT L.NOcurrencia, L.Cantidad, L.IdArticulo, A.DescripcionArticulo, L.Precio, L.STotal, L.TipoIVA,
    > L.PNeto, L.STNeto"
    > strSql += " FROM OAlbaran L, Articulos A WHERE L.IDArticulo = A.IdArticulo"
    > strSql += " AND L.IdAlbaran = '" & IdAlbaran & "'"

    Por cierto, entiendo que lo suyo sería utilizar una combinación INNER JOIN y utilizar un parámetro de entrada para especificar el valor del campo IdAlbaran:

        strSql = "SELECT L.NOcurrencia, L.Cantidad, L.IdArticulo, A.DescripcionArticulo, L.Precio, " & _
                 "L.STotal, L.TipoIVA, L.PNeto, L.STNeto " & _
                 "FROM OAlbaran L INNER JOIN Articulos A " & _
                 "ON L.IDArticulo = A.IdArticulo " & _
                 "WHERE L.IdAlbaran = @idAlbaran"

    Yo te puedo explicar cómo rellenar un control DataGridView como resultado de ejecutar la consulta SELECT anterior, y como insertar nuevos registros en la tabla OAlbaran.

    Para ello, inserta en tu proyecto el siguiente módulo que te servirá de ayuda para el acceso a datos:

    Imports System.Data.OleDb Friend Module HelperDataAccess Private Function GetConnectionString() As String ' La función devolverá la cadena de conexión utilizada ' por el proyeto, y en ella puedes escribir el código ' fuente necesario para leerla desde el archivo de ' configuración de la aplicación. ' Return "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Mis documentos\Database1.accdb" End Function ''' <summary> ''' Ejecuta la consulta SQL de acción existente en el objeto Command ''' devolviendo el número de registros afectados. ''' </summary> ''' <param name="cmd">objeto OleDbCommand debidamente configurado.</param> ''' <returns></returns> ''' <remarks></remarks> Friend Function ExecuteAction(cmd As OleDbCommand) As Integer If (cmd Is Nothing) Then Throw New ArgumentNullException("cmd") End If Using cnn As New OleDbConnection(HelperDataAccess.GetConnectionString()) cmd.Connection = cnn cnn.Open() Return cmd.ExecuteNonQuery() End Using End Function ''' <summary> ''' Ejecuta la consulta SQL de selección existente en el objeto Command ''' devolviendo un objeto DataTable. ''' </summary> ''' <param name="cmd">objeto Command debidamente configurado.</param> ''' <returns></returns> ''' <remarks></remarks> Friend Function GetData(cmd As OleDbCommand) As DataTable If (cmd Is Nothing) Then Throw New ArgumentNullException("cmd") End If Dim dt As New DataTable() ' Configuramos una conexión con el origen de datos. ' Using cnn As New OleDbConnection(GetConnectionString()) cmd.Connection = cnn Dim da As New OleDbDataAdapter(cmd) ' Añadimos información sobre la clave principal de la tabla. ' da.MissingSchemaAction = MissingSchemaAction.AddWithKey da.Fill(dt)

    ' Si no se va a utilizar el método UpdateData existente
    ' en éste Module, comentar la siguiente línea.
    ' ' En el objeto DataTable guardamos el objeto ' Command utilizado para ejecutar la consulta. ' dt.ExtendedProperties.Add("Command", cmd) End Using Return dt End Function ''' <summary> ''' Actualiza el origen de datos con los datos existentes ''' en el objeto DataTable pasado al procedimiento. ''' </summary> ''' <param name="dt">Objeto DataTable configurado con el objeto Command y la ''' cadena de conexión utilizadas para rellenar el objeto DataTable.</param> ''' <returns></returns> ''' <remarks></remarks> Friend Function UpdateData(dt As DataTable) As Integer If (dt Is Nothing) Then Throw New ArgumentNullException("dt") End If ' Recuperamos el objeto Command almacenado ' en las propiedades extendidas del objeto ' DataTable. ' Dim cmd As OleDbCommand = DirectCast(dt.ExtendedProperties("Command"), OleDbCommand) If (cmd Is Nothing) Then Throw New ArgumentException("No se ha configurado el objeto Command.") End If ' Referenciar el objeto Connection Using cnn As OleDbConnection = cmd.Connection ' Obtener la cadena de conexión cnn.ConnectionString = GetConnectionString() ' Configurar el adaptador de datos. Dim da As New OleDbDataAdapter(cmd) ' Generar automáticamente las propiedades del adaptador de datos, pero ' para ello, la tabla tiene que tener establecida su correspondiente ' clave principal. ' Dim cb As New OleDbCommandBuilder(da) cb.QuotePrefix = "[" cb.QuoteSuffix = "]" With da .InsertCommand = cb.GetInsertCommand() .DeleteCommand = cb.GetDeleteCommand() .UpdateCommand = cb.GetUpdateCommand() End With Return da.Update(dt) End Using End Function End Module


    Modifica la función GetConnectionString para que la misma devuelva la cadena de conexión que estás utilizando en tu proyecto.

    Cuando desees recuperar un objeto DataTable como resultado de ejecutar una consulta SQL de selección, llamarías al método GetData existente en el módulo. Para ello, modificarías tu procedimiento LlenarGridAlbaranes para dejarlo como indico a continuación:

        Private Sub LlenaGridAlbaranes(ByVal IdAlbaran As String)
    
            Try
                Dim cmd As New OleDbCommand()
    
                ' Seleccionamos los registros de la tabla OAlbaran que se
                ' correspondan con el criterio especificado en la cláusula
                ' WHERE.
                '
                cmd.CommandText = "SELECT L.NOcurrencia, L.Cantidad, L.IdArticulo, A.DescripcionArticulo, " & _
                                  "L.Precio, L.STotal, L.TipoIVA, L.PNeto, L.STNeto " & _
                                  "FROM OAlbaran L INNER JOIN Articulos A " & _
                                  "ON L.IDArticulo = A.IdArticulo " & _
                                  "WHERE L.IdAlbaran = @idAlbaran"
             
                ' Añadimos el único parámetro de entrada
                cmd.Parameters.AddWithValue("@idAlbaran", IdAlbaran)
    
                ' Enlazamos el control DataGridView con un objeto DataTable
                Me.dgrAlbaranes.DataSource = HelperDataAccess.GetData(cmd)
    
                Me.dgrAlbaranes.Columns(0).HeaderText = "Línea"
                Me.dgrAlbaranes.Columns(1).HeaderText = "Cantidad"
                Me.dgrAlbaranes.Columns(2).HeaderText = "Id Artículo"
                Me.dgrAlbaranes.Columns(3).HeaderText = "Descripción"
                Me.dgrAlbaranes.Columns(4).HeaderText = "Precio"
                Me.dgrAlbaranes.Columns(5).HeaderText = "SubTotal"
                Me.dgrAlbaranes.Columns(6).HeaderText = "Tipo IVA"
                Me.dgrAlbaranes.Columns(7).HeaderText = "Precio Neto"
                Me.dgrAlbaranes.Columns(8).HeaderText = "SubTotal Neto"
    
            Catch ex As Exception
                ' Se ha producido un error
                MessageBox.Show(ex.Message)
    
            End Try
    
        End Sub

    Y ahora, cuando desees añadir a la tabla OAlbaran nuevos registros, tendrías que configurar un nuevo objeto OleDbCommand para pasárselo al método ExecuteAction existente en el módulo HelperDataAccess. Pero ¡claro! No puedes tomar los datos existentes en el control DataGridView porque se supone que éstos registros ya existen en la tabla OAlbaran, por lo que, o lo duplicarías o recibirías el error oportuno si la tabla tiene su correspondiente clave principal, por tanto, a modo de ejemplo vamos a suponer que los datos de la tabla OAlbaran los tomas de los valores escritos en controles TextBox:

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Try
                Dim cmd As New OleDbCommand()
                cmd.CommandText = "INSERT INTO OAlbaran(NOcurrencia, Cantidad, IdArticulo, Precio, " &
                                                        "STotal, TipoIVA, PNeto, STNeto) " &
                                  "VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)"
    
                ' Añadimos los 8 parámetros de entrada y en el MISMO ORDEN en el
                ' que se encuentran declarados en la consulta INSERT INTO
                '
                cmd.Parameters.AddWithValue("@p1", TextBox1.Text)
                cmd.Parameters.AddWithValue("@p2", TextBox2.Text)
                cmd.Parameters.AddWithValue("@p3", TextBox3.Text)
                cmd.Parameters.AddWithValue("@p4", TextBox4.Text)
                cmd.Parameters.AddWithValue("@p5", TextBox5.Text)
                cmd.Parameters.AddWithValue("@p6", TextBox6.Text)
                cmd.Parameters.AddWithValue("@p7", TextBox7.Text)
                cmd.Parameters.AddWithValue("@p8", TextBox8.Text)
    
                ' Procedemos a insertar el nuevo registro
                HelperDataAccess.ExecuteAction(cmd)
    
            Catch ex As Exception
                ' Se ha producido un error
                MessageBox.Show(ex.Message)
    
            End Try
    
        End Sub

    Fíjate que en el módulo HelperDataAccess existe un método llamada UpdateData que no se utiliza en el ejemplo pero que el día de mañana te puede ser bastante útil, sobre todo para ejecutar lo que comenté más arriba cuando escribí la expresión "otro gallo cantaría". ;-)

    Un saludo


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.


    viernes, 30 de septiembre de 2016 17:47
    Moderador
  • Muchísimas gracias por tu ayuda y el tiempo que te habrá llevado, lo valoro enormemente, voy a ir poniéndolo en práctica.

    Lo de las dos tablas cruzadas es imprescindible, de la tabla artículos se recupera simplemente la descripción del artículo.

    Un saludo, y gracias de nuevo.

    sábado, 1 de octubre de 2016 7:33