none
Eliminar filas vacías RRS feed

  • Pregunta

  • Hola, tengo la siguiente función la cual se encarga de completar un DataGridView con los valores de una hoja de Excel

        Private Sub ImportarConNom()
            Try
                With dlgAbrirArchivo
                    ' Comprobar que el archivo seleccionado existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckFileExists = True
                    ' Comprobar que la ruta de acceso seleccionada existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckPathExists = True
                    ' Obtener o establecer una extensión predeterminada. No incluye el "." inicial.
                    .DefaultExt = "xlsx"
                    .Filter = "Ficheros Excel (*.xlsx)|*.xlsx|(*.xls)|*.xls"
                    .Multiselect = False
                    ' ¿Restaurar el directorio original después de seleccionar un archivo? Si False, el directorio actual cambia al directorio en el que seleccionó el archivo.
                    ' Establézcalo como True para poner la carpeta actual de nuevo donde estaba cuando comenzó.
                    .RestoreDirectory = True
                    .Title = "Seleccione el Fichero"
                    ' ¿Aceptar sólo nombres de archivo Win32 válidos?
                    .ValidateNames = True
    
                    DgvImportar.Rows.Clear()
                    DgvImportar.Columns.Clear()
    
                    If .ShowDialog = DialogResult.OK Then
                        origen = .FileName
                        lP_CargaDataTable()
    
                        Me.DgvImportar.DataSource = mdtDataTable
    
                        For X = 0 To Me.DgvImportar.Rows.Count - 1
                            If Me.DgvImportar.Rows(X).Cells(1).Value = Nothing Then
                                If Not (Me.DgvImportar.Rows(X).IsNewRow) Then
                                    Me.DgvImportar.Rows.Remove(Me.DgvImportar.Rows(X))
                                End If
                            End If
                        Next
    
                    End If
    
                End With
            Catch ex As Exception
                MessageBox.Show("Se produjo un error : " & ex.Message)
            End Try
        End Sub
    Private Sub lP_CargaDataTable()
            Dim workbook As Workbook = New Workbook()
            workbook.LoadFromFile(origen)
            'Initailize worksheet
            Dim sheet As Worksheet = workbook.Worksheets(0)
            mdtDataTable = sheet.ExportDataTable()
        End Sub

    El problema que tengo es que intento eliminar las filas la cuales todas sus celdas están vacías pero no logro hacerlo. Como se ve trato de hacerlo pero no funciona.

    Como podría hacerlo para eliminar las filas completamente vacías?

    Saludos!!

    martes, 16 de enero de 2018 20:11

