2

I have downloaded data that is contained in a List<Row> Rows like this:

class Row
{
    string[] Items { get; set; }
    public Row(string[] Items)
    {
        this.Items = Items;
    }
}

The rows are basically comma delimited entries (.csv)

using (var reader = new StreamReader(spreadSheetStream))          
{
    string header = reader.ReadLine(); //This is the header
    Rows.Add(new Row(header.Split(',')));

    while (!reader.EndOfStream)
    {
        string tickerInfo = reader.ReadLine();  //This is a data entry                                             
        Rows.Add(new Row(tickerInfo.Split(',')));                        
    }
}

I convert the List<Row> into a Datatable like this

DataTable historicalDataTable = ToDataTable<Row>(Rows);

The first element of List<Row> Rows contains the names of the columns, seven of them. Then each element thereafter is an actual data element.

public static DataTable ToDataTable<T>(List<T> items)
{
    DataTable dataTable = new DataTable(typeof(T).Name);

    //Get all the properties
    PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
    foreach (PropertyInfo prop in Props)
    {
        //Setting column names as Property names
        dataTable.Columns.Add(prop.Name);
    }
    foreach (T item in items)
    {
        var values = new object[Props.Length];
        for (int i = 0; i < Props.Length; i++)
        {
            //inserting property values to datatable rows
            values[i] = Props[i].GetValue(item, null);
        }
        dataTable.Rows.Add(values);
    }
    //put a breakpoint here and check datatable
    return dataTable;
}

When I try to write out the contents of the table, I see the right number of rows, but there is nothing in ItemArray

foreach (DataRow dataRow in historicalDataTable.Rows)
{
    Console.WriteLine(dataRow.ToString());
    foreach (var item in dataRow.ItemArray)
    {
        Console.WriteLine(item);
    }
}
Ivan
  • 7,448
  • 14
  • 69
  • 134
  • Your `Row` class has only one property (`Items`). The `ToDataTable` method will add a single column. Is that what you are trying to achieve? – Federico Dipuma May 07 '17 at 21:14
  • Hmmm, no I am trying to add all seven columns. – Ivan May 07 '17 at 21:14
  • Then you either have to change the way you are generating the `DataTable` or use a strongly typed class with a property for each column instead of your current `Row` class. – Federico Dipuma May 07 '17 at 21:16
  • Well, I am not sure what you are saying. The code splits the items on each row, and sticks it in the array of Rows. From there, I am trying to get the ToTable to correctly stick each field in a table. – Ivan May 07 '17 at 21:30
  • What I am saying is that your `Row` class will not work with the current implementation of `ToDataTable` because it has only a single property (which is a `string` array). This will cause your method to create a `DataTable` with just one column containing a `string[]`. If you need to convert a CSV to `DataTable` I strongly advice you to change your approach and follow a different one starting by looking at [answers of this question](https://stackoverflow.com/questions/1050112/how-to-read-a-csv-file-into-a-net-datatable). – Federico Dipuma May 07 '17 at 21:43
  • 1
    Just use [CsvHelper](http://joshclose.github.io/CsvHelper/#reading-trygetfield) Don't start writhing your own csv parser since its not as easy as it seams. – Filip Cordas May 07 '17 at 21:53

1 Answers1

1

Your code is a bit contradictory. You are trying to copy properties as column names, however your csv code actually populates the first row as the column names. You have no distinction between header rows and data rows

You can just read it straight into a datatable with something like :-

(though you may want to do better error checking)

var dt = new DataTable("Rows");
string data = "a,b,c\r\n1,2,3\r\n4,5,6";
var stream = GenerateStreamFromString(data); // http://stackoverflow.com/questions/1879395/how-to-generate-a-stream-from-a-string

using (var reader = new StreamReader(stream))
{
    reader.ReadLine()?.Split(',').ToList().ForEach(h => dt.Columns.Add(h));
    while (!reader.EndOfStream)
    {
        dt.Rows.Add(reader.ReadLine()?.Split(',').ToArray());
    }
}
foreach (DataColumn dataColumn in dt.Columns)
{
    Console.Write($"{dataColumn.ColumnName} ");
}
Console.WriteLine();

foreach (DataRow dataRow in dt.Rows)
{
    Console.Write("Row: ");
    foreach (var item in dataRow.ItemArray)
    {
        Console.Write(item + " ");
    }
    Console.WriteLine();
}
Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156