Importare TXT delimitato da spazi

di hantrax il
34 risposte

Ciao…

Dovrei importare un file TXT delimitato da spazi (non tab) in un dataview, il numero degli spazi però non è fisso..

alla fine dovrei avere una colonna per Area, una per areaelem….

ho provato con questo codice trovato online, ma vede ogni spazio come una colonna…
la chiamo con :

Dim TXT_Datatable As DataTable = txt_to_data(nomeFile, vbYes, Space(1))

Private Function txt_to_data(ByVal filename As String, ByVal header As Boolean, ByVal delimiter As String) As DataTable
    'New datatable
    Dim dt As DataTable = New DataTable

    'Read the contents of the textfile into an array
    Dim sr As IO.StreamReader = New IO.StreamReader(filename)
    Dim txtlines() As String = sr.ReadToEnd.Split({Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)

    'Return nothing if there's nothing in the textfile
    If txtlines.Count = 0 Then
        Return Nothing
    End If

    Dim column_count As Integer = 0
    For Each col As String In txtlines(0).Split({delimiter}, StringSplitOptions.None)
        If header Then
            'If there's a header then add it by it's name
            dt.Columns.Add(col)
            dt.Columns(column_count).Caption = col
        Else
            'If there's no header then add it by the column count
            dt.Columns.Add(String.Format("Column{0}", column_count))
            dt.Columns(column_count).Caption = String.Format("Column{0}", column_count + 1)
        End If

        column_count += 1
    Next

    If header Then
        For rows As Integer = 1 To txtlines.Count - 1 'start at one because there's a header for the first line(0)
            'Declare a new datarow
            Dim dr As DataRow = dt.NewRow

            'Set the column count back to 0, we can reuse this variable ;]
            column_count = 0
            For Each col As String In txtlines(rows).Split({delimiter}, StringSplitOptions.None) 'Each column in the row
                'The column in cue is set for the datarow
                dr(column_count) = col
                column_count += 1
            Next

            'Add the row
            dt.Rows.Add(dr)
        Next
    Else
        For rows As Integer = 0 To txtlines.Count - 1 'start at zero because there's no header
            'Declare a new datarow
            Dim dr As DataRow = dt.NewRow

            'Set the column count back to 0, we can reuse this variable ;]
            column_count = 0
            For Each col As String In txtlines(rows).Split({delimiter}, StringSplitOptions.None) 'Each column in the row
                'The column in cue is set for the datarow
                dr(column_count) = col
                column_count += 1
            Next

            'Add the row
            dt.Rows.Add(dr)
        Next
    End If

    Return dt
End Function

avete altre soluzioni?
dopo averlo importato devo filtrare i valori per colonna Area e poi Outputcase, e fare la media dei vaolri

34 Risposte

  • …questo codice trovato online…

    male!

    Riesci a sapere il numero massimo di spazi presenti tra una colonna e l'altra?

  • Guardando l'immagine che hai allegato mi sembra che la cosa sia molto banale, 
    è semplicemente un file TXT con colonne a larghezza fissa.
    Basta contare ogni colonna quanto larga è, estrarre i dati con un semplicissimo string.Substring(x, n).Trim per avere i dati.
    Poi i valori decimali si trasformano in numeri con Double.Parse

    Oppure puoi usare Microsoft.VisualBasic.FileIO.TextFieldParser che ti dà già tutto disposizione

  • Ciao…hai ragione..ma mi è servito per cominciare…
    ho modificato l'istruzione txtlines(0).Split({delimiter}, StringSplitOptions.None) mettendo StringSplitOptions.RemoveEmptyEntries ed ha funzionato…

    Il numero massimo di spazi dovrei saperlo…

    per calcolare la media, pensavo di:

    Ordinare il dataview per le due colonne che mi interessano

    Trovare i valori univoci delle due colonne

    Creare due for each per filtrare con i dati univoci e poi calcolare la media di ogni colonna,,,

    Per ora ho fatto questo:

           Dim ListaArea As New List(Of Double)
    
           Dim UniqueAREA As System.Collections.Generic.List(Of String) = ((From T In TXT_Datatable.AsEnumerable() Select T.Field(Of String)("Area")).Distinct()).OrderBy(Function(s) s).ToList()
           Dim UniqueCASE As System.Collections.Generic.List(Of String) = ((From T In TXT_Datatable.AsEnumerable() Select T.Field(Of String)("OutputCase")).Distinct()).OrderBy(Function(s) s).ToList()
    
    
           Dim TXTdataview As DataView = TXT_Datatable.AsDataView
    
           TXTdataview.Sort = "Area, OutputCase"
    
           If UniqueAREA.Item(0) Is Nothing Then UniqueAREA.RemoveAt(0)
           If UniqueCASE.Item(0) Is Nothing Then UniqueCASE.RemoveAt(0)
           UniqueAREA.Sort()
           UniqueCASE.Sort()
    
    
           For Each TXT_AREA As String In UniqueAREA
    
        For Each TXT_OUTPUTCASE As String In UniqueCASE
    
    
            Dim filterstr As String = "Area = " & "'" & TXT_AREA & "' " & "AND " & "Outputcase = " & "'" & TXT_OUTPUTCASE & "'"
            '"Area = '23' AND OutputCase '46'"
    
    
    
            TXTdataview.RowFilter = filterstr
    
    
            For k = 8 To 24
    
    
                For Each dataRowTMP As DataRowView In TXTdataview
    
                    F11 += F11
                    F22 += F22
                    F12 += F12
                    FMax += FMax
                    FMin += FMin
                    FAngle += FAngle
                    FVM += FVM
                    M11 += M11
                    M22 += M22
                    M12 += M12
    
    
    'trovo i totali delle colonne filtrate e calcolo la media
    
                    Dim TotTMP As Double = 0
    
    
    
    
                Next
    
    
    
            Next
    
    
    
    
    
    
            dataRowTMP = TXTdataview.Item(0)
    
    
            Me.DataGridView1.DataSource = TXTdataview
    
    
    
        Next
    
            

    c' è un modo più veloce?

  • Non so se è la maniera più veloce ma funziona.
    ora il problema è fargli scrivere il secondo datatable creato con le media, in un file txt che ha la stessa struttura di quello che aprivo

           Dim nomeFile As String = "E:\_Lavori\_Visual_Basic\07_VarieRFAEM\wetransfer_dirx_slu_zona_unica-txt_2023-09-05_1225\prova_media3.txt"
           Dim TXT_Datatable As DataTable = txt_to_data(nomeFile, True, Space(1))
           Dim TXTMedia_Datatable As DataTable = TXT_Datatable.Clone
    
           'ImpData(nomeFile)
    
           Dim ListaArea As New List(Of Double)
    
           Dim UniqueAREA As System.Collections.Generic.List(Of String) = ((From T In TXT_Datatable.AsEnumerable() Select T.Field(Of String)("Area")).Distinct()).OrderBy(Function(s) s).ToList()
           Dim UniqueCASE As System.Collections.Generic.List(Of String) = ((From T In TXT_Datatable.AsEnumerable() Select T.Field(Of String)("OutputCase")).Distinct()).OrderBy(Function(s) s).ToList()
    
    
           Dim TXTdataview As DataView = TXT_Datatable.AsDataView
    
           Me.DataGridView1.DataSource = TXTdataview
           Me.Update()
           TXTdataview.Sort = "Area, Joint, OutputCase"
           Me.DataGridView1.DataSource = TXTdataview
           Me.Update()
    
           If UniqueAREA.Item(0) Is Nothing Then UniqueAREA.RemoveAt(0)
           If UniqueCASE.Item(0) Is Nothing Then UniqueCASE.RemoveAt(0)
           UniqueAREA.Sort()
           UniqueCASE.Sort()
    
    
           For Each TXT_AREA As String In UniqueAREA
    
               For Each TXT_OUTPUTCASE As String In UniqueCASE
    
    
                   Dim filterstr As String = "Area = " & "'" & TXT_AREA & "' " & "AND " & "Outputcase = " & "'" & TXT_OUTPUTCASE & "'"
                   '"Area = '23' AND OutputCase '46'"
    
    
    
                   TXTdataview.RowFilter = filterstr
                   Me.DataGridView1.DataSource = TXTdataview
                   Me.Update()
    
                   Dim F11 As Double = 0
                   Dim F22 As Double = 0
                   Dim F12 As Double = 0
                   Dim FMax As Double = 0
                   Dim FMin As Double = 0
                   Dim FAngle As Double = 0
                   Dim FVM As Double = 0
                   Dim M11 As Double = 0
                   Dim M22 As Double = 0
                   Dim M12 As Double = 0
                   Dim MMax As Double = 0
                   Dim MMin As Double = 0
                   Dim MAngle As Double = 0
                   Dim V13 As Double = 0
                   Dim V23 As Double = 0
                   Dim VMax As Double = 0
                   Dim VAngle As Double = 0
    
    
    
                   Dim Area_media As String = ""
                   Dim AreaElem_Media As String = ""
                   Dim Shell_Media As String = ""
                   Dim Joint_Media As String = ""
                   Dim OutputCase_Media As String = ""
                   Dim CaseType_Media As String = ""
                   Dim StepType_Media As String = ""
    
    
                   Dim F11_Media As Double = 0
                   Dim F22_Media As Double = 0
                   Dim F12_Media As Double = 0
                   Dim FMax_Media As Double = 0
                   Dim FMin_Media As Double = 0
                   Dim FAngle_Media As Double = 0
                   Dim FVM_Media As Double = 0
                   Dim M11_Media As Double = 0
                   Dim M22_Media As Double = 0
                   Dim M12_Media As Double = 0
                   Dim MMax_Media As Double = 0
                   Dim MMin_Media As Double = 0
                   Dim MAngle_Media As Double = 0
                   Dim V13_Media As Double = 0
                   Dim V23_Media As Double = 0
                   Dim VMax_Media As Double = 0
                   Dim VAngle_Media As Double = 0
    
    
                   For Each dataRowTMP As DataRowView In TXTdataview
    
                       Area_media = dataRowTMP.Item(0)
                       AreaElem_Media = dataRowTMP.Item(1)
                       Shell_Media = dataRowTMP.Item(2)
                       Joint_Media = "CENTER"
                       OutputCase_Media = dataRowTMP.Item(4)
                       CaseType_Media = dataRowTMP.Item(5)
                       StepType_Media = "Min/MAX"
    
                       F11 += Double.Parse(dataRowTMP.Item(7).ToString.Replace(".", ","))
                       F22 += Double.Parse(dataRowTMP.Item(8).ToString.Replace(".", ","))
                       F12 += Double.Parse(dataRowTMP.Item(9).ToString.Replace(".", ","))
                       FMax += Double.Parse(dataRowTMP.Item(10).ToString.Replace(".", ","))
                       FMin += Double.Parse(dataRowTMP.Item(11).ToString.Replace(".", ","))
                       FAngle += Double.Parse(dataRowTMP.Item(12).ToString.Replace(".", ","))
                       FVM += Double.Parse(dataRowTMP.Item(13).ToString.Replace(".", ","))
                       M11 += Double.Parse(dataRowTMP.Item(14).ToString.Replace(".", ","))
                       M22 += Double.Parse(dataRowTMP.Item(15).ToString.Replace(".", ","))
                       M12 += Double.Parse(dataRowTMP.Item(16).ToString.Replace(".", ","))
                       MMax += Double.Parse(dataRowTMP.Item(17).ToString.Replace(".", ","))
                       MMin += Double.Parse(dataRowTMP.Item(18).ToString.Replace(".", ","))
                       MAngle += Double.Parse(dataRowTMP.Item(19).ToString.Replace(".", ","))
                       V13 += Double.Parse(dataRowTMP.Item(20).ToString.Replace(".", ","))
                       V23 += Double.Parse(dataRowTMP.Item(21).ToString.Replace(".", ","))
                       VMax += Double.Parse(dataRowTMP.Item(22).ToString.Replace(".", ","))
                       VAngle += Double.Parse(dataRowTMP.Item(23).ToString.Replace(".", ","))
    
    
                   Next
    
                   F11_Media = Math.Round(F11 / TXTdataview.Count, 2)
                   F22_Media = Math.Round(F22 / TXTdataview.Count, 2)
                   F12_Media = Math.Round(F12 / TXTdataview.Count, 2)
                   FMax_Media = Math.Round(FMax / TXTdataview.Count, 2)
                   FMin_Media = Math.Round(FMin / TXTdataview.Count, 2)
                   FAngle_Media = Math.Round(FAngle / TXTdataview.Count, 2)
                   FVM_Media = Math.Round(FVM / TXTdataview.Count, 2)
                   M11_Media = Math.Round(M11 / TXTdataview.Count, 2)
                   M22_Media = Math.Round(M22 / TXTdataview.Count, 2)
                   M12_Media = Math.Round(M12 / TXTdataview.Count, 2)
                   MMax_Media = Math.Round(MMax / TXTdataview.Count, 2)
                   MMin_Media = Math.Round(MMin / TXTdataview.Count, 2)
                   MAngle_Media = Math.Round(MAngle / TXTdataview.Count, 2)
                   V13_Media = Math.Round(V13 / TXTdataview.Count, 2)
                   V23_Media = Math.Round(V23 / TXTdataview.Count, 2)
                   VMax_Media = Math.Round(VMax / TXTdataview.Count, 2)
                   VAngle_Media = Math.Round(VAngle / TXTdataview.Count, 2)
    
    
                   Dim drNewRow As DataRow = TXTMedia_Datatable.NewRow
    
                   drNewRow(0) = Area_media
                   drNewRow(1) = AreaElem_Media
                   drNewRow(2) = Shell_Media
                   drNewRow(3) = Joint_Media
                   drNewRow(4) = OutputCase_Media
                   drNewRow(5) = CaseType_Media
                   drNewRow(6) = StepType_Media
    
                   drNewRow(7) = F11_Media
                   drNewRow(8) = F22_Media
                   drNewRow(9) = F12_Media
                   drNewRow(10) = FMax_Media
                   drNewRow(11) = FMin_Media
                   drNewRow(12) = FAngle_Media
                   drNewRow(13) = FVM_Media
                   drNewRow(14) = M11_Media
                   drNewRow(15) = M22_Media
                   drNewRow(16) = M12_Media
                   drNewRow(17) = MMax_Media
                   drNewRow(18) = MMin_Media
                   drNewRow(19) = MAngle_Media
                   drNewRow(20) = V13_Media
                   drNewRow(21) = V23_Media
                   drNewRow(22) = VMax_Media
                   drNewRow(23) = VAngle_Media
    
                   TXTMedia_Datatable.Rows.Add(drNewRow)
    
    
                   Me.DataGridView1.DataSource = TXTdataview
                   Me.DataGridView2.DataSource = TXTMedia_Datatable
    
                   Me.Update()
    
    
               Next
    
           Next
  • Boh, secondo me il tuo approccio è sbagliato.
    Hai un file TXT con le colonne a larghezza fissa eppure continui a fare lo SPLIT con un DELIMITER.
    Ti funziona solo perchè dentro nel file non ci sono dati con lo spazio in mezzo, e quindi diciamo che finora sei solo stato fortunato, ma se ti arriva un file con uno spazio in mezzo cosa fai ??
    Prova ad esempio a modificare il file, sostituendo un qualsiasi “Shell-Thin” con “Shell Thin” e poi vedrai che non funziona più nulla.

  • In questo caso il file TXT che esce dal programma di calcolo è sempre così e non cambia, ma comunque  hai ragione e provo a sistemare il codice per farlo funzionare sempre.

    Per quanto riguarda invece il calcolo dei valori medi, ho lanciato il programma e per elaborare 1 milione di righe del file txt impiega una vita..dopo 3 ore era ancora al 15%…

    c'è un altro sistema che posso utilizzare più veloce?

    attualmente leggo dalle due colonne che mi interessano i valori univoci, e poi con due for each filtro il dataview e calcolo la media….

  • Ma devi calcolare la media di sole due colonne ??
    Si può avere questo file ??

  • Non so come allegare il file….

    comunque studiando ho trovato datatype.compute() è ho scritto questo:
    Funziona e in circa 1 ora calcola tutto considerando che il txt originale è da circa 1645000 righe) prima dopo 3 ore non aveva finito

    poi passo all'importazione del txt fissando il numero di caratteri delle colonne in modo da farlo funzionare sempre

     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
    
    
         Dim nomeFile As String = "prova_media.txt"
    
         Dim TXT_Datatable As DataTable = txt_to_data(nomeFile, True, Space(1))
         Dim TXTMedia_Datatable As DataTable = TXT_Datatable.Clone
    
         'ImpData(nomeFile)
    
         Dim ListaArea As New List(Of Double)
    
         Dim UniqueAREA As System.Collections.Generic.List(Of String) = ((From T In TXT_Datatable.AsEnumerable() Select T.Field(Of String)("Area")).Distinct()).OrderBy(Function(s) s).ToList()
         Dim UniqueCASE As System.Collections.Generic.List(Of String) = ((From T In TXT_Datatable.AsEnumerable() Select T.Field(Of String)("OutputCase")).Distinct()).OrderBy(Function(s) s).ToList()
    
         Me.Label3.Text = TimeString
    
    
         Me.TextBox_Aree.Text = UniqueAREA.Count.ToString
    
         Me.TextBox_Combi.Text = UniqueCASE.Count.ToString
    
         Me.TextBox_Aree.ReadOnly = True
         Me.TextBox_Combi.ReadOnly = True
    
         Me.ProgressBar_Area.Maximum = UniqueAREA.Count
         Me.ProgressBar_Combinazioni.Maximum = UniqueCASE.Count
    
         Me.ProgressBar_Area.Minimum = 1
         Me.ProgressBar_Combinazioni.Minimum = 1
    
         Me.ProgressBar_Area.Step = 1
         Me.ProgressBar_Combinazioni.Step = 1
         Dim TXTdataview As DataView = TXT_Datatable.AsDataView
    
         Me.DataGridView1.DataSource = TXTdataview
         Me.Update()
         TXTdataview.Sort = "Area, Joint, OutputCase"
         Me.DataGridView1.DataSource = TXTdataview
         Me.Update()
    
         If UniqueAREA.Item(0) Is Nothing Then UniqueAREA.RemoveAt(0)
         If UniqueCASE.Item(0) Is Nothing Then UniqueCASE.RemoveAt(0)
         UniqueAREA.Sort()
         UniqueCASE.Sort()
    
    
         For Each TXT_AREA As String In UniqueAREA
    
             For Each TXT_OUTPUTCASE As String In UniqueCASE
                 Dim filterstr As String = "Area = " & "'" & TXT_AREA & "' " & "AND " & "Outputcase = " & "'" & TXT_OUTPUTCASE & "'"
    
                 Dim F11_Media As Double = TXT_Datatable.Compute("Avg(F11)", filterstr)
                 Dim F22_Media As Double = TXT_Datatable.Compute("Avg(F22)", filterstr)
                 Dim F12_Media As Double = TXT_Datatable.Compute("Avg(F12)", filterstr)
                 Dim FMax_Media As Double = TXT_Datatable.Compute("Avg(FMax)", filterstr)
                 Dim FMin_Media As Double = TXT_Datatable.Compute("Avg(FMin)", filterstr)
                 Dim FAngle_Media As Double = TXT_Datatable.Compute("Avg(FAngle)", filterstr)
                 Dim FVM_Media As Double = TXT_Datatable.Compute("Avg(FVM)", filterstr)
                 Dim M11_Media As Double = TXT_Datatable.Compute("Avg(M11)", filterstr)
                 Dim M22_Media As Double = TXT_Datatable.Compute("Avg(M22)", filterstr)
                 Dim M12_Media As Double = TXT_Datatable.Compute("Avg(M12)", filterstr)
                 Dim MMax_Media As Double = TXT_Datatable.Compute("Avg(MMax)", filterstr)
                 Dim MMin_Media As Double = TXT_Datatable.Compute("Avg(F11)", filterstr)
                 Dim MAngle_Media As Double = TXT_Datatable.Compute("Avg(MMin)", filterstr)
                 Dim V13_Media As Double = TXT_Datatable.Compute("Avg(V13)", filterstr)
                 Dim V23_Media As Double = TXT_Datatable.Compute("Avg(F11)", filterstr)
                 Dim VMax_Media As Double = TXT_Datatable.Compute("Avg(VMax)", filterstr)
                 Dim VAngle_Media As Double = TXT_Datatable.Compute("Avg(VAngle)", filterstr)
    
    
                 Dim drNewRow As DataRow = TXTMedia_Datatable.NewRow
    
                 drNewRow(0) = TXT_AREA
                 drNewRow(1) = TXT_AREA
                 drNewRow(2) = "Shell-Thin"
                 drNewRow(3) = "CENTER"
                 drNewRow(4) = TXT_OUTPUTCASE
                 drNewRow(5) = "Combination"
                 drNewRow(6) = "Min/Max"
    
                 drNewRow(7) = F11_Media
                 drNewRow(8) = F22_Media
                 drNewRow(9) = F12_Media
                 drNewRow(10) = FMax_Media
                 drNewRow(11) = FMin_Media
                 drNewRow(12) = FAngle_Media
                 drNewRow(13) = FVM_Media
                 drNewRow(14) = M11_Media
                 drNewRow(15) = M22_Media
                 drNewRow(16) = M12_Media
                 drNewRow(17) = MMax_Media
                 drNewRow(18) = MMin_Media
                 drNewRow(19) = MAngle_Media
                 drNewRow(20) = V13_Media
                 drNewRow(21) = V23_Media
                 drNewRow(22) = VMax_Media
                 drNewRow(23) = VAngle_Media
    
                 TXTMedia_Datatable.Rows.Add(drNewRow)
    
    
                 Me.DataGridView1.DataSource = TXTdataview
                 Me.DataGridView2.DataSource = TXTMedia_Datatable
    
                 Me.Update()
    
                 Me.ProgressBar_Combinazioni.PerformStep()
                 Me.Update()
    
    
             Next
             Me.ProgressBar_Area.PerformStep()
             Me.Update()
         Next
    
         Me.Label4.Text = TimeString
    
     End Sub
  • Riesci a mettere il file su qualche server e/o servizio cloud in modo che posso scaricarlo ??

  • Ok, provo a dargli un'occhiata e vediamo se i tempi di elaborazione sono gli stessi o se riesco a ridurli.
    Ho la necessità di sapere di quali colonne hai bisogno la media

    Ti sarà arrivata una email di richiesta da google per poter condividere il file TXT altrimenti non riesco a scaricarlo

  • Le colonne da cui calcolare la media sono dalla F11 all'ultima colonna

    Per ogni elemento della colonna Area, posso avere n combinazioni di carico (Outputcase) la media la calcolo filtrando la colonna area e outputcase

  • ….. riesci a farmi avere il file TXT ??

Devi accedere o registrarti per scrivere nel forum
34 risposte