Respuestas

  • "Federico32113" escribió:

    > Agregue estas lineas antes de asignar el datetable pero sigue sin funcionar
    >
    >   If Not (IsNothing(mdtDataTable.Rows(i).item(j))) Then
    >
    > Alguna otra solución?

    Hola, Federico:

    Si tu intención es eliminar las filas del objeto DataTable donde el valor de cierta columna no tenga datos, en lugar de verificar si su valor es Nothing, verifica si el valor es DBNull.Value, porque por defecto, todas las columnas del objeto DataTable admiten valores NULL, que es un valor diferente a Nothing:

    Propiedad DataColumn.AllowDBNull

        For i As Integer = 0 To mdtDataTable.Rows.Count - 1
            For j As Integer = 0 To mdtDataTable.Columns.Count - 1
                If (mdtDataTable.Rows(i).item(j) Is DBNull.Value) Then
                    mdtDataTable.Rows(i).Delete()
                    ' Abandonar el bucle 'j' porque no tiene sentido
                    ' recorrer más campos de la fila si esta se ha
                    ' eliminado.
                    Exit For
                End If
            Next
        Next

    ' Aceptar los cambios habidos en el objeto DataTable
      mdtDataTable.AcceptChanges()

    Por cierto, observa el siguiente procedimiento:

    >    Private Sub lP_CargaDataTable()
    >        Dim workbook As Workbook = New Workbook()
    >        workbook.LoadFromFile(origen)
    >        'Initailize worksheet
    >        Dim sheet As Worksheet = workbook.Worksheets(0)
    >        mdtDataTable = sheet.ExportDataTable()
    >    End Sub

    Deduzco que tienes declarado a nivel del formulario o a nivel global, una variable llamada mdtDataTable del tipo DataTable. Si es así, elimina tal declaración y modifica la firma del procedimiento lP_CargaDataTable para que devuelva precisamente un objeto DataTable:

        Private Function lP_CargaDataTable() As DataTable
            Dim workbook As Workbook = New Workbook()
            workbook.LoadFromFile(origen)
            'Initailize worksheet
            Dim sheet As Worksheet = workbook.Worksheets(0)
    
            ' Devolver el objeto DataTable
            Return sheet.ExportDataTable()
        End Sub

    Y al control DataGridView le asignarías el objeto DataTable de la siguiente manera:

        ' lP_CargaDataTable()
        Me.DgvImportar.DataSource = lP_CargaDataTable()

    Cuando desees referenciar dicho objeto DataTable tan solo tienes que ejecutar lo siguiente:

        ' Referenciar el objeto DataTable asociado al control DataGridView
        Dim dt As DataTable = DirectCast(Me.DgvImportar.DataSource, DataTable)

    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.




    miércoles, 17 de enero de 2018 19:44
    Moderador
  • Como ignoro por completo la biblioteca de objetos de "Excel" (entre comillas) que estás utilizando, no sé si el método ExportDataTable admite ejecutar consultas SQL de selección, porque si permite ejecutarlas, entonces lo que tienes que hacer es seleccionar todas las filas de un rango de celdas concreto donde el valor de la primera columna, por ejemplo, NO TENGA el valor NULL.

    Imagina que la Hoja1 de tu libro de Excel presenta las siguientes datos:


    El siguiente ejemplo utiliza el ISAM de Excel del motor de datos Microsoft ACE para rellenar un objeto DataTable como resultado de la ejecución de una simple consulta SQL de selección:

    Imports System.Data.OleDb
    
        Private Shared Function GetDataTable() As DataTable
    
            Dim dt As New DataTable()
    
            Using cnn As New OleDbConnection()
                ' Especificamos la cadena de conexión con el libro de Excel
                ' donde indicamos que la primera fila NO CONTIENE el nombre
                ' de las columnas (HDR=No).
                cnn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" &
                                          "Data Source=C:\Carpeta\Libro1.xlsx;" &
                                          "Extended Properties='Excel 12.0 Xml;HDR=No'"
    
                Dim cmd As OleDbCommand = cnn.CreateCommand()
    
                ' Seleccionamos las celdas existentes en el rango A1:C10 donde
                ' el valor de la primera columna (F1) no tenga el valor NULL.
                ' 
                cmd.CommandText = "SELECT * FROM [Hoja1$A1:C10] WHERE NOT F1 IS NULL"
    
                Dim da As New OleDbDataAdapter(cmd)
                da.Fill(dt)
            End Using
    
            Return dt
    
        End Function

    Como en la primera fila del rango de celdas no aparecen los nombres de las columnas o campos, por defecto éstas tendrán el nombre F1 (primera columna), F2 (segunda columna), F3 (tercera columna), etc.

    Y asignarías los datos al control DataGridView efectuando una simple llamada a la función GetDataTable:

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Try
                DataGridView1.DataSource = GetDataTable()
    
            Catch ex As Exception
                ' Se ha producido un error
                MessageBox.Show(ex.Message)
    
            End Try
    
        End Sub

    Y aquí tienes el resultado:


    Como podrás observar, no aparecen las 6 líneas en blanco existentes en el rango A1:C10 de la hoja de Excel seleccionada.

    Mira a ver si puedes aplicar la consulta SQL de selección indicada a ese método ExportDataTable de la biblioteca de "Excel" que estás utilizando, de esta manera te ahorrarías tener que eliminarlas en el propio objeto DataTable.


    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, 19 de enero de 2018 16:07
    Moderador
  • Hola buenas, prueba a borrarlo en el datatable en vez de en el datagridview, lo que pasa es que lo estas borrando en el datagrid y en el datatable sigue estando esa fila por lo que se vuelve a cargar en el Datagridview.

    Un Saludo.

    miércoles, 17 de enero de 2018 7:41
  • "Federico32113" escribió:

    > Pd: probé el "For" que me subministraste el cual no cumple lo que
    > requiero en mi caso y el mensaje de error es "no hay ninguna fila
    > en la posición 2" de la misma hoja de excel.

    Me extraña que mi bucle For ... Next, tal cual lo escribí, te arroje el error que comentas, porque yo no obtengo error alguno.

    > ... mi intención original ..., todas las celdas tienen que estar
    > vacías para que eliminar la fila por eso lo modifique.

    Es decir, que si alguna celda de la fila contiene un valor que no es NULL, esa fila NO SE ELIMINARÁ. ¿Correcto? Si es así, mira a ver si te sirve el siguiente bucle For ... Next.

    Partimos de los siguientes datos existentes en la hoja de Excel:

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Try
                ' Obtenemos un objeto DataTable con los datos
                ' existentes en la hoja de cálculo de Excel.
                '
                Dim dt As DataTable = lP_CargaDataTable()
    Dim eliminarFila As Boolean For i As Integer = 0 To dt.Rows.Count - 1 For j As Integer = 0 To dt.Columns.Count - 1 If (dt.Rows(i).Item(j) Is DBNull.Value) Then ' El valor de la celda es NULL. eliminarFila = True Else ' El valor de la celda no es NULL. eliminarFila = False ' Como al menos existe una celda con un valor ' no NULL, abandonamos el bucle 'j'. Exit For End If Next If (eliminarFila) Then ' Si el marcador es True, eliminar la fila, porque se ' comprende que todas las celdas tienen valor NULL. dt.Rows(i).Delete() End If Next ' Aceptar los cambios habidos en el objeto DataTable dt.AcceptChanges() ' Asignamos el objeto DataTable al control DataGridView. DgvImportar.DataSource = dt Catch ex As Exception ' Se ha producido un error MessageBox.Show(ex.Message) End Try End Sub

    Se comprende que la función lP_CargaDataTable te devuelve un objeto DataTable. Y el resultado es el siguiente:

    Observa que la segunda fila no se ha eliminado porque su tercera celda tiene el valor 1212.

    Te ruego que te limites a ejecutar el código TAL CUAL ESTÁ ESCRITO. ¿De acuerdo?


    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, 26 de enero de 2018 18:42
    Moderador

