Saltar al contenido

Leyendo el archivo CSV, faltan algunas columnas

Mantén la atención porque en esta división vas a encontrar la contestación que buscas.Este escrito ha sido aprobado por nuestros expertos para asegurar la calidad y veracidad de nuestro post.

Solución:

Una cosa con la que debes enfrentarte es que esos Filexxxx Los métodos están prácticamente en desuso oficial y formalmente. Al usarlos, Intellisense aparece con:

… La función My le ofrece una mejor productividad y rendimiento en las operaciones de E / S de archivos que FileOpen. Para obtener más información, consulte Microsoft.VisualBasic.FileIO.FileSystem.

Están hablando sobre My.Computer.FileSystem pero hay algunos métodos NET aún más útiles.

La publicación no revela cómo se almacenarán los datos, pero si es un array de cualquier tipo y / o estructura, son al menos subóptimas, si no también obsoletas. Esto lo almacenará en una clase para que los datos numéricos se puedan almacenar como números y un List se utilizará en lugar de un array.

Hice un archivo rápido similar al tuyo con algunos datos aleatorios: "CustName", "Phone", "UserName", "Product", "Cost", "Price", "Profit", "SaleDate", "RefCode":

  • El CustName está presente el 70% del tiempo
  • El nombre de usuario nunca está presente
  • El RefCode está presente el 30% del tiempo
  • Agregué un Fecha de venta para ilustrar esa conversión de datos

Ziggy Aurantium, 132-5562“ Comida para gatos, 8.26,9.95,1.69,08 / 04/2016,
Catrina Caison, 899-8599“ Afilador de cuchillos, 4.95,6.68,1.73,10 / 12/2016, X-873-W3
, 784-4182“ Compresor de vapor, 11.02,12.53,1.51,09 / 12/2016,

Código para analizar el CSV

Nota: esta es una mala forma de analizar un CSV. Hay muchos problemas que pueden surgir al hacerlo de esta manera; además se necesita más código. Se presenta porque es una forma sencilla de no tener que lidiar con los campos que faltan. Ver La direccion correcta

' form/class level var:
Private SalesItems As List(Of SaleItem)

SaleItem es una clase simple para almacenar los elementos que le interesan. SalesItems es una colección que puede almacenar solamenteSaleItem objetos. Las propiedades en esa clase permiten Precio y Costo para ser almacenado como Decimal y la fecha como DateTime.

' temp var
Dim item As SaleItem
' create the collection
SalesItems = New List(Of SaleItem)
    
' load the data....all of it
Dim data = File.ReadAllLines("C:Tempcustdata.csv")

' parse data lines 
' Start at 1 to skip a Header
For n As Int32 = 0 To data.Length - 1
    Dim split = data(n).Split(","c)

    ' check if it is a good line
    If split.Length = 9 Then
        ' create a new item
        item = New SaleItem
        ' store SOME data to it
        item.CustName = split(0)
        item.Phone = split(1)
        ' dont care anout user name (2)
        item.Product = split(3)
        ' convert numbers
        item.Price = Convert.ToDecimal(split(4))
        item.Cost = Convert.ToDecimal(split(5))
        ' dont use the PROFIT, calculate it in the class (6)

        ' convert date
        item.SaleDate = Convert.ToDateTime(split(7))

        ' ignore nonexistant RefCode (8)

        ' add new item to collection
        ' a List sizes itself as needed!
        SalesItems.Add(item)
    Else
        ' To Do: make note of a bad line format
    End If
Next

' show in DGV for approval/debugging
dgvMem.DataSource = SalesItems

Resultado:
ingrese la descripción de la imagen aquí

Notas

Por lo general, es una mala idea almacenar algo que se pueda calcular simplemente. Entonces el Profit propiedad es:

Public ReadOnly Property Profit As Decimal
    Get
        Return (Cost - Price)
    End Get
End Property

Nunca puede quedar “obsoleto” si se actualiza el costo o el precio.

Como se muestra, el uso de la colección resultante se puede mostrar al usuario muy fácilmente. Dado un DataSource, los DataGridView creará las columnas y poblará las filas.

La direccion correcta

String.Split(c) es una muy mala idea porque si el producto es: "Hose, Small Green" lo cortará y lo tratará como 2 campos. Hay una serie de herramientas que harán casi todo el trabajo por usted:

  1. Leer el archivo
  2. Analizar las líneas
  3. Asignar los datos CSV a una clase
  4. convertir el texto en el tipo de datos adecuado
  5. crear una colección económica

Aparte de la clase, todo lo anterior se puede hacer en unas pocas líneas usando CSVHelper:

Private CustData As List(Of SaleItem)
...
Using sr As New StreamReader("C:Tempcustdata.csv", False),
     csv = New CsvReader(sr)
    csv.Configuration.HasHeaderRecord = True

    CustData = csv.GetRecords(Of SaleItem)().ToList()
End Using

Dos o tres líneas de código para leer, analizar y crear una colección de 250 elementos.

Incluso si quieres hacerlo manualmente por alguna razón, CSVHelper puede ayudar. En lugar de crear un List(Of SaleItem) para usted, puede usarlo para leer y analizar los datos:

... like above
csv.Configuration.HasHeaderRecord = True
Do Until csv.Read() = False
    For n As Int32 = 0 To csv.Parser.FieldCount - 1
        DoSomethingWith(csv.GetField(n))
    Next
