none
Importar TXT a TABLA SQLSERVER (automaticamente) RRS feed

  • Pregunta

  • Hola amigos.

    Estoy tratando de hacer una rutina que lea un TXT y lo incorpore a una tabla SQL Server de forma automática picando un botón.

    Entre las opciones que barajo está el cargar los datos a un DataGridView, mostrarlos en pantalla y luego haciendo click en otro botón pasarlos a una tabla SQL Server.

    En el TXT los campos están delimitados por ;

    Agradecería cualquier ayuda.

    Salud!

    viernes, 12 de junio de 2015 7:00

Respuestas

  • Yo soy partidario de no leer el fichero con el JET Engine. Aparte del problema que mencionas con el ini, otro inconveniente es que fallará si alguna vez lo ruedas en una máquina que no tenga el driver Text para el JET, y también fallará si alguna vez lo ruedas en 64 bits, porque únicamente hay JET en 32 bits. Puedes leer el fichero con un bucle y trocear las líneas con Split. No queda mucho más largo que lo que has escrito, más o menos sería algo parecido a lo siguiente (escrito de memoria, no lo he probado):

    imports System.IO
    ...
    
    Dim lineas as String()=File.ReadAllLines(fichero)
    
    Dim NombresColumnas as String() = lineas(0).Split(";"c)
    
    Dim dt as New DataTable()
    Foreach NombreColumna as String in NombresColumnas
        dt.Columns.Add(NombreColumna, GetType(String))
    Next
    
    For i as Integer=1 to lineas.Length-1
        Dim Columnas as String() = lineas(i).Split(";"c)
        dt.Rows.Add(Columnas)
    Next
    
    DataGridView1.DataSource = dt
    

    • Marcado como respuesta JotaQ martes, 16 de junio de 2015 6:34
    domingo, 14 de junio de 2015 11:44

Todas las respuestas

  • Todo se puede hacer, dependiendo de tus objetivos. Para leer el txt separado por ";", puedes usar un StreamReader para leer linea por linea, y cada linea trocearla por el ";" mediante String.Split. El resultado lo cargas en un List<miClase> o en un DataTable, y lo vinculas con el Grid. A la hora de grabar, simplemente ese mismo DataTable lo vuelcas al SqlServer con un SqlBulkInsert.

    Otra opción es usar el asistente para importar y exportar de Sql Server desde SSMS. Cuando termine el asistente, le dices que salve el paquete de SSIS. Cada vez que quieras repetir la importación simplemente ejecutas el paquete. Esto no te presenta los datos en pantalla, pero tiene la ventaja de que lo puedes automatizar muy fácilmente para que se ejecute periódicamente mediante el Agente de SQL Server.

    viernes, 12 de junio de 2015 9:41
  • Alberto gracias por la resupuesta.

    Estoy usando este código:

    Dim file As String = "test.txt"
    Dim path As String = "C:\tt\"
    Dim ds As New DataSet
    Try
    If IO.File.Exists(IO.Path.Combine(path, file)) Then
    Dim ConStr As String = _
    "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
    path & ";Extended Properties=""text;HDR=Yes;FMT=Delimited ( ; )\"""
    Dim conn As New OleDb.OleDbConnection(ConStr)
    Dim da As New OleDb.OleDbDataAdapter("Select * from " & _
    file, conn)
    da.Fill(ds, "TextFile")
    End If
    Catch ex As Exception
    MessageBox.Show(ex.ToString)
    End Try
    DataGridView1.DataSource = ds.Tables(0)

    Funciona bien pero se necesita un fichero Schema.ini para cada fichero importado, de otra manera no hace correctamente el split:

    [test.txt]
    Format=Delimited( ; )
    ColNameHeader=True
    MaxScanRows=0

    conoces alguna forma en la que pueda prescindir del schema.ini?

    GRacias de nuevo


    domingo, 14 de junio de 2015 9:40
  • Yo soy partidario de no leer el fichero con el JET Engine. Aparte del problema que mencionas con el ini, otro inconveniente es que fallará si alguna vez lo ruedas en una máquina que no tenga el driver Text para el JET, y también fallará si alguna vez lo ruedas en 64 bits, porque únicamente hay JET en 32 bits. Puedes leer el fichero con un bucle y trocear las líneas con Split. No queda mucho más largo que lo que has escrito, más o menos sería algo parecido a lo siguiente (escrito de memoria, no lo he probado):

    imports System.IO
    ...
    
    Dim lineas as String()=File.ReadAllLines(fichero)
    
    Dim NombresColumnas as String() = lineas(0).Split(";"c)
    
    Dim dt as New DataTable()
    Foreach NombreColumna as String in NombresColumnas
        dt.Columns.Add(NombreColumna, GetType(String))
    Next
    
    For i as Integer=1 to lineas.Length-1
        Dim Columnas as String() = lineas(i).Split(";"c)
        dt.Rows.Add(Columnas)
    Next
    
    DataGridView1.DataSource = dt
    

    • Marcado como respuesta JotaQ martes, 16 de junio de 2015 6:34
    domingo, 14 de junio de 2015 11:44
  • Alberto el código que me has puesto funciona a la perfección. Muchísimas gracias

    Solamente quería preguntarte si existe limitación en el tamaño del txt porque los txt que voy a manejar tienen muchas filas, son grandes y como se cargan en un string

    Un saludo!

    martes, 16 de junio de 2015 6:34
  • Tal como está el ejemplo que te puse, el límite de tamaño es aproximadamente dos gigabytes, si lo ruedas en 32 bits. Nótese que si lo vas a vincular a un DataGrid, de todas formas tendrías también ese límite en el DataTable, y lo volverías a tener en el DataGrid. Si ruedas en 32 bits, las tres cosas se cargan a la vez en memoria, por lo que no podrás tratar archivos de más de unos cientos de megas por esta vía.

    Si necesitas ficheros mayores, la parte de los Strings se puede obviar usando un StreamReader para procesar el fichero linea por linea sin cargarlas todaas en memoria... pero si las pasas a un DataTable para mostrarlas en el Grid seguirás teniendo limitaciones de tamaño en esa parte.

    martes, 16 de junio de 2015 8:02
  • No... con 2Gb me sobra

    Muchas gracias de nuevo

    Un saludo!

    martes, 16 de junio de 2015 10:22
  • Por cierto Alberto... ¿Se te ocurre una manera de controlar que si el usuario elige un fichero que no se ajusta a las especificaciones de un fichero con texto separado por  " ; " se le avise de que ese fichero no es adecuado??

    Gracias

    martes, 16 de junio de 2015 11:25
  • Lo más sencillo que se me ocurre es examinar el resultado del Split, cuando haces esto:

    Dim NombresColumnas as String() = lineas(0).Split(";"c)

    El array contiene los nombres de las columnas. Si tiene menos de dos elementos significa que la primera línea del fichero no tenía los nombres de columnas separados por punto y coma. Además también se podrían examinar los nombres, por ejemplo, si tú sabes que todos los ficheros tienen una primera columna llamada "Codigo", puedes verificar que NombresColumnas(0) cumple efectivamente ese criterio.

    martes, 16 de junio de 2015 11:32