Reputation: 35
I currently have a program that uses Linq to read a CSV file. Everything was working great until a recent change was done where the CSV file had records being added to it where the last 2 columns where empty.
So, the error I am getting now is Index was outside the bounds of the array. The question I have is how do I handle a column where an empty or null value is set in the CSV file?
Here's my abbreviated code below. Thanks for any help in advance.
Function readLINQ(ByVal strCustomerFile As String) As DataTable
Dim readlines = File.ReadAllLines(strCustomerFile)
File.WriteAllLines(strCustomerFile, readlines.Skip(4).ToArray())
Dim gTable As New DataTable("CashFile")
With gTable
.Columns.Add("Num").DataType = GetType(System.String)
.Columns.Add("EnvNum").DataType = GetType(System.String)
.Columns.Add("TransNum").DataType = GetType(System.String)
.Columns.Add("Envelope").DataType = GetType(System.String)
.Columns.Add("RemitterName").DataType = GetType(System.String)
.Columns.Add("InvoiceNumber").DataType = GetType(System.String)
End With
Dim lines As String() = System.IO.File.ReadAllLines(strCustomerFile)
Dim pattern As String = ",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
Dim r As System.Text.RegularExpressions.Regex = New System.Text.RegularExpressions.Regex(pattern)
Dim custs = From line In lines Where line <> header AndAlso Not String.IsNullOrEmpty(line)
Let data = r.Split(line)
Select New With {.Num = data(0), .EnvNum = data(1), .TransNum = data(2), .Envelope = data(3), .RemitterName = data(4), .InvoiceNumber = data(5)}
Dim xRow As DataRow
For Each row In custs
xRow = gTable.NewRow()
xRow.ItemArray = {row.Num, row.EnvNum, row.TransNum, row.Envelope, _
row.RemitterName, row.InvoiceNumber}
gTable.Rows.Add(xRow)
Next
readlines = Nothing
lines = Nothing
Return gTable
End Function
Upvotes: 0
Views: 1561
Reputation: 35
This is what ended up being a viable alternative solution. I posted all of the columns here so it may be a bit long. Hope this helps someone down the road.
Function TextFieldReadCSV(ByVal strCustomerFile As String) As DataTable
'need to skip 4 lines
Dim readlines = File.ReadAllLines(strCustomerFile)
File.WriteAllLines(strcustomerfile, readlines.Skip(4).ToArray())
Dim gTable As New DataTable("CashFile")
With gTable
.Columns.Add("Num").DataType = GetType(System.String)
.Columns.Add("EnvNum").DataType = GetType(System.String)
.Columns.Add("TransNum").DataType = GetType(System.String)
.Columns.Add("Envelope").DataType = GetType(System.String)
.Columns.Add("TID").DataType = GetType(System.String)
.Columns.Add("TransUID").DataType = GetType(System.String)
.Columns.Add("Lockbox").DataType = GetType(System.String)
.Columns.Add("Date").DataType = GetType(System.String)
.Columns.Add("Time").DataType = GetType(System.String)
.Columns.Add("Batch").DataType = GetType(System.String)
.Columns.Add("BatchItem").DataType = GetType(System.String)
.Columns.Add("TransSource").DataType = GetType(System.String)
.Columns.Add("Group").DataType = GetType(System.String)
.Columns.Add("GroupName").DataType = GetType(System.String)
.Columns.Add("Amount").DataType = GetType(System.String)
.Columns.Add("ABART").DataType = GetType(System.String)
.Columns.Add("AccountNum").DataType = GetType(System.String)
.Columns.Add("CheckNum").DataType = GetType(System.String)
.Columns.Add("NumImages").DataType = GetType(System.String)
.Columns.Add("CheckImage").DataType = GetType(System.String)
.Columns.Add("CheckBack").DataType = GetType(System.String)
.Columns.Add("EnvelopeImage").DataType = GetType(System.String)
.Columns.Add("EnvelopeBack").DataType = GetType(System.String)
.Columns.Add("InvoiceImage").DataType = GetType(System.String)
.Columns.Add("InvoiceBack").DataType = GetType(System.String)
.Columns.Add("AllPageImages").DataType = GetType(System.String)
.Columns.Add("AllPageBack").DataType = GetType(System.String)
.Columns.Add("RemitterName").DataType = GetType(System.String)
.Columns.Add("InvoiceNumber").DataType = GetType(System.String)
End With
Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser(strCustomerFile)
MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(",")
Dim currentRow As String()
While Not MyReader.EndOfData
currentRow = MyReader.ReadFields()
Dim currentField As String
Dim FieldArray(28) As String
Dim i = 0
For Each currentField In currentRow
FieldArray(i) = currentField
i = i + 1
Next
Dim xRow As DataRow
xRow = gTable.NewRow()
xRow.ItemArray = {FieldArray(0), FieldArray(1), FieldArray(2), FieldArray(3), FieldArray(4), FieldArray(5), FieldArray(6), FieldArray(7), _
FieldArray(8), FieldArray(9), FieldArray(10), FieldArray(11), FieldArray(12), FieldArray(13), FieldArray(14), FieldArray(15), _
FieldArray(16), FieldArray(17), FieldArray(18), FieldArray(19), FieldArray(20), FieldArray(21), FieldArray(22), _
FieldArray(23), FieldArray(24), FieldArray(25), FieldArray(26), FieldArray(27), FieldArray(28)}
gTable.Rows.Add(xRow)
End While
End Using
Return gTable
End Function
Upvotes: 1
Reputation: 109185
You could simply use
Let data = r.Split(line + ",,")
by which you add two empty entries add the end of each line. They are ignored for lines with 6 entries and for lines with 4 entries they add two empty entries, so data(4)
and data(5)
are not out of bounds.
This causes RemitterName and InvoiceNumber to be empty strings. I assume that is what should happen when the last 2 columns are absent.
Upvotes: 0