I have a DataTable which I save into a CSV file.
If I now read that CSV file and fill the value of it into a new DataTable the first column has a questionmark before it. Like '?Strasse'.
I guess there is a encoding issue, but I don't know how to fix it.
Code that generates CSV:
private static void SaveProgressToCSV(List<DataTable> dts)
{
int count = 0;
_pathToCSVs = new List<string>();
foreach (DataTable dt in dts)
{
count++;
StringBuilder sb = new StringBuilder();
IEnumerable<string> columnNames = dt.Columns.Cast<DataColumn>().
Select(column => column.ColumnName);
sb.AppendLine(string.Join(",", columnNames));
foreach (DataRow row in dt.Rows)
{
IEnumerable<string> fields = row.ItemArray.Select(field =>
string.Concat("\"", field.ToString().Replace("\"", "\"\""), "\""));
sb.AppendLine(string.Join(",", fields));
}
File.WriteAllText(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + #"\save"+ count + ".csv", sb.ToString(), Encoding.UTF8);
_pathToCSVs.Add(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + #"\save" + count + ".csv");
}
}
Code that reads CSV:
private static void ReadCSVIntoDataTable()
{
DataTable = new List<System.Data.DataTable>();
foreach (String pathToSave in _pathToSave)
{
DataTable dt = new System.Data.DataTable();
string pathOnly = Path.GetDirectoryName(pathToSave);
string fileName = Path.GetFileName(pathToSave);
string sql = #"SELECT * FROM [" + fileName + "]";
using (OleDbConnection connection = new OleDbConnection(
#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + pathOnly +
";Extended Properties=\"Text;HDR=Yes;CharacterSet=65001;\""))
using (OleDbCommand command = new OleDbCommand(sql, connection))
using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
{
adapter.Fill(dt);
}
DataTable.Add(dt);
}
}
Like #juharr mentioned in the comments, I tried a CSV parser library.
The one I choose was the GenericParser.
Here the code including the GenericParser that fixed my encoding issue:
private static void ReadCSVIntoDataTable()
{
foreach (String pathToSave in _pathToSave)
{
var adapter = new GenericParsing.GenericParserAdapter(pathToSave, Encoding.UTF8);
adapter.FirstRowHasHeader = true;
DataTable dt = adapter.GetDataTable();
DataTableToExpose.Add(dt);
}
}
Thanks for the help #everyone.
Related
I read excel but dataGridView show data than lines excel file, So I can't write datagridview.Rowcount(). I use the below given code to read the excel file.
Code:
filePath = txtExcelFile.Text;
string[] fileSpit = filePath.Split('.');
if (filePath.Length > 1 && fileSpit[1] == "xls")
{
connString = "Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties='Excel 8.0;HDR=No'";
}
else
{
connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties='Excel 12.0;HDR=No'";
}
OleDbCommand cmd = new OleDbCommand(#"Select * from [" +comboBox1.SelectedValue.ToString() + "]", ole);
OleDbDataAdapter oledata = new OleDbDataAdapter();
oledata.SelectCommand = cmd;
DataSet ds = new DataSet();
oledata.Fill(ds);
dataGridView1.DataSource = ds.Tables[0].DefaultView;
Either strip out the blank lines from the data table before assigning it to the grid:
private DataTable StripEmptyRows(DataTable dt)
{
List<int> rowIndexesToBeDeleted = new List<int>();
int indexCount = 0;
foreach(var row in dt.Rows)
{
var r = (DataRow)row;
int emptyCount = 0;
int itemArrayCount = r.ItemArray.Length;
foreach(var i in r.ItemArray) if(string.IsNullOrWhiteSpace (i.ToString())) emptyCount++;
if(emptyCount == itemArrayCount) rowIndexesToBeDeleted.Add(indexCount);
indexCount++;
}
int count = 0;
foreach(var i in rowIndexesToBeDeleted)
{
dt.Rows.RemoveAt(i-count);
count++;
}
return dt;
}
Or do your own row count ignoring blank rows.
I'm exporting data from SQLite into .csv but I got problem on rows why the result is always appear in the 1st row? did I miss something??
RESULT:
My Code:
private void DataExport()
{
SaveFileDialog saveFileDialog = new SaveFileDialog
{
Title = "Choose file to save to",
FileName = ".csv",
Filter = "CSV (*.csv)|*.csv",
FilterIndex = 0,
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
};
if (saveFileDialog.ShowDialog() == true)
{
SQLiteCommand cmd = new SQLiteCommand();
String sSQL;
sSQL = "select * from Tile1";
cmd.CommandText = sSQL;
clsCon.con.Open();
cmd.Connection = clsCon.con;
SQLiteDataReader dr2;
dr2 = cmd.ExecuteReader();
dr2.Read();
DataSet _dataSet = new DataSet();
DataTable _dataTable = new DataTable();
for (var i = 0; i < dr2.FieldCount; i++)
{
_dataTable.Columns.Add("" + dr2.GetName(i) + "", typeof(string));
_dataTable.Rows.Add("" + dr2.GetValue(i) + "");
}
var rows = _dataTable.Rows;
StringBuilder sb = new StringBuilder();
IEnumerable<string> columnNames = _dataTable.Columns.Cast<DataColumn>().Select(column => column.ColumnName);
sb.AppendLine(string.Join(",", columnNames));
foreach (DataRow row in rows)
{
IEnumerable<string> fields = row.ItemArray.Select(field => field.ToString());
sb.AppendLine(string.Join(",", fields));
}
File.WriteAllText(saveFileDialog.FileName, sb.ToString());
clsCon.con.Close();
}
}
it looks the DataTable object has not been filled correctly, check the part here:
for (var i = 0; i < dr2.FieldCount; i++)
{
_dataTable.Columns.Add("" + dr2.GetName(i) + "", typeof(string));
_dataTable.Rows.Add("" + dr2.GetValue(i) + "");
}
I guess you tried to set up columns of the data table here, but you can't append rows in the same time, you actually add each column values of the first row into different rows. The table you generated would be like this:
col1 col2 col3 col4
row1 val(1,1)
row2 val(1,2)
row3 val(1,3)
row4 val(1,4)
val(x,y) means value at column y and row x in database.
#Darin Dimitrov 's solution works very well for your issue.
Try simplifying your code a bit, I mean those DataTables and DataSets are driving me nuts:
private void DataExport()
{
SaveFileDialog saveFileDialog = new SaveFileDialog
{
Title = "Choose file to save to",
FileName = ".csv",
Filter = "CSV (*.csv)|*.csv",
FilterIndex = 0,
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
};
if (!saveFileDialog.ShowDialog())
{
return;
}
using (var conn = new SQLiteConnection(ConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT * FROM Tile1";
using (var reader = cmd.ExecuteReader())
using (var writer = new StreamWriter(saveFileDialog.FileName))
{
var columnNames = Enumerable
.Range(0, reader.FieldCount)
.Select(reader.GetName);
string header = string.Join(", ", columnNames);
writer.WriteLine(header);
while (reader.Read())
{
var values = Enumerable
.Range(0, reader.FieldCount)
.Select(reader.GetValue);
string valuesRow = string.Join(", ", values);
writer.WriteLine(valuesRow);
}
}
}
}
The problem is that the first column is empty and it can not be read.
To read the file, I wrote the following code:
MyConnection = new OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "'" + filename + "'" + ";Extended Properties=\"Excel 8.0;IMEX=1;HDR=NO;TypeGuessRows=0\"");
DtSet = new DataSet();
MyConnection.Open();
var dt = MyConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
MyCommand = new OleDbDataAdapter("select * from [$first]", MyConnection);
MyCommand.Fill(DtSet); // filldata
dataExcel.AddRange(fillData(DtSet.Tables["Table"]).Select(info => info.ToList()));
}
List<List<string>> fillData(DataTable DtSet) //reader
{
List<List<string>> data = new List<List<string>>();
foreach (DataRow item in DtSet.Rows)
{
if (item == null) continue;
List<string> gettedData = new List<string>();
int i = 0;
foreach (var columnitem in item.ItemArray)
{
if (i == 0 && columnitem.ToString() == "") ;
else gettedData.Add(columnitem.ToString()); //add data
i++;
}
data.Add(gettedData);
}
return data;
}
This code works but the first column, he does not see. Thank you!
Example for file below:
I want to capture the "Customers" (highlighted) as a string.
How do I achieve this in ASP.NET/C#?
Thank you.
You may use OleDbConnection.GetOleDbSchemaTable method.
connection.Open();
DataTable schemaTable = connection.GetOleDbSchemaTable(
OleDbSchemaGuid.Tables,
new object[] { null, null, null, "TABLE" });
foreach (DataRow row in schemaTable.Rows )
{
Console.WriteLine(row["TABLE_NAME"]);
}
public static List<string> GetSheetNames(string PathToExcelFile)
{
List<string> SheetNameList = new List<string>();
System.Data.DataTable SchemaTable;
string OleConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + PathToExcelFile + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1\"";
using (System.Data.OleDb.OleDbConnection OleConnection = new System.Data.OleDb.OleDbConnection(OleConnectionString))
{
OleConnection.Open();
SchemaTable = OleConnection.GetSchema("Tables");
OleConnection.Close();
}
foreach (System.Data.DataRow SchemaRow in SchemaTable.Rows)
{
SheetNameList.Add(SchemaRow["TABLE_NAME"].ToString().TrimEnd('$'));
}
return SheetNameList;
}
What i need id to take the first column of an excel file and put that column in a string variable but numbers that will be taken from excel to be separated with blank space.
For Example:
Excel file:
1
3
4
56
76
7
876
23
43
(in column)
and string in C#
string number = "1 3 4 56 76 7 876 23 43"
Any code will help me
I have made the connection with excel file and i have created the dataset/datatable
but now i can not take those numbers as the sample above ?
If you have the data in a datset...you can do something like this....
////TRY THIS!!!
DataSet dsExcelContent = new DataSet();
//Fill from db
//
StringBuilder builder = new StringBuilder();
foreach (DataRow row in dsExcelContent.Tables[0].Rows)
{
builder.Append(row[0].ToString());
builder.Append(" ");
}
Console.WriteLine(builder.ToString());
.....More exact to your code....
OleDbConnection objConn = new OleDbConnection(sConnectionString);
objConn.Open();
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [sheet1$]", objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
DataSet dsExcelContent = new DataSet();
DataTable dsExcelContent1 = new DataTable();
objAdapter1.Fill(dsExcelContent);
dataGridView1.DataSource = dsExcelContent1;
objConn.Close();
int test = dsExcelContent.Tables[0].Rows.Count;
StringBuilder builder = new StringBuilder();
foreach (DataRow row in dsExcelContent.Tables[0].Rows)
{
builder.Append(row[0].ToString());
builder.Append(" ");
}
//s has the data you want.....
string s = builder.ToString();
//REST OF YOUR CODE.....
Have a link - Reading Excel Document
Here's what I would do...first open the spreadsheet with this code.
xlApp = New Excel.Application
filePath = "FILENAME"
xlWorkBook = xlApp.Workbooks.Open(filePath)
xlWorkSheet = xlWorkBook.Worksheets(1)
Then read through the column like this
For data As Integer = 0 To 8
Dim obj As Excel.Range = CType(xlWorkSheet.Cells(data, 1), Range)
If obj.Value IsNot Nothing Then
MyArray(data) = obj.Value
Else
Exit Do
End If
Next
Then you should have all your data in MyArray then loop through and create a string with spaces and you should be good. This code is in VB but it should give you a good idea of the commands and structure to use.
private void Form1_Load(object sender, EventArgs e)
{
String sConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=unsorted.xls;Extended Properties=""Excel 12.0;HDR=NO;""";
OleDbConnection objConn = new OleDbConnection(sConnectionString);
objConn.Open();
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [sheet1$]", objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
DataSet dsExcelContent = new DataSet();
DataTable dsExcelContent1 = new DataTable();
objAdapter1.Fill(dsExcelContent);
dataGridView1.DataSource = dsExcelContent1;
objConn.Close();
int test = dsExcelContent.Tables[0].Rows.Count;
foreach(DataRow row in dsExcelContent.Tables[0].Rows)
{
StringBuilder builder = new StringBuilder();
foreach (DataColumn col in dsExcelContent.Tables[0].Columns)
{
builder.Append(row[col].ToString());
builder.Append(" ");
}
string s = builder.ToString();
this.label1.Text = s;
string[] numbers = s.Split(' ');
ArrayList numberList = new ArrayList();
int i;
foreach (String num in numbers)
{
if (Int32.TryParse(num, out i))
{
numberList.Add(i);
}
else
Console.WriteLine("'{0}' is not a number!", num);
}
this.listBox1.DataSource = numberList;
}
}
}
You just want to loop through the rows in the Dataset now:
var numberStr = EmptyStr;
foreach (DataRow dr in MyDataSet.Tables[0].Rows)
{
numberStr = EmptyStr ? numberStr += dr[0].ToString() : numberStr += " " + dr[0].ToString();
}
Updated Solution
private void Form1_Load(object sender, EventArgs e)
{
String s = String.Empty;
String sConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;DataSource=unsorted.xls;Extended Properties=""Excel 12.0;HDR=NO;""";
using (OleDbConnection conn = new OleDbConnection(sConnectionString))
{
conn.Open();
DataTable schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
foreach (DataRow schemaRow in schemaTable.Rows)
{
string sheet = schemaRow["TABLE_NAME"].ToString();
OleDbCommand cmd = new OleDbCommand("SELECT * FROM [" + sheet + "]", conn);
cmd.CommandType = CommandType.Text;
DataTable outputTable = new DataTable(sheet);
output.Tables.Add(outputTable);
new OleDbDataAdapter(cmd).Fill(outputTable);
}
// populate string with value from rows
foreach (DataRow dr in MyDataSet.Tables[0].Rows)
{
s = String.Empty ? s += dr[0].ToString() : s += " " + dr[0].ToString();
}
dataGridView1.DataSource = dsExcelContent1;
objConn.Close();
}
this.label1.Text = s;
string[] numbers = s.Split(' ');
ArrayList numberList = new ArrayList();
int i;
foreach (String num in numbers)
{
if (Int32.TryParse(num, out i))
{
numberList.Add(i);
}
else
{
Console.WriteLine("'{0}' is not a number!", num);
}
}
this.listBox1.DataSource = numberList;
}