tags:

views:

67

answers:

2

I have a csv file with 48 columns of data. I need to open this file, place it into a data structure and then search that data and present it in a DataRepeater.

So far I have successfully used CSVReader to extract the data and bind it to myDataRepeater. However I am now struggling to place the data in a table so that I can filter the results. I do not want to use SQL or any other database.

Does anyone have a suggestion on the best way to do this?

So far, this is working in returning all records:

Private Sub BindCsv()
    ' open the file "data.csv" which is a CSV file with headers"
    Dim dirInfo As New DirectoryInfo(Server.MapPath("~/ftp/"))
    Dim fileLocation As String = dirInfo.ToString & "data.txt"
    Using csv As New CsvReader(New StreamReader(fileLocation), True)
        myDataRepeater.DataSource = csv
        myDataRepeater.DataBind()
    End Using
End Sub

Protected Sub myDataRepeater_ItemDataBound(ByVal sender As Object, ByVal e As RepeaterItemEventArgs) Handles myDataRepeater.ItemDataBound

    Dim dataItem As String() = DirectCast(e.Item.DataItem, String())

    DirectCast(e.Item.FindControl("lblPropertyName"), ITextControl).Text = dataItem(2).ToString
    DirectCast(e.Item.FindControl("lblPrice"), ITextControl).Text = dataItem(7).ToString

    DirectCast(e.Item.FindControl("lblPricePrefix"), ITextControl).Text = dataItem(6)
    DirectCast(e.Item.FindControl("lblPropertyID"), ITextControl).Text = dataItem(1)
    DirectCast(e.Item.FindControl("lblTYPE"), ITextControl).Text = dataItem(18)
    DirectCast(e.Item.FindControl("lblBedrooms"), ITextControl).Text = dataItem(8)
    DirectCast(e.Item.FindControl("lblShortDescription"), ITextControl).Text = dataItem(37)

    Dim dirInfo As New DirectoryInfo(Server.MapPath("~/ftp/images/"))
    DirectCast(e.Item.FindControl("imgMain"), Image).ImageUrl = dirInfo.ToString & "pBRANCH_" & dataItem(1) & ".jpg"
    DirectCast(e.Item.FindControl("linkMap"), HyperLink).NavigateUrl = "http://www.multimap.com/map/browse.cgi?client=public&db=pc&cidr_client=none&lang=&pc=" & dataItem(5) & "&advanced=&client=public&addr2=&quicksearch=" & dataItem(5) & "&addr3=&addr1="
End Sub

Code add to filter results:

 Try
        Dim csv As New CSVFile(fileLocation)
        Dim ds As DataSet = csv.ToDataSet("MyTable")
        If Not ds Is Nothing Then


            Dim strExpr As String = "Bedrooms >= '3'"
            Dim strSort As String = "PropertyID ASC"

            'Use the Select method to find all rows matching the filter.
            Dim myRows() As DataRow
            'myRows = Dt.Select(strExpr, strSort)
            myRows = csv.ToDataSet("MyTable").Tables("MyTable").Select(strExpr, strSort)
            myDataRepeater.DataSource = myRows
            myDataRepeater.DataBind()
        End If
    Catch ex As Exception

    End Try

Which does return the two rows I am expecting but then when it binds to the datarepeater I get the following error: DataBinding: 'System.Data.DataRow' does not contain a property with the name 'PropertyName'.

Corrected code, filter not being applied:

