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:
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:
- Leer el archivo
- Analizar las líneas
- Asignar los datos CSV a una clase
- convertir el texto en el tipo de datos adecuado
- 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.