Here's the code :
try
{
string strReadDataLine;
strReadDataLine = sr.ReadLine();
while (strReadDataLine != null)
{
string[] strReadDataLineSplited = strReadDataLine.Split(';');
DataRow thisRow = thisDataSet.Tables["Repartition"].NewRow();
DataTable item = thisDataSet.Tables["Repartition"];
for (int i = 0; i < strDataLines.Length; i++)
{
DataColumn thisColomn =
thisDataSet.Tables["Repartition"].Columns[i];
// Here i need to know if the colomn is a string
if (thisColomn.DataType.ToString() == "System.String")
{
thisRow[strDataLines[i]] = strReadDataLineSplited[i];
}
}
thisRow["ID_USAGER"] = 1;
thisDataSet.Tables["Repartition"].Rows.Add(thisRow);
strReadDataLine = sr.ReadLine();
}
//thisDataAdapter.Update(thisDataSet, "Repartition");
}
What I need is to know if a column is a string to assign a data as string to the column. What I get is a argumentException saying "input string was not in correct format. couldn't store <2.111> in MY_FLOAT colomn. Expect type is double."
What I really need is to compare the column type to something to get the type then assign the column to the correct type.
I hope this is clear as my English is not so good.
If I understand correctly I built a functional copy of the code-fragment and fixed it to correctly handle the type conversion. You really only missed two things:
. #1 - You were indexing into the columns by ordinal and using that information to obtain the column type. Then setting the information you indexed the column my name. I corrected this with the introduction of the 'columnName' variable below.
. #2 - To properly convert the string input to the desired column type you only need to use the System.Convert.ChangeType(object, Type) method as shown below.
static void Main()
{
DataSet ds = new DataSet();
DataTable dt = ds.Tables.Add("Repartition");
DataColumn col;
col = dt.Columns.Add("ID_USAGER", typeof(int));
col = dt.Columns.Add("TestString", typeof(string));
col = dt.Columns.Add("TestInt", typeof(int));
col = dt.Columns.Add("TestDouble", typeof(double));
string testData = "TestString;TestInt;TestDouble";
testData += Environment.NewLine + "Test1;1;1.1";
testData += Environment.NewLine + "Test2;2;2.2";
Test(ds, new StringReader(testData));
}
public static void Test(DataSet thisDataSet, StringReader sr)
{
string[] strDataLines = sr.ReadLine().Split(';');
string strReadDataLine;
strReadDataLine = sr.ReadLine();
while (strReadDataLine != null)
{
string[] strReadDataLineSplited = strReadDataLine.Split(';');
DataRow thisRow = thisDataSet.Tables["Repartition"].NewRow();
DataTable item = thisDataSet.Tables["Repartition"];
for (int i = 0; i < strDataLines.Length; i++)
{
string columnName = strDataLines[i];
//#1 Don't use this as Columns[i] may not be Columns[columnName]
//DataColumn thisColomn = thisDataSet.Tables["Repartition"].Columns[i];
DataColumn thisColomn = thisDataSet.Tables["Repartition"].Columns[columnName];
//#2 Assing to the results of the string converted to the correct type:
thisRow[strDataLines[i]] = System.Convert.ChangeType(strReadDataLineSplited[i], thisColomn.DataType);
}
thisRow["ID_USAGER"] = 1;
thisDataSet.Tables["Repartition"].Rows.Add(thisRow);
strReadDataLine = sr.ReadLine();
}
}
Related
Working on a windows form application that reads in data from csv files and adds the data to a Datagridview. I ran into an issue with all of the rows being added to the datable and being displayed on the datagridview. The datagridview displays the datarows from the first two if conditions and OneRow if condition only. It will not add the rows from the twoRow if condition if the datable and datagridview rows are populated with the OneRow if condition rows. But i want the rows from both OneRow and TwoRow to be displyed. Also the rows from TwoRow do populate the datatable and datagridview when I comment(/**/) out the OneRow if condition. But I need both to populate the table. Thanks in advance!
Construct.MainDataTable.Columns.Add("Date", typeof(DateTime));
Construct.MainDataTable.Columns.Add("Time");
Construct.MainDataTable.Columns.Add("Serial");
Construct.MainDataTable.Columns.Add("Type");
Construct.MainDataTable.Columns.Add("level");
Construct.MainDataTable.Columns.Add("price");
Construct.MainDataTable.Columns.Add(" Limit");
Construct.MainDataTable.Columns.Add("last Limit");
Construct.MainDataTable.Columns.Add("Data");
..........................
...............................................
DataRow oneRow = Construct.MainDataTable.NewRow();
DataRow twoRow = Construct.MainDataTable.NewRow();
dataGridView2.AllowUserToAddRows = false;
if (line.Split(',')[2].Equals("Time"))
{
time = line.Split(',')[3];
date = line.Split(',')[1];
}
if (line.Split(',')[2].Equals("Level"))
{
level = line.Split(',')[3];
}
//OneROw(IF condition)
if ((Convert.ToDecimal(line.Split(',')[8])) < (Convert.ToDecimal (line.Split(',')[12])))
{
type = line.Split(',')[1];
serial = line.Split(',')[7];
price = line.Split(',')[3];
Limit = line.Split(',')[8];
lastLimit = line.Split(',')[10];
Data = line.Split(',')[12];
oneRow["Date"] = date;
oneRow["Time"] = time;
oneRow["Serial"] = serial;
oneRow["Type"] = type;
oneRow["level"] = level;
oneRow["price"] = price;
oneRow[" Limit"] = Limit;
oneRow["last Limit"] = lastlimit;
oneRow["Data"] = Data;
Construct.MainDataTable.Rows.Add(oneRow);
}
//TwoROw(IF condition)
if ((line.Contains('"')) && ((line.Contains("NG"))))
{
price = line.Split(',')[3];
type = line.Split(',')[1];
serial = line.Split(',')[7];
Limit = line.Split('"')[7];
var valLimit = Limit.Split(',').Select(a => Convert.ToInt32(a, 16));
var limitJoin = String.Join(",", valLimit);
lastlimit = line.Split('"')[1];
var vallastLimit = lastlimit.Split(',').Select(d => Convert.ToInt32(d, 16));
var lastJoin = String.Join(",", vallastLimit);
Data = line.Split('"')[5];
var valDatas = Data.Split(',').Select(s => Convert.ToInt32(s, 16));
var dataJoin = String.Join(",", valDatas);
twoRow["Date"] = date;
twoRow["Time"] = time;
twoRow["Serial"] = serial;
twoRow["Type"] = type;
twoRow["level"] = level;
twoRow["price"] = price;
twoRow["Limit"] = limitJoin;
twoRow["last Limit"] = lastJoin;
twoRow["Data"] = dataJoin;
Construct.MainDataTable.Rows.Add(twoRow);
}
dataGridView2.DataSource = Construct.MainDataTable;
Can't add a comment because I don't have enough karma so I ask my questions here: So, if I understood your problem you can't add data from one .csv file if it have more then one row? Why are you using 2 different if conditions for row in .csv file?
If you have empty data in row never mind you can still place them to your DataTable column, so you can use loop to add data from .csv to your DataTable. Try some thing like this:
public static DataTable CsvToDataTable(string csv)
{
DataTable dt = new DataTable();
string[] lines = csv.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
Regex onlyDeimiterComma = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");
for (int i = 0; i < lines.Length; i++)
{
DataRow row = dt.NewRow();
string[] cells = onlyDeimiterComma.Split(lines[i]);
for (int j = 0; j < cells.Length; j++)
{
if (i == 0)
{
if (j == 0)
{
dt.Columns.Add(cells[j], typeof(DateTime));
}
else
{
dt.Columns.Add(cells[j]);
}
}
else
{
row[j] = cells[j];
}
}
dt.Rows.Add(row);
}
return dt;
}
Just call this method anywhere in your code and give it string read from your .csv file.
You can try to compile this code here and see how it works on .csv data with different data (empty columns, quoted text, quoted commas)
UPD: If you need to fill DataTable from two different .csv files you can still use code above. Just call it twice for both files and then Merge two DataTable, like this:
DataTable dt = CsvToDataTable(csvFileOne);
DataTable dtTwo = CsvToDataTable(csvFileTwo);
dt.Merge(dtTwo);
this question has been asked but mine has a different approach link 1
l have a datatable with the following data
DataTable dtProduct = new DataTable();
dtProduct.Columns.Add("productId");
dtProduct.Columns.Add("name");
DataRow dataRow = dtProduct.NewRow();
dataRow["productId"] = 1;
dataRow["name"] = "Burger";
dtProduct.Rows.Add(dataRow);
DataRow dataRow2 = dtProduct.NewRow();
dataRow2["productId"] = 2;
dataRow2["name"] = "Chicken";
dtProduct.Rows.Add(dataRow2);
DataTable dtSales = new DataTable();
dtSales.Columns.Add("productId");
dtSales.Columns.Add("saleId");
dtSales.Columns.Add("month");
dtSales.Columns.Add("quantity");
DataRow dataSalesRow = dtSales.NewRow();
dataSalesRow["productId"] = 1;
dataSalesRow["saleId"] = "1";
dataSalesRow["month"] = "Jan";
dataSalesRow["quantity"] = 3433;
dtSales.Rows.Add(dataSalesRow);
DataRow drSales2 = dtSales.NewRow();
drSales2["productId"] = 1;
drSales2["saleId"] = "2";
drSales2["month"] = "Feb";
drSales2["quantity"] = 56;
dtSales.Rows.Add(drSales2);
DataRow drSales3 = dtSales.NewRow();
drSales3["productId"] = 1;
drSales3["saleId"] = "3";
drSales3["month"] = "Mar";
drSales3["quantity"] = 34522;
dtSales.Rows.Add(drSales3);
DataRow drSales4 = dtSales.NewRow();
drSales4["productId"] = 2;
drSales4["saleId"] = "4";
drSales4["month"] = "Feb";
drSales4["quantity"] = 345;
dtSales.Rows.Add(drSales4);
And another sample 2
DataTable dtStudents = new DataTable();
dtStudents.Columns.Add("studentId");
dtStudents.Columns.Add("fullname");
DataRow drStudentrow = dtStudents.NewRow();
drStudentrow["studentId"] = 1;
drStudentrow["fullname"] = "Bil";
dtStudents.Rows.Add(drStudentrow);
DataRow drStudentrow2 = dtStudents.NewRow();
drStudentrow2["studentId"] = 2;
drStudentrow2["fullname"] = "Paul";
dtStudents.Rows.Add(drStudentrow2);
DataTable dtStudentExam = new DataTable();
dtStudentExam.Columns.Add("studentId");
dtStudentExam.Columns.Add("subjectId");
dtStudentExam.Columns.Add("mark");
DataRow dataStudentExamRow = dtStudentExam.NewRow();
dataStudentExamRow["studentId"] = 1;
dataStudentExamRow["subjectId"] = "E123";
dataStudentExamRow["mark"] = 34;
dtStudentExam.Rows.Add(dataStudentExamRow);
DataRow dataStudentExamRow2 = dtStudentExam.NewRow();
dataStudentExamRow2["studentId"] = 2;
dataStudentExamRow2["subjectId"] = "E123";
dataStudentExamRow2["mark"] = 90;
dtStudentExam.Rows.Add(dataStudentExamRow2);
DataRow dataStudentExamRow3 = dtStudentExam.NewRow();
dataStudentExamRow3["studentId"] = 1;
dataStudentExamRow3["subjectId"] = "E155";
dataStudentExamRow3["mark"] = 78;
dtStudentExam.Rows.Add(dataStudentExamRow3);
DataRow dataStudentExamRow4 = dtStudentExam.NewRow();
dataStudentExamRow4["studentId"] = 1;
dataStudentExamRow4["subjectId"] = "E101";
dataStudentExamRow4["mark"] = 12;
dtStudentExam.Rows.Add(dataStudentExamRow4);
DataRow dataStudentExamRow5 = dtStudentExam.NewRow();
dataStudentExamRow5["studentId"] = 1;
dataStudentExamRow5["subjectId"] = "E234";
dataStudentExamRow5["mark"] = 42;
dtStudentExam.Rows.Add(dataStudentExamRow5);
DataTable products(dtProduct ) has a productId which is the key and another data table sales (dtSales) has sales for the product based on month . and has a column productId .
what l want to achieve is merge this two tables to this
Same Applies for students
l have a data table student (dtStudents) but l however l have student exam marks data tables (dtStudentExam) for each subject
and combine to something like this
So my question is can l do this dynamically . l tried the following below
public static System.Data.DataTable MergeRowsToColumns(DataTable rowDataTable, string rowDataTableIdColumnName, string friendlyName, DataTable columData)
{
List<string> columnsToAdd = new List<string>();
if (rowDataTable == null)
{
return null;
}
DataTable finalDataTable = new DataTable();
finalDataTable.Columns.Add(friendlyName.ToLower());
finalDataTable.Columns.Add(rowDataTableIdColumnName.ToLower());
foreach (DataColumn column in columData.Columns)
{
if (column.ColumnName.ToString() == rowDataTableIdColumnName.ToString())
{
continue;
}
else
{
finalDataTable.Columns.Add(column.ColumnName.ToString());
columnsToAdd.Add(column.ColumnName.ToString());
}
}
foreach (DataRow row in rowDataTable.Rows)
{
DataRow newRow = finalDataTable.NewRow();
newRow[rowDataTableIdColumnName] = row[rowDataTableIdColumnName];
newRow[friendlyName] = row[friendlyName];
foreach (DataRow columnRows in columData.Rows)
{
foreach (string column in columnsToAdd)
{
var value = columnRows[column].ToString();
newRow[column] = value;
}
}
finalDataTable.Rows.Add(newRow);
}
return finalDataTable;
}
Algorithm logic
Table 1 holds the key information
Table 2 holds the value data for table
using a column name from table one for id which will be the same on table 2
can l do it generically
in one function like
var dtMergedProducts = HelperDataTable.MergeRowsToColumns(dtProduct, "productId", "name", dtSales);
var dtStudents = HelperDataTable.MergeRowsToColumns(dtStudents, "studentId", "fullname", dtStudentExam);
Please am retrieving the data as is hence can not group by in table 2 and also table two does not have a friendly name that will be displayed.
Most of the data that is loaded is not more than 100 000
this is the link of the helper utility am making git hub
Edit One
DataTable 2 will have column value one for column and the other for value
For example
dtSales
1- month : shown vertically
2- quantity: will be cell value
Sample 2
dtStudentExam
1- subjectId : shown vertically
2- mark : will be the student mark
l got it working this morning
here if the method
public static System.Data.DataTable MergeRowsToColumns(DataTable rowDataTable, string rowDataTableIdColumnName, string friendlyName, DataTable dataAllValue , string dataColumnValue , string dataColumnKey)
{
List<string> columnsToAdd = new List<string>();
if (rowDataTable == null)
{
return null;
}
DataTable finalDataTable = new DataTable();
finalDataTable.Columns.Add(friendlyName.ToLower());
finalDataTable.Columns.Add(rowDataTableIdColumnName.ToLower());
foreach (DataRow row in dataAllValue.Rows)
{
if (row[rowDataTableIdColumnName].ToString() == rowDataTableIdColumnName.ToString())
{
continue;
}
else
{
var isExistColumnValue = columnsToAdd.Where(c => c == row[dataColumnKey].ToString()).FirstOrDefault();
if(isExistColumnValue == null)
{
columnsToAdd.Add(row[dataColumnKey].ToString());
finalDataTable.Columns.Add(row[dataColumnKey].ToString());
}
}
}
foreach (DataRow row in rowDataTable.Rows)
{
DataRow newRow = finalDataTable.NewRow();
newRow[rowDataTableIdColumnName] = row[rowDataTableIdColumnName];
newRow[friendlyName] = row[friendlyName];
foreach (DataRow columnRows in dataAllValue.Rows)
{
if(row[rowDataTableIdColumnName].ToString() != columnRows[rowDataTableIdColumnName].ToString())
{
continue;
}
var columnName = columnRows[dataColumnKey].ToString();
var columnValue = columnRows[dataColumnValue].ToString();
newRow[columnName] = columnValue;
}
finalDataTable.Rows.Add(newRow);
}
return finalDataTable;
}
it looked like l was failing on adding the column names before merging
you can just call like
var dt = HelperDataTable.MergeRowsToColumns(dtProduct, "productId", "name", dtSales , "quantity", "month");
var dt2 = HelperDataTable.MergeRowsToColumns(dtStudents, "studentId", "fullname", dtStudentExam , "mark", "subjectId");
i am currently working on a small Project and i got stuck with a Problem i currently can not manage to solve...
I have multiple ".CSV" Files i want to read, they all have the same Data just with different Values.
Header1;Value1;Info1
Header2;Value2;Info2
Header3;Value3;Info3
While reading the first File i Need to Create the Headers. The Problem is they are not splited in Columns but in rows (as you can see above Header1-Header3).
Then it Needs to read the Value 1 - Value 3 (they are listed in the 2nd Column) and on top of that i Need to create another Header -> Header4 with the data of "Info2" which is always placed in Column 3 and Row 2 (the other values of Column 3 i can ignore).
So the Outcome after the first File should look like this:
Header1;Header2;Header3;Header4;
Value1;Value2;Value3;Info2;
And after multiple files it sohuld be like this:
Header1;Header2;Header3;Header4;
Value1;Value2;Value3;Value4;
Value1b;Value2b;Value3b;Value4b;
Value1c;Value2c;Value3c;Value4c;
I tried it with OleDB but i get the Error "missing ISAM" which i cant mange to fix. The Code i Used is the following:
public DataTable ReadCsv(string fileName)
{
DataTable dt = new DataTable("Data");
/* using (OleDbConnection cn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"" +
Path.GetDirectoryName(fileName) + "\";Extendet Properties ='text;HDR=yes;FMT=Delimited(,)';"))
*/
using (OleDbConnection cn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
Path.GetDirectoryName(fileName) + ";Extendet Properties ='text;HDR=yes;FMT=Delimited(,)';"))
{
using(OleDbCommand cmd = new OleDbCommand(string.Format("select *from [{0}]", new FileInfo(fileName).Name,cn)))
{
cn.Open();
using(OleDbDataAdapter adapter = new OleDbDataAdapter(cmd))
{
adapter.Fill(dt);
}
}
}
return dt;
}
Another attempt i did was using StreamReader. But the Headers are in the wrong place and i dont know how to Change this + do this for every file. the Code i tried is the following:
public static DataTable ReadCsvFilee(string path)
{
DataTable oDataTable = new DataTable();
var fileNames = Directory.GetFiles(path);
foreach (var fileName in fileNames)
{
//initialising a StreamReader type variable and will pass the file location
StreamReader oStreamReader = new StreamReader(fileName);
// CONTROLS WHETHER WE SKIP A ROW OR NOT
int RowCount = 0;
// CONTROLS WHETHER WE CREATE COLUMNS OR NOT
bool hasColumns = false;
string[] ColumnNames = null;
string[] oStreamDataValues = null;
//using while loop read the stream data till end
while (!oStreamReader.EndOfStream)
{
String oStreamRowData = oStreamReader.ReadLine().Trim();
if (oStreamRowData.Length > 0)
{
oStreamDataValues = oStreamRowData.Split(';');
//Bcoz the first row contains column names, we will poluate
//the column name by
//reading the first row and RowCount-0 will be true only once
// CHANGE TO CHECK FOR COLUMNS CREATED
if (!hasColumns)
{
ColumnNames = oStreamRowData.Split(';');
//using foreach looping through all the column names
foreach (string csvcolumn in ColumnNames)
{
DataColumn oDataColumn = new DataColumn(csvcolumn.ToUpper(), typeof(string));
//setting the default value of empty.string to newly created column
oDataColumn.DefaultValue = string.Empty;
//adding the newly created column to the table
oDataTable.Columns.Add(oDataColumn);
}
// SET COLUMNS CREATED
hasColumns = true;
// SET RowCount TO 0 SO WE KNOW TO SKIP COLUMNS LINE
RowCount = 0;
}
else
{
// IF RowCount IS 0 THEN SKIP COLUMN LINE
if (RowCount++ == 0) continue;
//creates a new DataRow with the same schema as of the oDataTable
DataRow oDataRow = oDataTable.NewRow();
//using foreach looping through all the column names
for (int i = 0; i < ColumnNames.Length; i++)
{
oDataRow[ColumnNames[i]] = oStreamDataValues[i] == null ? string.Empty : oStreamDataValues[i].ToString();
}
//adding the newly created row with data to the oDataTable
oDataTable.Rows.Add(oDataRow);
}
}
}
//close the oStreamReader object
oStreamReader.Close();
//release all the resources used by the oStreamReader object
oStreamReader.Dispose();
}
return oDataTable;
}
I am thankful for everyone who is willing to help. And Thanks for reading this far!
Sincerely yours
If I understood you right, there is a strict parsing there like this:
string OpenAndParse(string filename, bool firstFile=false)
{
var lines = File.ReadAllLines(filename);
var parsed = lines.Select(l => l.Split(';')).ToArray();
var header = $"{parsed[0][0]};{parsed[1][0]};{parsed[2][0]};{parsed[1][0]}\n";
var data = $"{parsed[0][1]};{parsed[1][1]};{parsed[2][1]};{parsed[1][2]}\n";
return firstFile
? $"{header}{data}"
: $"{data}";
}
Where it would return - if first file:
Header1;Header2;Header3;Header2
Value1;Value2;Value3;Value4
if not first file:
Value1;Value2;Value3;Value4
If I am correct, rest is about running this against a list file of files and joining the results in an output file.
EDIT: Against a directory:
void ProcessFiles(string folderName, string outputFileName)
{
bool firstFile = true;
foreach (var f in Directory.GetFiles(folderName))
{
File.AppendAllText(outputFileName, OpenAndParse(f, firstFile));
firstFile = false;
}
}
Note: I missed you want a DataTable and not an output file. Then you could simply create a list and put the results into that list making the list the datasource for your datatable (then why would you use semicolons in there? Probably all you need is to simply attach the array values to a list).
(Adding as another answer just to make it uncluttered)
void ProcessMyFiles(string folderName)
{
List<MyData> d = new List<MyData>();
var files = Directory.GetFiles(folderName);
foreach (var file in files)
{
OpenAndParse(file, d);
}
string[] headers = GetHeaders(files[0]);
DataGridView dgv = new DataGridView {Dock=DockStyle.Fill};
dgv.DataSource = d;
dgv.ColumnAdded += (sender, e) => {e.Column.HeaderText = headers[e.Column.Index];};
Form f = new Form();
f.Controls.Add(dgv);
f.Show();
}
string[] GetHeaders(string filename)
{
var lines = File.ReadAllLines(filename);
var parsed = lines.Select(l => l.Split(';')).ToArray();
return new string[] { parsed[0][0], parsed[1][0], parsed[2][0], parsed[1][0] };
}
void OpenAndParse(string filename, List<MyData> d)
{
var lines = File.ReadAllLines(filename);
var parsed = lines.Select(l => l.Split(';')).ToArray();
var data = new MyData
{
Col1 = parsed[0][1],
Col2 = parsed[1][1],
Col3 = parsed[2][1],
Col4 = parsed[1][2]
};
d.Add(data);
}
public class MyData
{
public string Col1 { get; set; }
public string Col2 { get; set; }
public string Col3 { get; set; }
public string Col4 { get; set; }
}
I don't know if this is the best way to do this. But what i would have done in your case, is to rewrite the CSV's the conventionnal way while reading all the files, then create a stream containing the new CSV created.
It would look like something like this :
var csv = new StringBuilder();
csv.AppendLine("Header1;Header2;Header3;Header4");
foreach (var item in file)
{
var newLine = string.Format("{0},{1},{2},{3}", item.value1, item.value2, item.value3, item.value4);
csv.AppendLine(newLine);
}
//Create Stream
MemoryStream stream = new MemoryStream();
StreamReader reader = new StreamReader(stream);
//Fill your data table here with your values
Hope this will help.
I'm using this code to parse the values and store them in List. The first row has names which are getting stored fine. But when storing values, only the second row is bring saved. I'm not sure what edit I need to make so that it parses all other rows as well.
Please see image and code below.
List<string> names = new List<string>(); // List to store Key names
List<string> values = new List<string>(); // List to store key values
using (StreamReader stream = new StreamReader(filePath))
{
names = stream.ReadLine().Split(',').ToList(); // Seperate key names and store them in a List
values = stream.ReadLine().Split(',').ToList(); // Seperate key values and store them in a list
}
See if something like this works better:
// List to store Key names
List<string> names = new List<string>();
// List to store key values
List<List<string>> values = new List<string>();
using (StreamReader stream = new StreamReader(filePath))
{
if(!stream.EndOfStream)
{
// Seperate key names and store them in a List
names = stream.ReadLine().Split(',').ToList();
}
while(!stream.EndOfStream)
{
// Seperate key values and store them in a list
values.Add(stream.ReadLine().Split(',').ToList());
}
}
This changes your values list to be a list of a list of strings so that each row will a list of string
While this probably isn't the best way to parse a .csv, if your data is consistent and the file format is strongly consistent you can probably get away with doing it like this. As soon as you try this with odd values, quoted strings, strings with commas, etc., you'll need a different approach.
i have written the code for grid view make changes it to a list.I think it will help
protected void Button1_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
string s = FileUpload1.FileName.Trim();
if (s.EndsWith(".csv"))
{
FileUpload1.PostedFile.SaveAs(Server.MapPath("~/data/" + s));
string[] readText = File.ReadAllLines(Server.MapPath("~/data/" + s));
DataSet ds = new DataSet();
DataTable dt = new DataTable();
// Array.Sort(readText);
for (int i = 0; i < readText.Length; i++)
{
if (i == 0)
{
string str = readText[0];
string[] header = str.Split(',');
dt.TableName = "sal";
foreach (string k in header)
{
dt.Columns.Add(k);
}
}
else
{
DataRow dr = dt.NewRow();
string str1 = readText[i];
if (readText[i] == ",,,,")
{
break;
}
string[] rows = str1.Split(',');
if (dt.Columns.Count == rows.Length)
{
for (int z = 0; z < rows.Length; z++)
{
if (rows[z] == "")
{
rows[z] = null;
}
dr[z] = rows[z];
}
dt.Rows.Add(dr);
}
else
{
Label1.Text = "please select valid format";
}
}
}
//Iterate through the columns of the datatable to set the data bound field dynamically.
ds.Merge(dt);
Session["tasktable"] = dt;
foreach (DataColumn col in dt.Columns)
{
BoundField bf = new BoundField();
bf.DataField = col.ToString();
bf.HeaderText = col.ColumnName;
if (col.ToString() == "Task")
{
bf.SortExpression = col.ToString();
}
GridView1.Columns.Add(bf);
}
GridView1.DataSource = ds;
GridView1.DataBind();
}
else
{
Label1.Text = "please select a only csv format";
}
}
else
{
Label1.Text = "please select a file";
}
}
This is a take on some experimental code that #Tim Schmelter pointed me in the correct direction towards earlier this afternoon. The majority of it is almost exactly the same as what worked earler, but it is throwing a invalidCastException on the last line or second last line, depending whichever i try. I cannot see why this is.
Boolean test = false;
string filePathStudent = System.IO.Path.GetFullPath("StudentInfo.txt");
DataTable studentDataTable = new DataTable();
studentDataTable.Columns.Add("Id", typeof(int));
studentDataTable.Columns.Add("StudentID");
studentDataTable.Columns.Add("FirstName");
studentDataTable.Columns.Add("LastName");
studentDataTable.Columns.Add("StreetAdd");
studentDataTable.Columns.Add("City");
studentDataTable.Columns.Add("State");
studentDataTable.Columns.Add("Zip");
studentDataTable.Columns.Add("Choice1");
studentDataTable.Columns.Add("CreditHrs1");
studentDataTable.Columns.Add("Choice2");
studentDataTable.Columns.Add("CreditHrs2");
studentDataTable.Columns.Add("Choice3");
studentDataTable.Columns.Add("CreditHrs3");
studentDataTable.Columns.Add("Choice4");
studentDataTable.Columns.Add("CreditHrs4");
studentDataTable.Columns.Add("Choice5");
studentDataTable.Columns.Add("CreditHrs5");
studentDataTable.Columns.Add("Choice6");
studentDataTable.Columns.Add("CreditHrs6");
foreach (string line in File.ReadLines(filePathStudent))
{
DataRow row = studentDataTable.Rows.Add();
string[] fields = line.Split(new[] { (char)9 });
int id;
if (fields.Length == 19 && int.TryParse(fields[0], out id))
{
row.SetField("Id", id);
row.SetField("StudentID", fields[1]);
row.SetField("FirstName", fields[2]);
row.SetField("LastName", fields[3]);
row.SetField("StreetAdd", fields[4]);
row.SetField("City", fields[5]);
row.SetField("State", fields[6]);
row.SetField("Zip", fields[7]);
row.SetField("Choice1", fields[8]);
row.SetField("CreditHrs1", fields[9]);
row.SetField("Choice2", fields[10]);
row.SetField("CreditHrs2", fields[11]);
row.SetField("Choice3", fields[12]);
row.SetField("CreditHrs3", fields[13]);
row.SetField("Choice4", fields[14]);
row.SetField("CreditHrs4", fields[15]);
row.SetField("Choice5", fields[16]);
row.SetField("CreditHrs5", fields[17]);
row.SetField("Choice6", fields[18]);
row.SetField("CreditHrs6", fields[19]);
}
}
using (StreamReader reader = new StreamReader(filePathStudent))
{
String line1 = reader.ReadLine();
if (line1 == null)
maxIDStdTable = 0;
else
test = true;
reader.Dispose();
reader.Close();
}
if(test)
int maxIDStdTable = studentDataTable.AsEnumerable().Max(r => r.Field<int>("Id"));
//int maxIDStdTable = (int)studentDataTable.Compute("Max(Id)", "");
You have made two mistakes :
1) You have create new DataRow with DataTable.NewRow()
2) Sfter setting DataRow you have to add it to the DataTable with DataTable.Rows.Add(youDataRow).
Update your code as and try:
foreach (string line in File.ReadLines(filePathStudent))
{
DataRow row = studentDataTable.NewRow();
string[] fields = line.Split(new[] { (char)9 });
int id;
if (fields.Length == 19 && int.TryParse(fields[0], out id))
{
row["Id"]= id;
row["StudentID"]= fields[1];
row["FirstName"]= fields[2];
row[LastName"]= fields[3];
row["StreetAdd"]= fields[4];
row["City"]=fields[5];
row["State"]= fields[6];
row["Zip"]=fields[7];
row["Choice1"]= fields[8];
row["CreditHrs1"]= fields[9];
row["Choice2"]= fields[10];
row["CreditHrs2"]= fields[11];
row[("Choice3"]= fields[12];
row["CreditHrs3"]=, fields[13];
row["Choice4"]= fields[14];
row["CreditHrs4"]= fields[15];
row["Choice5"]= fields[16];
row["CreditHrs5"]= fields[17];
row["Choice6"]= fields[18];
row["CreditHrs6"] =fields[19];
}
studentDataTable.Rows.Add(row);
}
It might not be the best solution, but it works.
string filePathStudent = System.IO.Path.GetFullPath("StudentInfo.txt");
DataTable studentDataTable = new DataTable();
studentDataTable.Columns.Add("Id", typeof(Int32));
studentDataTable.Columns.Add("StudentID");
studentDataTable.Columns.Add("FirstName");
studentDataTable.Columns.Add("LastName");
studentDataTable.Columns.Add("StreetAdd");
studentDataTable.Columns.Add("City");
studentDataTable.Columns.Add("State");
studentDataTable.Columns.Add("Zip");
studentDataTable.Columns.Add("Choice1");
studentDataTable.Columns.Add("CreditHrs1");
studentDataTable.Columns.Add("Choice2");
studentDataTable.Columns.Add("CreditHrs2");
studentDataTable.Columns.Add("Choice3");
studentDataTable.Columns.Add("CreditHrs3");
studentDataTable.Columns.Add("Choice4");
studentDataTable.Columns.Add("CreditHrs4");
studentDataTable.Columns.Add("Choice5");
studentDataTable.Columns.Add("CreditHrs5");
studentDataTable.Columns.Add("Choice6");
studentDataTable.Columns.Add("CreditHrs6");
// Read in a file line-by-line, and store it
var txtFileLine = File.ReadAllLines(filePathStudent).ToList();
//Reads line splits data to colums at tab (ASCII value 9)
txtFileLine.ForEach(line => studentDataTable.Rows.Add(line.Split((char)9)));
List<int> rowsForColumn1 = studentDataTable.AsEnumerable().Select(x => x.Field<int>(0)).ToList();
//Tests for empty Datatable
foreach (DataRow row in studentDataTable.Rows)
{
if (row.IsNull("Id"))
break;
else
//get max value from "Id" row.
maxIDStdTable = rowsForColumn1.Max();
}
}