Public Sub PageLoad(ByVal Sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    If Not Page.IsPostBack Then
        ReadCsv()
        lblSearch.Text = "Lettings Search"
    End If
End Sub

Private Sub ReadCsv()
    Dim dirInfo As New DirectoryInfo(Server.MapPath("~/ftp/"))
    Dim fileLocation As String = dirInfo.ToString & "data.txt"

    Try
        Dim csv As New CSVFile(fileLocation)
        Dim ds As DataSet = csv.ToDataSet("MyTable")
        If Not ds Is Nothing Then
            myDataRepeater.DataSource = ds
            myDataRepeater.DataMember = ds.Tables.Item(0).TableName
            myDataRepeater.DataBind()
        End If
        ds = Nothing
        csv = Nothing
    Catch ex As Exception
        MsgBox(ex.Message)
    End Try
End Sub

Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles btnSubmit.Click
    Dim rowCount As Integer

    rowCount = QueryCsv()
    pnlSearch.Visible = False
    lblResults.Visible = True
    lblSearch.Text = "Search Results"
    lblResults.Text = "Your search returned " & rowCount.ToString & " results"

    If rowCount > 0 Then
        myDataRepeater.Visible = True
        pnlResults.Visible = True
        btnBack.Visible = True
    End If

End Sub

Protected Function QueryCsv() As Integer

    Dim dirInfo As New DirectoryInfo(Server.MapPath("~/ftp/"))
    Dim fileLocation As String = dirInfo.ToString & "data.txt"
    Dim numberofRows As Integer

    Try
        Dim csv As New CSVFile(fileLocation)
        Dim ds As DataSet = csv.ToDataSet("MyTable")
        If Not ds Is Nothing Then


            Dim strExpr As String = "PropertyID = 'P1005'"
            Dim strSort As String = "PropertyID DESC"

            Try

                ds.Tables.Item(0).DefaultView.RowFilter = strExpr
                ds.Tables.Item(0).DefaultView.Sort = strSort
                myDataRepeater.DataSource = ds.Tables.Item(0).DefaultView

            Catch ex As Exception
            End Try

        End If
    numberofRows = ds.Tables("MyTable").Rows.Count
    Catch ex As Exception

    End Try
    Return numberofRows
End Function
+1  A: 

Why not use the built-in TextFileParser to get the data into a DataTable? Something like Paul Clement's answer in this thread

MarkJ
Thanks. This builds the table but then when I try to bind to the datarepeater I get the followingUnable to cast object of type 'System.Data.DataRowView' to type 'System.String[]'.On line Dim dataItem As String() = DirectCast(e.Item.DataItem, String())
Helen
A: 
Josaph
Great thanks for such a detailed response. It'll take me a while to code this up but I'll let you know how I get one.
Helen
No problem. You can also call the function with just a delimited line using CSVFile(mycsvlinestring, ",") The new(filename) constructor just makes it easy to load it by just passing the filename.
Josaph
Sorry, dumb question, please expain:Public Sub LoadFile(ByVal Filename As String) Dim inFile As StreamReader = File.OpenText(Filename) Do While inFile.Peek > 0 FromString(inFile.ReadLine, ",") _Items.Add(_Norwegian) _Norwegian = Nothing Loop inFile.Close() End SubShould _Norwegian be replaced with each one of 47 column names?
Helen
Gah! I copied this from one of my programs. Replace _Norwegian with _CSVFile. I'll edit the code above.
Josaph
Fixed the code. Sorry about that.
Josaph
Ah! ok thanks. So it's all working, the CSVFile is created. What is the best way to bind this my data repeater and then filter the results?to
Helen
The best way is to build a ToDataRepeater on the Structure and use reflection to dynamically build it. Let me alter the code. Give me a minute.
Josaph
Okay, check it out now. I changed CSVFile.vb class, CSVFileFields.vb and updated the Form1 example. Now, I just used labels in the dynamic creation of the datarepeater. You can do whatever you want at that point once you have the dataset. drMain is the datarepeater control on the form.
Josaph
FYI: TextFieldParser Class can be used instead of splitting. It's more effective for such task: http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser.aspx
Sphynx
Well they are similar, but mine handles any row of data regardless if the row has all of the fields.For example:"MyName,Address1,Address2,City,State,Zip,Phone""MyName""MyName,Address1"All of those will work without erroring out. There are times, especially with x12 standards, that you could get one line with some of the fields, and another with only the first few.I would say for input sanitization TextFieldParser would be the way to go. However, if you are dealing with a dynamic line that may have different field lengths, the above method would be preferred.
Josaph
For example, look at EDI 835 and EDI 837 standards. :-D
Josaph
This is great thanks, I should have pointed out that this is for a web application and not win forms therefore Microsoft.VisualBasic.PowerPacks Namespace is not valid.
Helen
Just got it all up and running. Only problem is that some columns contains daa with commas. How can I change the code to ignore commas when they exist within the text?
Helen
As long as you have a string qualifier, " for example, you can use this function here: http://www.nomorepasting.com/getpaste.php?pasteid=33449. Then instead of calling Line.Split(","), call Split(Line, ",", Chr(34), True)
Josaph
Superb. All is working but when I try to add a filter to the results I get an error (see edited code)
Helen
You need to bind using this method:Try... Dim myRows() As DataRow 'myRows = Dt.Select(strExpr, strSort) myRows = ds.Tables("MyTable").Select(strExpr, strSort) myDataRepeater.DataSource = ds myDataRepeater.DataMember = ds.Tables.Item(0).TableName End If Catch ex As Exception End Try
Josaph
Thank, but this does not use myRows and retrieves all records. I tried changing myDataRepeater.DataSource to myRows but get the same error.
Helen
ds.Tables.Item(0).DefaultView.RowFilter = strExprds.Tables.Item(0).DefaultView.Sort = strSortmyDataRepeater.DataSource = ds.Tables.Item(0).DefaultViewREMOVE THIS LINE ----->myDataRepeater.DataBind() <---- REMOVE THIS LINE!
Josaph
I don't want to test your patience with me as you have been such a great help. However, the filter is not being applied. I have updated the full code above. And a final question, how can I ignore the first CSV line if it contains headers?
Helen