Todas las respuestas

  • Hola buenas, prueba a borrarlo en el datatable en vez de en el datagridview, lo que pasa es que lo estas borrando en el datagrid y en el datatable sigue estando esa fila por lo que se vuelve a cargar en el Datagridview.

    Un Saludo.

    miércoles, 17 de enero de 2018 7:41
  • Agregue estas lineas antes de asignar el datetable pero sigue sin funcionar

                        For i = 0 To mdtDataTable.Rows.Count
                            Vacia = True
                            For j = 0 To mdtDataTable.Columns.Count
                                If Not (IsNothing(mdtDataTable.Rows(i).item(j))) Then
                                    Vacia = False
                                End If
                            Next
                            If Vacia = True Then
                                mdtDataTable.Rows(i).delete()
                            End If
                        Next
    Alguna otra solución?
    miércoles, 17 de enero de 2018 19:15
  • "Federico32113" escribió:

    > Agregue estas lineas antes de asignar el datetable pero sigue sin funcionar
    >
    >   If Not (IsNothing(mdtDataTable.Rows(i).item(j))) Then
    >
    > Alguna otra solución?

    Hola, Federico:

    Si tu intención es eliminar las filas del objeto DataTable donde el valor de cierta columna no tenga datos, en lugar de verificar si su valor es Nothing, verifica si el valor es DBNull.Value, porque por defecto, todas las columnas del objeto DataTable admiten valores NULL, que es un valor diferente a Nothing:

    Propiedad DataColumn.AllowDBNull

        For i As Integer = 0 To mdtDataTable.Rows.Count - 1
            For j As Integer = 0 To mdtDataTable.Columns.Count - 1
                If (mdtDataTable.Rows(i).item(j) Is DBNull.Value) Then
                    mdtDataTable.Rows(i).Delete()
                    ' Abandonar el bucle 'j' porque no tiene sentido
                    ' recorrer más campos de la fila si esta se ha
                    ' eliminado.
                    Exit For
                End If
            Next
        Next

    ' Aceptar los cambios habidos en el objeto DataTable
      mdtDataTable.AcceptChanges()

    Por cierto, observa el siguiente procedimiento:

    >    Private Sub lP_CargaDataTable()
    >        Dim workbook As Workbook = New Workbook()
    >        workbook.LoadFromFile(origen)
    >        'Initailize worksheet
    >        Dim sheet As Worksheet = workbook.Worksheets(0)
    >        mdtDataTable = sheet.ExportDataTable()
    >    End Sub

    Deduzco que tienes declarado a nivel del formulario o a nivel global, una variable llamada mdtDataTable del tipo DataTable. Si es así, elimina tal declaración y modifica la firma del procedimiento lP_CargaDataTable para que devuelva precisamente un objeto DataTable:

        Private Function lP_CargaDataTable() As DataTable
            Dim workbook As Workbook = New Workbook()
            workbook.LoadFromFile(origen)
            'Initailize worksheet
            Dim sheet As Worksheet = workbook.Worksheets(0)
    
            ' Devolver el objeto DataTable
            Return sheet.ExportDataTable()
        End Sub

    Y al control DataGridView le asignarías el objeto DataTable de la siguiente manera:

        ' lP_CargaDataTable()
        Me.DgvImportar.DataSource = lP_CargaDataTable()

    Cuando desees referenciar dicho objeto DataTable tan solo tienes que ejecutar lo siguiente:

        ' Referenciar el objeto DataTable asociado al control DataGridView
        Dim dt As DataTable = DirectCast(Me.DgvImportar.DataSource, DataTable)

    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.




    miércoles, 17 de enero de 2018 19:44
    Moderador
  • No me exprese bien lo que quiero hacer, mi intención es eliminar las filas las cuales están vacías del Excel para posteriormente agregar al DGV, acá dejo un ejemplo:

    Eliminaría la segunda por lo tanto en el datagridview quedarían 2 filas únicamente.

    Espero me puedan ayudar.



    jueves, 18 de enero de 2018 20:32
  • Es mas facil pasarlo asi como esta a visual en un datagrid  o datatable luego recorres con un for o foreach como gustes y eliminas los registros en blanco.

    Importante no te olvides de usar

    AcceptChanges()


    Si necesitas ayuda sube tu avance de otro modo no puedo ayudarte , Suerte!

    jueves, 18 de enero de 2018 21:40
  • "Federico32113" escribió:

    > No me exprese bien lo que quiero hacer, mi intención es eliminar las
    > filas las cuales están vacías del Excel para posteriormente agregar
    > al DGV, acá dejo un ejemplo:
    >
    > Eliminaría la segunda por lo tanto en el datagridview quedarían 2 filas
    > únicamente.

    Entonces, ¿para qué utilizas un objeto DataTable el cual le asignas al control DataGridView a través de su propiedad DataSource?

    Me.DgvImportar.DataSource = mdtDataTable

    Mi respuesta la escribí en base al código fuente que mostrastes en tu pregunta, para que eliminaras las filas en blanco en el propio objeto DataTable ANTES de asignárselo al control DataGridView.

    >  Private Function lP_CargaDataTable() As DataTable
    >       Dim workbook As Workbook = New Workbook()
    >       workbook.LoadFromFile(origen)
    >       'Initailize worksheet
    >       Dim sheet As Worksheet = workbook.Worksheets(0)
    >
    >       ' Devolver el objeto DataTable
    >       Return sheet.ExportDataTable()
    >   End Sub

    Observa que estás devolviendo un objeto DataTable como resultado de llamar al método ExportDataTable de un objeto Worksheet.

    Por cierto, ¿qué clase de biblioteca de "Excel" (entre comillas) estás utilizando? Te lo pregunto porque, que yo sepa, el objeto Worksheet de la biblioteca de objetos de Microsoft Excel no dispone de un método llamado ExportDataTable, ni tampoco el objeto Workbook implementa un método LoadFromFile. ¿?


    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, 19 de enero de 2018 11:25
    Moderador
  • Como ignoro por completo la biblioteca de objetos de "Excel" (entre comillas) que estás utilizando, no sé si el método ExportDataTable admite ejecutar consultas SQL de selección, porque si permite ejecutarlas, entonces lo que tienes que hacer es seleccionar todas las filas de un rango de celdas concreto donde el valor de la primera columna, por ejemplo, NO TENGA el valor NULL.

    Imagina que la Hoja1 de tu libro de Excel presenta las siguientes datos:


    El siguiente ejemplo utiliza el ISAM de Excel del motor de datos Microsoft ACE para rellenar un objeto DataTable como resultado de la ejecución de una simple consulta SQL de selección:

    Imports System.Data.OleDb
    
        Private Shared Function GetDataTable() As DataTable
    
            Dim dt As New DataTable()
    
            Using cnn As New OleDbConnection()
                ' Especificamos la cadena de conexión con el libro de Excel
                ' donde indicamos que la primera fila NO CONTIENE el nombre
                ' de las columnas (HDR=No).
                cnn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" &
                                          "Data Source=C:\Carpeta\Libro1.xlsx;" &
                                          "Extended Properties='Excel 12.0 Xml;HDR=No'"
    
                Dim cmd As OleDbCommand = cnn.CreateCommand()
    
                ' Seleccionamos las celdas existentes en el rango A1:C10 donde
                ' el valor de la primera columna (F1) no tenga el valor NULL.
                ' 
                cmd.CommandText = "SELECT * FROM [Hoja1$A1:C10] WHERE NOT F1 IS NULL"
    
                Dim da As New OleDbDataAdapter(cmd)
                da.Fill(dt)
            End Using
    
            Return dt
    
        End Function

    Como en la primera fila del rango de celdas no aparecen los nombres de las columnas o campos, por defecto éstas tendrán el nombre F1 (primera columna), F2 (segunda columna), F3 (tercera columna), etc.

    Y asignarías los datos al control DataGridView efectuando una simple llamada a la función GetDataTable:

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Try
                DataGridView1.DataSource = GetDataTable()
    
            Catch ex As Exception
                ' Se ha producido un error
                MessageBox.Show(ex.Message)
    
            End Try
    
        End Sub

    Y aquí tienes el resultado:


    Como podrás observar, no aparecen las 6 líneas en blanco existentes en el rango A1:C10 de la hoja de Excel seleccionada.

    Mira a ver si puedes aplicar la consulta SQL de selección indicada a ese método ExportDataTable de la biblioteca de "Excel" que estás utilizando, de esta manera te ahorrarías tener que eliminarlas en el propio objeto DataTable.


    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, 19 de enero de 2018 16:07
    Moderador
  • Gracias por la ultima respuesta pero me gustaría seguir utilizando como "parámetro" el código "original", ademas ya que al ejecutar la función me aparece el siguiente mensaje de error: el proveedor 'microsoft.ace.oledb.12.0' no está registrado en el equipo local.

    Mi idea no es tener que instalarlo cada vez que lo necesite en la PC del cliente.

    Intente recorrer el DataTable y si se cumple la condición de que todos sus campos están vacíos, eliminar la fila de la hoja del Excel anteriormente mostrada pero no logro que funcione.

      

    Imports Spire.Xls

    Private Sub ImportarConNom() Try With dlgAbrirArchivo ' Comprobar que el archivo seleccionado existe. El cuadro de diálogo muestra una advertencia en caso contrario. .CheckFileExists = True ' Comprobar que la ruta de acceso seleccionada existe. El cuadro de diálogo muestra una advertencia en caso contrario. .CheckPathExists = True ' Obtener o establecer una extensión predeterminada. No incluye el "." inicial. .DefaultExt = "xlsx" .Filter = "Ficheros Excel (*.xlsx)|*.xlsx|(*.xls)|*.xls" .Multiselect = False ' ¿Restaurar el directorio original después de seleccionar un archivo? Si False, el directorio actual cambia al directorio en el que seleccionó el archivo. ' Establézcalo como True para poner la carpeta actual de nuevo donde estaba cuando comenzó. .RestoreDirectory = True .Title = "Seleccione el Fichero" ' ¿Aceptar sólo nombres de archivo Win32 válidos? .ValidateNames = True DgvImportar.Rows.Clear() DgvImportar.Columns.Clear() If .ShowDialog = DialogResult.OK Then origen = .FileName lP_CargaDataTable() Dim eliminar As Boolean For i As Integer = 0 To mdtDataTable.Rows.Count - 1 eliminar = True For j As Integer = 0 To mdtDataTable.Columns.Count - 1 If (mdtDataTable.Rows(i).Item(j) IsNot Nothing) Then eliminar = False Exit For End If Next If eliminar = True Then mdtDataTable.Rows(i).Delete() End If Next ' Aceptar los cambios habidos en el objeto DataTable mdtDataTable.AcceptChanges() ' Dim dt As DataTable = DirectCast(Me.DgvImportar.DataSource, DataTable) Me.DgvImportar.DataSource = mdtDataTable End If End With Catch ex As Exception MessageBox.Show("Se produjo un error : " & ex.Message) End Try End Sub

     Private Sub lP_CargaDataTable()
            Dim workbook As Workbook = New Workbook()
            workbook.LoadFromFile(origen)
            'Initailize worksheet
            Dim sheet As Worksheet = workbook.Worksheets(0)
            mdtDataTable = sheet.ExportDataTable()
        End Sub

    Como podría modificar la función? o es indispensable hacerlo como me muestras en la ultima respuesta?

    lunes, 22 de enero de 2018 19:51
  • "Federico32113" escribió:

    > ... al ejecutar la función me aparece el siguiente mensaje de error:
    > el proveedor microsoft.ace.oledb.12.0' no está registrado en el
    > equipo local. 
    >

    ¿Has trabajado alguna vez con bases de datos Access versión 2007 o superior? Te lo pregunto porque el proveedor Microsoft.ACE.OLEDB.12.0 es el que se suele utilizar para conectarse con una base de datos de Access, un archivo de Excel, o un simple archivo de texto delimitado. Pero, ¡claro! Si no lo tienes instalado en el equipo, difícilmente lo vas a poder utilizar.

    > Intente recorrer el DataTable y si se cumple la condición de que todos
    > sus campos están vacíos, eliminar la fila de la hoja del Excel
    > anteriormente mostrada pero no logro que funcione.
    >
    > Dim eliminar As Boolean
    > For i As Integer = 0 To mdtDataTable.Rows.Count - 1
    >     eliminar = True
    >     For j As Integer = 0 To mdtDataTable.Columns.Count - 1
    >         If (mdtDataTable.Rows(i).Item(j) IsNot Nothing) The
    >             eliminar = False
    >             Exit For
    >         End If
    >     Next
    >     If eliminar = True Then
    >         mdtDataTable.Rows(i).Delete()
    >     End If
    > Next
    >
    > Como podría modificar la función?

    Nuevamente te remito a la lectura del contenido existente en el mensaje de MI PRIMERA RESPUESTA.

    > o es indispensable hacerlo como me muestras en la ultima
    > respuesta?

    No, aunque entiendo que es muchísimo mejor no seleccionar en el ORIGEN (el archivo de Excel) las filas que no nos interesan (las que todas sus celdas estén en blanco), en lugar de eliminarlas en el DESTINO (el objeto DataTable que has rellenado con la "biblioteca de Excel" que estés utilizando).


    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.




    martes, 23 de enero de 2018 12:29
    Moderador
  • Casi termino... decidí implementar parte del código de la primera respuesta por lo que la función me quedo así:

        Private Sub ImportarConNom()
            Try
                With dlgAbrirArchivo
                    ' Comprobar que el archivo seleccionado existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckFileExists = True
                    ' Comprobar que la ruta de acceso seleccionada existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckPathExists = True
                    ' Obtener o establecer una extensión predeterminada. No incluye el "." inicial.
                    .DefaultExt = "xlsx"
                    .Filter = "Ficheros Excel (*.xlsx)|*.xlsx|(*.xls)|*.xls"
                    .Multiselect = False
                    ' ¿Restaurar el directorio original después de seleccionar un archivo? Si False, el directorio actual cambia al directorio en el que seleccionó el archivo.
                    ' Establézcalo como True para poner la carpeta actual de nuevo donde estaba cuando comenzó.
                    .RestoreDirectory = True
                    .Title = "Seleccione el Fichero"
                    ' ¿Aceptar sólo nombres de archivo Win32 válidos?
                    .ValidateNames = True
    
                    DgvImportar.Rows.Clear()
                    DgvImportar.Columns.Clear()
    
                    If .ShowDialog = DialogResult.OK Then
                        origen = .FileName
    
                        '   lP_CargaDataTable()
                        Me.DgvImportar.DataSource = lP_CargaDataTable()
    
                        Dim mdtDataTable As DataTable = DirectCast(Me.DgvImportar.DataSource, DataTable)
    
                        Dim eliminar As Boolean
                        For i As Integer = 0 To mdtDataTable.Rows.Count - 1
                            'Celda vacia error
                            eliminar = True
                            For j As Integer = 0 To mdtDataTable.Columns.Count - 1
                                If (mdtDataTable.Rows(i).Item(j) IsNot DBNull.Value) Then
                                    eliminar = False
                                    Exit For
                                End If
                            Next
                            If eliminar = True Then
                                mdtDataTable.Rows(i).Delete()
                            End If
                        Next
                        ' Aceptar los cambios habidos en el objeto DataTable
                        mdtDataTable.AcceptChanges()
                    End If
                End With
            Catch ex As Exception
                MessageBox.Show("Se produjo un error : " & ex.Message)
            End Try
        End Sub
      Private Function lP_CargaDataTable() As DataTable
            Dim workbook As Workbook = New Workbook()
            workbook.LoadFromFile(origen)
            'Initailize worksheet
            Dim sheet As Worksheet = workbook.Worksheets(0)
    
            ' Devolver el objeto DataTable
            Return sheet.ExportDataTable()
        End Function

    Cuando trato de cargar por ejemplo esta hoja, me aparece el siguiente mensaje de error "No hay ninguna fila en la posición 3" y no me agrega lo fila vacía lo cual es correctoen cambio si no existen filas vacía funciona bien.

    El error me lo marca en esta linea 

    If (mdtDataTable.Rows(i).Item(j) IsNot DBNull.Value) Then



    jueves, 25 de enero de 2018 20:29
  • "Federico32113" escribió:

    > Cuando trato de cargar por ejemplo esta hoja, me aparece el siguiente
    > mensaje de error "No hay ninguna fila en la posición 3" y no me agrega
    > lo fila vacía lo cual es correcto, en cambio si no existen filas vacía
    > funciona bien.
    >
    > El error me lo marca en esta linea
    > If (mdtDataTable.Rows(i).Item(j) IsNot DBNull.Value) Then

    Una pregunta. ¿Tienes algún problema o inconveniente en ejecutar el bucle FOR ... NEXT tal cual lo publiqué en mi primera respuesta?

    Yo te aconsejaría que al menos probaras una sola vez a ejecutar el bucle tal cual lo escribí, y después me comentas si te marca error alguno. Pero no me preguntes el motivo por el que obtienes el error que describes cuando estás ejecutando un bucle que es TOTALMENTE DIFERENTE al que yo publiqué. ¡Vamos! Que las decisiones que se toman en un bucle son diferentes a las que se toman en el otro.

    Yo puedo responder por los errores que se obtengan al ejecutar mi código, pero no puedo hacerlo por el que tú estás ejecutando por capricho o por los motivos que tengas para ejecutar el bucle For ... Next tal cual lo tienes implementado. ;-)


    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, 26 de enero de 2018 8:22
    Moderador
  • Modifique el ciclo "For" ya que mi intención original no es eliminar la fila si una celda esta vacía, todas las celdas tienen que estar vacías para que eliminar la fila por eso lo modifique.

    Ahora mi consultas es si tenes algún consejo para que no me aparezca el mensaje de error el cual publique en mi anterior respuesta.

    Pd: probé el "For" que me subministraste el cual no cumple lo que requiero en mi caso y el mensaje de error es "no hay ninguna fila en la posición 2" de la misma hoja de excel.


    viernes, 26 de enero de 2018 17:16
  • "Federico32113" escribió:

    > Pd: probé el "For" que me subministraste el cual no cumple lo que
    > requiero en mi caso y el mensaje de error es "no hay ninguna fila
    > en la posición 2" de la misma hoja de excel.

    Me extraña que mi bucle For ... Next, tal cual lo escribí, te arroje el error que comentas, porque yo no obtengo error alguno.

    > ... mi intención original ..., todas las celdas tienen que estar
    > vacías para que eliminar la fila por eso lo modifique.

    Es decir, que si alguna celda de la fila contiene un valor que no es NULL, esa fila NO SE ELIMINARÁ. ¿Correcto? Si es así, mira a ver si te sirve el siguiente bucle For ... Next.

    Partimos de los siguientes datos existentes en la hoja de Excel:

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Try
                ' Obtenemos un objeto DataTable con los datos
                ' existentes en la hoja de cálculo de Excel.
                '
                Dim dt As DataTable = lP_CargaDataTable()
    Dim eliminarFila As Boolean For i As Integer = 0 To dt.Rows.Count - 1 For j As Integer = 0 To dt.Columns.Count - 1 If (dt.Rows(i).Item(j) Is DBNull.Value) Then ' El valor de la celda es NULL. eliminarFila = True Else ' El valor de la celda no es NULL. eliminarFila = False ' Como al menos existe una celda con un valor ' no NULL, abandonamos el bucle 'j'. Exit For End If Next If (eliminarFila) Then ' Si el marcador es True, eliminar la fila, porque se ' comprende que todas las celdas tienen valor NULL. dt.Rows(i).Delete() End If Next ' Aceptar los cambios habidos en el objeto DataTable dt.AcceptChanges() ' Asignamos el objeto DataTable al control DataGridView. DgvImportar.DataSource = dt Catch ex As Exception ' Se ha producido un error MessageBox.Show(ex.Message) End Try End Sub

    Se comprende que la función lP_CargaDataTable te devuelve un objeto DataTable. Y el resultado es el siguiente:

    Observa que la segunda fila no se ha eliminado porque su tercera celda tiene el valor 1212.

    Te ruego que te limites a ejecutar el código TAL CUAL ESTÁ ESCRITO. ¿De acuerdo?


    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, 26 de enero de 2018 18:42
    Moderador
  • Me quedo así la función:

       Private Sub ImportarConNom()
            Try
                With dlgAbrirArchivo
                    ' Comprobar que el archivo seleccionado existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckFileExists = True
                    ' Comprobar que la ruta de acceso seleccionada existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckPathExists = True
                    ' Obtener o establecer una extensión predeterminada. No incluye el "." inicial.
                    .DefaultExt = "xlsx"
                    .Filter = "Ficheros Excel (*.xlsx)|*.xlsx|(*.xls)|*.xls"
                    .Multiselect = False
                    ' ¿Restaurar el directorio original después de seleccionar un archivo? Si False, el directorio actual cambia al directorio en el que seleccionó el archivo.
                    ' Establézcalo como True para poner la carpeta actual de nuevo donde estaba cuando comenzó.
                    .RestoreDirectory = True
                    .Title = "Seleccione el Fichero"
                    ' ¿Aceptar sólo nombres de archivo Win32 válidos?
                    .ValidateNames = True
    
                    DgvImportar.Rows.Clear()
                    DgvImportar.Columns.Clear()
    
                    If .ShowDialog = DialogResult.OK Then
                        origen = .FileName
    
                        Dim dt As DataTable = lP_CargaDataTable()
                        Dim eliminarFila As Boolean
                        For i As Integer = 0 To dt.Rows.Count - 1
                            For j As Integer = 0 To dt.Columns.Count - 1
                                If (dt.Rows(i).Item(j) Is DBNull.Value) Then
                                    ' El valor de la celda es NULL.
                                    eliminarFila = True
                                Else
                                    ' El valor de la celda no es NULL.
                                    eliminarFila = False
                                    ' Como al menos existe una celda con un valor
                                    ' no NULL, abandonamos el bucle 'j'.
                                    Exit For
                                End If
                            Next
                            If (eliminarFila) Then
                                ' Si el marcador es True, eliminar la fila, porque se
                                ' comprende que todas las celdas tienen valor NULL.
                                dt.Rows(i).Delete()
                            End If
                        Next
                        ' Aceptar los cambios habidos en el objeto DataTable
                        dt.AcceptChanges()
                        ' Asignamos el objeto DataTable al control DataGridView.
                        DgvImportar.DataSource = dt
                    End If
                End With
            Catch ex As Exception
                MessageBox.Show("Se produjo un error : " & ex.Message)
            End Try
        End Sub

    Cuando cargo la hoja de excel igual a la anterior me aparece el error "No hay ninguna fila en la posición 3", en esta linea.

         If (dt.Rows(i).Item(j) Is DBNull.Value) Then

    Puede ser que el error se produzca debido a alguna propiedad que halla modificado del DGV? Porque en esta función la primer linea seria el encabezado del DGV y luego tengo otra función donde el encabezado no es la primer fila.


    lunes, 29 de enero de 2018 19:38
  • "Federico32113" escribió:

    > Cuando cargo la hoja de excel igual a la anterior me aparece
    > el error "No hay ninguna fila en la posición 3", en esta linea.
    >
    >     If (dt.Rows(i).Item(j) Is DBNull.Value) Then

    Me extraña muchísimo que obtengas ese error, porque en el supuesto de que el objeto DataTable devuelto por la función lP_CargaDataTable no tuviera ninguna fila, ni siquiera se ejecutaría el siguiente bucle For:

        Dim dt As DataTable = lP_CargaDataTable()
    
        For i As Integer = 0 To dt.Rows.Count - 1

    Es decir, si el objeto DataTable obtenido no contiene ninguna fila, NO SE EJECUTARÍA EL BUCLE, porque este se ejecutaría desde 0 hasta -1 (el número total de filas del objeto DataTable menos 1, es decir, desde 0 a -1), por tanto, explícame a mí cómo se puede ejecutar ese bucle. Y si no se puede ejecutar, ¿cómo se puede obtener el mensaje de error que indica que "No hay ninguna fila en la posición 3"? Digo yo que no habrá ninguna fila en la posición 1, 2, 3, etc. :-))

    > Puede ser que el error se produzca debido a alguna propiedad que
    > halla modificado del DGV? Porque en esta función la primer linea
    > seria el encabezado del DGV y luego tengo otra función donde el
    > encabezado no es la primer fila.

    Pues ni idea, y menos aún sin saber cómo tienes configurado el control DataGridView. Para salir de dudas, haz una copia de seguridad del formulario, y posteriormente elimina del mismo el control DataGridView e inserta uno nuevo, dejando los valores que tengan por defecto TODAS SUS PROPIEDADES, y prueba a ver si dejas de obtener el error que comentas.

    Fíjate lo que ejecutas ANTES de obtener el objeto DataTable, es decir, ANTES de llamar a la función lP_CargaDataTable:

    > DgvImportar.Rows.Clear()
    > DgvImportar.Columns.Clear()

    Por si lo ignoras, te comento que con ese código estás eliminando TODAS LAS FILAS Y COLUMNAS, respectivamente, existentes en el control DataGridView. Pero entiendo que eso no tendría nada que ver, porque tu intención es enlazar posteriormente el control DataGridView con el objeto DataTable obtenido de la función lP_CargaDataTable, pero como dices que obtienes el mensaje de error "No hay ninguna fila en la posición 3", cuestión esta que yo soy incapaz de reproducir, pues no tengo ni la menor idea de lo que te puede estar sucediendo. ¡Lo siento!


    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.


    martes, 30 de enero de 2018 16:01
    Moderador
  • No lo pude solucionar con las ultimas opciones que me diste, muchas gracias igual.

    Buscare otras opciones para validar las filas.

    Saludos!

    miércoles, 31 de enero de 2018 12:41
  • Yo lo hice de esta forma y me funcinó:

    Espero a alguien pueda servirle.

                Dim Fila2 As Integer = 0
                For Fila As Integer = 0 To NRow - 1
                    If ElGrid.Rows(Fila).Visible = True Then
                        For Col As Integer = 0 To NCol - 1

                            exHoja.Cells.Item(Fila2 + 2, Col + 1) = ElGrid.Item(Col, Fila).Value

                        Next
                        Fila2 = Fila2 + 1
                    End If
                Next

    viernes, 28 de diciembre de 2018 18:23