Loop

Esto le devolverá los campos uno por uno. No convertirá ninguna fecha o precio, pero tampoco se ahogará con elementos de datos faltantes.

Recursos

  • Introducción de cinco minutos a clases y listas
  • CSVHelper
  • Clase vs estructura
    • Pensamientos de Eric Lippert al respecto
  • La clase de archivo tiene montones de métodos útiles

Al usar la siguiente función, puede evaluar el contenido del archivo línea por línea y tomar la acción apropiada.

Imports System.IO    
Private Sub ParseCSVFile(psFile As String)
    Dim sArray() As String
    Dim Customer_Name As String = String.Empty
    Dim Phone_Number As String = String.Empty
    Dim Username As String = String.Empty
    Dim Product As String = String.Empty
    Dim Wholesale_Cost As String = String.Empty
    Dim Sales_Price As String = String.Empty
    Dim Gross_Profit As String = String.Empty
    Dim Customer_Reference As String = String.Empty

    Try
        Using objStreamReader As StreamReader = New StreamReader(psFile) 'should be full path
            Dim sLine As String = String.Empty
            Do
                sLine = objStreamReader.ReadLine()
                If sLine <> Nothing Then
                    sArray = Split(sLine, ",")
                    Customer_Name = sArray(0)
                    Phone_Number = sArray(1)
                    Username = sArray(2)
                    Product = sArray(3)
                    Wholesale_Cost = sArray(4)
                    Sales_Price = sArray(5)
                    Gross_Profit = sArray(6)
                    Customer_Reference = sArray(7)
                    Debug.Print(Customer_Name & "," & Phone_Number & "," & Username & "," & Product & "," & Wholesale_Cost & "," & Sales_Price & "," & Gross_Profit & "," & Customer_Reference)
                End If
            Loop Until sLine Is Nothing
        End Using
    Catch
        'log error
    End Try
End Sub

Advertencia: si CustomerName o ProductName los valores pueden contener comas
(.es decir CustomerName = "Callaway , Mark") no puedes usar el String.Split() método. y es mejor buscar un analizador csv de terceros, o puede usar TextFieldParser Clase -> artículo de MSDN

  • Puede seguir este enlace para aprender a importar csv usando TextFieldParser

    https://www.daniweb.com/programming/software-development/code/438959/read-in-text-from-csv-with-textfieldparser

  • Anteriormente me enfrenté a un problema al importar un archivo Csv usando los servicios de integración del servidor SQL (los campos contienen delimitadores), puede echar un vistazo (código en Vb.net):

    Error de importación de archivo CSV: valor de columna que contiene el delimitador de columna

Mi respuesta es asumir que los campos que faltan son siempre desde el lado derecho de la línea y ese valor de Campos no contiene comas(de lo contrario, la respuesta de @Plutonix es lo que estás buscando)

Con este código podrá importar líneas con campos faltantes.

Tienes que leer cada línea del archivo csv, contar el "," ocurrencia en esta línea usando el siguiente código

Line.Count(Function(c As Char) c = ",")

si el recuento es menor que 7 (8 columnas) agregará faltante ","

 String.PadRight((7 - intCommaCount), ",")

Nota: si las comas que faltan son del lado izquierdo, puede usar String.PadLeft((7 - intCommaCount), ",")

Y dividir la línea en propiedades del artículo

Creé lo siguiente Item Clase

Public Class MyItem


Public Property CustomerName As String
Public Property PhoneNumber As String
Public Property Username As String
Public Property Product As String
Public Property WholesaleCost As String
Public Property SalesPrice As String
Public Property GrossProfit As String
Public Property CustomerReference As String

Public Shared Function CreateObjectFromLine(ByVal Line As String) As MyItem

    'Count Comma occurence in Line
    Dim intCommaCount As Integer = Line.Count(Function(c As Char) c = CChar(","))
    Dim strTemp = Line

    'Add missing comma's
    If intCommaCount < 7 Then

        strTemp = strTemp.PadRight((7 - intCommaCount), ",")

    End If

    'Split Line and return MyItem Class
    Dim str() As String = strTemp.Split(",")

    Return New MyItem With .CustomerName = str(0),
        .PhoneNumber = str(1),
        .Username = str(2),
        .Product = str(3),
        .WholesaleCost = str(4),
        .SalesPrice = str(5),
        .GrossProfit = str(6),
        .CustomerReference = str(7)




End Function



End Class

Y utilicé el siguiente código para importar datos desde un archivo CSV

    Dim SalesItems As New List(Of MyItem)
    Dim csvFile As String = "C:1.csv"


    Using csvStreamReader As New IO.StreamReader(csvFile)

        While Not csvStreamReader.EndOfStream

       Dim strLine as string = csvStreamReader.ReadLine

       ' Skip Header
       If strLine.StartsWith("Customer Name") Then Continue While

            Dim item As MyItem = MyItem.CreateObjectFromLine(strLine)

            SalesItems.Add(item)



        End While


    End Using

    'Showing Result in a DataGridView
    dgvItems.DataSource = SalesItems

Nota:Este es un ejemplo simple que necesita agregar manejo de errores Try... Catch , Null Comprobación

Al final de la post puedes encontrar las explicaciones de otros programadores, tú además puedes dejar el tuyo si dominas el tema.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *