How to convert csv to datatable in c#, mvc - c#

I'm converting .csv file to datatable like below.
string header = isFirstRowHeader ? "Yes" : "No";
string itinerarycsvfilePath = Path.GetDirectoryName(#"D:\projects\MSC cruise\MSCCruiseProjects\MsccruiseWithLogin\MsccruiseWithLogin\UnzippedFiles\itinff_gbr_eng.csv");
string filename = Path.GetFileName(#"D:\projects\MSC cruise\MSCCruiseProjects\MsccruiseWithLogin\MsccruiseWithLogin\UnzippedFiles\itinff_gbr_eng.csv");
string sql = #"SELECT * FROM [" + filename + "]";
using (OleDbConnection connection = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + itinerarycsvfilePath +
";Extended Properties=\"Text;HDR=" + header + "\""))
using (OleDbCommand command = new OleDbCommand(sql, connection))
using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
{
DataTable dataTable = new DataTable("ItineraryDetails");
dataTable.Locale = CultureInfo.CurrentCulture;
adapter.Fill(dataTable);
return dataTable;
}
then the result when I look with quick watch
Am I doing something wrong.I feel like that because table does not show like columns.
what can I do for that.
hope your help.

See code below
public class CSVReader
{
public DataSet ReadCSVFile(string fullPath, bool headerRow)
{
string path = fullPath.Substring(0, fullPath.LastIndexOf("\\") + 1);
string filename = fullPath.Substring(fullPath.LastIndexOf("\\") + 1);
DataSet ds = new DataSet();
try
{
if (File.Exists(fullPath))
{
string ConStr = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}" + ";Extended Properties=\"Text;HDR={1};FMT=Delimited\\\"", path, headerRow ? "Yes" : "No");
string SQL = string.Format("SELECT * FROM {0}", filename);
OleDbDataAdapter adapter = new OleDbDataAdapter(SQL, ConStr);
adapter.Fill(ds, "TextFile");
ds.Tables[0].TableName = "Table1";
}
foreach (DataColumn col in ds.Tables["Table1"].Columns)
{
col.ColumnName = col.ColumnName.Replace(" ", "_");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return ds;
}
}

Related

C# Method to Load Excel File to DataTable or DateSet

good afternoon,
I am trying to create a method that returns the data of an excel file to call it through a FileDialog for example ... Here is my code:
public static DataSet MtdGetExcel(string prtlocalFile)
{
string sDBstrExcel = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=0\"", prtlocalFile);
OleDbConnection conexaoExcel = new OleDbConnection(sDBstrExcel);
conexaoExcel.Open();
DataTable dt = conexaoExcel.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
DataSet output = new DataSet();
foreach (DataRow row in dt.Rows)
{
string sheet = row["TABLE_NAME"].ToString(); //Obtém o nome da planilha corrente
OleDbCommand cmd = new OleDbCommand("SELECT * FROM [" + sheet + "]", conexaoExcel); //Obtém todas linhas da planilha corrente
cmd.CommandType = CommandType.Text;
DataTable outputTable = new DataTable(sheet); //Copia os dados da planilha para o DataTable
output.Tables.Add(outputTable);
new OleDbDataAdapter(cmd).Fill(outputTable);
}
conexaoExcel.Close();
return output;
}
But when I call the method does not return anything in the DataGridView...
public void testeImportExcel()
{
try
{
OpenFileDialog fdlg = new OpenFileDialog();
fdlg.Title = "Selecione o relatório do Detran";
fdlg.InitialDirectory = #"c:\";
//string endereco = fdlg.FileName;
//txtNomeArquivo.Text = fdlg.FileName;
fdlg.Filter = "Excel File (*.xlsx)|*.xlsx";
//fdlg.Filter = "Excel File (*.csv)|*.csv";
fdlg.FilterIndex = 1;
fdlg.RestoreDirectory = true;
if (fdlg.ShowDialog() == DialogResult.OK)
{
myDtGridView.DataSource = MtdGetExcel(fdlg.FileName);
myDtGridView.AutoGenerateColumns = true;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Result:
Can you help me?
Here is my exact method that I have in production:
public DataTable ReadExcel(string fileName, string TableName)
{
DataTable dt = new DataTable();
OleDbConnection conn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties=\"Excel 8.0\"");
OleDbCommand cmd = new OleDbCommand("SELECT * FROM " + TableName, conn);
try
{
conn.Open();
OleDbDataReader reader = cmd.ExecuteReader();
while (!reader.IsClosed)
{
dt.Load(reader);
}
}
finally
{
conn.Close();
}
return dt;
}
I'm sure just by looking at it you can tell- this method takes in the fileName (or file path) of the Excel you're wanting to read from. Creates the connection string and command. Excel will be read like a database and its worksheets will be read like tables. TableName is the name of the worksheet (table). This method returns a DataTable that can be added to a DataSet if needed.

Updating cells using dataset read from xls file and save to CSV file

can somebody tell me why this update procedure doesn't work? I want to read data to dataset from XLS and it works just fine but UPDATE doesn't work at all. No errors, no changes, like it doesn't exist. The file creates but values are just a copy from original xls.
Xls sheet format is pretty simple, one column: id 1 2 3
string string_conn = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=path\name.xls;Extended Properties='Excel 8.0;HDR=Yes;'";
OleDbConnection conn = new OleDbConnection(string_conn);
conn.Open();
DataTable dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string[] excelSheets = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
i++;
}
comboBox1.DataSource = excelSheets;
string xlsSheet = comboBox1.SelectedItem.ToString();
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [" + xlsSheet + "]", conn);
DataSet dataset = new DataSet();
adapter.Fill(dataset);
adapter.UpdateCommand = new OleDbCommand ("UPDATE " + xlsSheet + " SET id = " + tbox1.Text + " WHERE id = " + tbox2.Text + "", conn);
adapter.UpdateCommand.Parameters.Add("#id", OleDbType.Char, 255).SourceColumn = "id";
adapter.UpdateCommand.Parameters.Add("#Oldid", OleDbType.Char, 255, "id").SourceVersion = DataRowVersion.Original;
adapter.Update(dataset);
dataset.AcceptChanges();
DataTable dtable = new DataTable();
dtable = dataset.Tables[0];
StringBuilder str = new StringBuilder();
foreach (DataRow dr in dtable.Rows)
{
foreach (var field in dr.ItemArray)
{
str.Append(field.ToString());
str.Append(", ");
}
str.Replace(",", str.AppendLine().ToString(), str.Length - 1, 1);
}
MessageBox.Show(str.ToString()); //for test's sake
string pathFile = #"path\filename.csv";
if (!File.Exists(pathFile))
{
File.Create(pathFile).Close();
}
File.AppendAllText(pathFile, str.ToString());
Something is wrong with parameters probably but I tried this way and also no go (I added 2nd column so id stays the same just to find proper row), I get UPDATE command syntax error on execute:
string string_conn = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=path\arkusz.xls;Extended Properties='Excel 8.0;HDR=Yes;'";
OleDbConnection conn= new OleDbConnection(string_conn);
conn.Open();
DataTable dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string[] excelSheets = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
i++;
}
comboBox1.DataSource = excelSheets;
string xlsSheet = comboBox1.SelectedItem.ToString();
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [" + xlsSheet + "]", conn);
DataSet dataset = new DataSet();
adapter.Fill(dataset);
adapter.UpdateCommand = new OleDbCommand("UPDATE " + xlsSheet + " SET nazwa = #nazwa WHERE id = #id", conn);
adapter.UpdateCommand.Parameters.AddWithValue("#id", tbox1.Text).OleDbType = OleDbType.Integer;
adapter.UpdateCommand.Parameters.AddWithValue("#nazwa", tbox2.Text).OleDbType = OleDbType.VarChar;
adapter.UpdateCommand.ExecuteNonQuery();
adapter.Update(dataset);
dataset.AcceptChanges();
DataTable dtable = new DataTable();
dtable = dataset.Tables[0];
StringBuilder str = new StringBuilder();
foreach (DataRow dr in dtable.Rows)
{
foreach (var field in dr.ItemArray)
{
str.Append(field.ToString());
str.Append(", ");
}
str.Replace(",", str.AppendLine().ToString(), str.Length - 1, 1);
}
MessageBox.Show(str.ToString());
string sciezkaPlik = #"path\filename.csv";
if (!File.Exists(sciezkaPlik))
{
File.Create(sciezkaPlik).Close();
}
File.AppendAllText(sciezkaPlik, str.ToString());
I solved the issue. For future reference it works well like this:
string string_conn = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=path\arkusz.xls;Extended Properties='Excel 8.0;HDR=Yes;'";
OleDbConnection conn = new OleDbConnection(string_conn);
conn.Open();
DataTable dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string[] excelSheets = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
i++;
}
comboBox1.DataSource = excelSheets;
string xlsSheet = comboBox1.SelectedItem.ToString();
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [" + xlsSheet + "]", conn);
DataSet dataset = new DataSet();
adapter.Fill(dataset);
OleDbCommand odbc = new OleDbCommand("UPDATE ["+xlsSheet+"] SET nazwa = " + txtNewValue.Text + " WHERE id = " + txtID.Text + "", conn);
adapter.UpdateCommand = odbc;
odbc.Parameters.AddWithValue("nazwa", txtNewValue.Text).OleDbType = OleDbType.VarChar;
odbc.Parameters.AddWithValue("id", txtID.Text).OleDbType = OleDbType.Integer;
odbc.ExecuteNonQuery();
dataset.Clear();
adapter.Fill(dataset);
DataTable dtable = new DataTable();
dtable = dataset.Tables[0];
StringBuilder str = new StringBuilder();
foreach (DataRow dr in dtable.Rows)
{
foreach (var field in dr.ItemArray) /
{
str.Append(field.ToString());
str.Append(", ");
}
str = str.Replace(',', '\n');
}
string filePath= #"path\filename.csv";
if (!File.Exists(filePath))
{
File.Create(filePath).Close();
}
File.WriteAllText(filePath, str.ToString());
EDIT - I think it may be that this line needs to have the parameters put in as a question mark instead of having the actual values passed in, so more like this:
adapter.UpdateCommand = new OleDbCommand ("UPDATE " + xlsSheet + " SET id = ? WHERE id = ?", conn);
Then your next couple of lines are correct, they are clever enough to replace the question marks from the UpdateCommand with the actual values at run time:
adapter.UpdateCommand.Parameters.Add("#id", OleDbType.Char, 255).SourceColumn = "id";
adapter.UpdateCommand.Parameters.Add("#Oldid", OleDbType.Char, 255, "id").SourceVersion = DataRowVersion.Original;
Hare is a very simple method to do an insert into an Excel sheet.
using System;
using System.Drawing;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
System.Data.OleDb.OleDbConnection MyConnection ;
System.Data.OleDb.OleDbCommand myCommand = new System.Data.OleDb.OleDbCommand();
string sql = null;
MyConnection = new System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='c:\\csharp.net-informations.xls';Extended Properties=Excel 8.0;");
MyConnection.Open();
myCommand.Connection = MyConnection;
sql = "Insert into [Sheet1$] (id,name) values('5','e')";
myCommand.CommandText = sql;
myCommand.ExecuteNonQuery();
MyConnection.Close();
}
catch (Exception ex)
{
MessageBox.Show (ex.ToString());
}
}
}
}

reading Excel spreadsheet in C#

I made a program to open Excel file.
There are exist data page and blank page.
Can I add only the pages where the data exists in the combo box?
Can I use ButtonEvent to view only pages that contain data?
string filePath = openFileDialog1.FileName;//파일 경로 가져오기
string filename = openFileDialog1.SafeFileName;//파일 이름만 가져오기
string fileExtension = Path.GetExtension(filePath);
//string connectionString = string.Empty;
string sheetName = string.Empty;
using (OleDbConnection con = new OleDbConnection(ConnectStr()))
{
using (OleDbCommand cmd = new OleDbCommand())
{
using (OleDbDataAdapter oda = new OleDbDataAdapter())
{
DataTable dt = new DataTable();
cmd.CommandText = "SELECT * From [" + sheetName + "]";
cmd.Connection = con;
con.Open();
oda.SelectCommand = cmd;
oda.Fill(dt);
con.Close();
dataGridView1.DataSource = dt;
}
}
}
public string ConnectStr()
{
string filePath = openFileDialog1.FileName;
string filename = openFileDialog1.SafeFileName;//파일 이름만 가져오기
string fileExtension = Path.GetExtension(filePath);
string connectionString = string.Empty;
string sheetName = string.Empty;
switch (fileExtension)
{
case ".xls": //Excel 97-03버전
connectionString = string.Format(Excel03ConString, filePath);
break;
case ".xlsx": //Excel 07이상 버전
connectionString = string.Format(Excel16ConString, filePath);
break;
}
return connectionString;
}
I don't really get what is this. But I beg you need to show only specific sheet from spreadsheet correct me if i'm wrong.
There is a SQL commend that we can query from the specific sheet.
try
{
this.txtImportFilePath.Text = opd.FileName;
OleDbConnection con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;data source=" + this.txtImportFilePath.Text + ";Extended Properties=Excel 8.0;");
StringBuilder stbQuery = new StringBuilder();
stbQuery.Append("Select * From [Sheet1$]");
OleDbDataAdapter adp = new OleDbDataAdapter(stbQuery.ToString(), con);
DataSet dsXLS = new DataSet();
adp.Fill(dsXLS);
DataView dvEmp = new DataView(dsXLS.Tables[0]);
trnxlistDataview.DataSource = dvEmp;
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}

csv reading using OLEDB command

Am trying to read a csv file using oledb command. Following is am using.
This code execute smoothly. But i need to remove first row from csv file and set second row as column header of the datatable. Is it possible?
static DataTable ImportCsvFileToDataTable(string filename, string fullPath)
{
FileInfo file = new FileInfo(fullPath);
using (OleDbConnection con =
new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"" +
file.DirectoryName + "\";Extended Properties='text;HDR=Yes;FMT=Delimited(,)';"))
{
using (OleDbCommand cmd = new OleDbCommand(string.Format
("SELECT * FROM [{0}]", file.Name), con))
{
con.Open();
// Using a DataTable to process the data
using (OleDbDataAdapter adp = new OleDbDataAdapter(cmd))
{
DataTable tbl = new DataTable(filename);
adp.Fill(tbl);
return tbl;
}
}
}
}
I shed much blood trying to develop the perfect method to import CSV's into DataTable. Here's the result. It parses first row as column headers. This method works with Ace OleDB 12, but should with no problem work with Jet OleDB 4 as well.
public static DataTable FromCSV(string FilePath, char Delimiter = ',')
{
DataTable dt = new DataTable();
Dictionary<string, string> props = new Dictionary<string, string>();
if (!File.Exists(FilePath))
return null;
if (FilePath.EndsWith(".csv", StringComparison.OrdinalIgnoreCase))
{
props["Provider"] = "Microsoft.Ace.OLEDB.12.0";
props["Extended Properties"] = "\"Text;FMT=Delimited\"";
props["Data Source"] = Path.GetDirectoryName(FilePath);
}
else
return null;
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, string> prop in props)
{
sb.Append(prop.Key);
sb.Append('=');
sb.Append(prop.Value);
sb.Append(';');
}
string connectionString = sb.ToString();
File.Delete(Path.GetDirectoryName(FilePath) + "/schema.ini");
using (StreamWriter sw = new StreamWriter(Path.GetDirectoryName(FilePath) + "/schema.ini", false))
{
sw.WriteLine("[" + Path.GetFileName(FilePath) + "]");
sw.WriteLine("Format=Delimited(" + Delimiter + ")");
sw.WriteLine("DecimalSymbol=.");
sw.WriteLine("ColNameHeader=True");
sw.WriteLine("MaxScanRows=1");
sw.Close();
sw.Dispose();
}
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM [" + Path.GetFileName(FilePath) + "] WHERE 1=0";
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
using (StreamWriter sw = new StreamWriter(Path.GetDirectoryName(FilePath) + "/schema.ini", true))
{
for (int i = 0; i < dt.Columns.Count; i++)
{
string NewColumnName = dt.Columns[i].ColumnName.Replace(#"""", #"""""");
int ColumnNamePosition = NewColumnName.LastIndexOf("#csv.", StringComparison.OrdinalIgnoreCase);
if (ColumnNamePosition != -1)
NewColumnName = NewColumnName.Substring(ColumnNamePosition + "#csv.".Length);
if (NewColumnName.StartsWith("NoName"))
NewColumnName = "F" + (i + 1).ToString();
sw.WriteLine("col" + (i + 1).ToString() + "=" + NewColumnName + " Text");
}
sw.Close();
sw.Dispose();
}
dt.Columns.Clear();
cmd.CommandText = "SELECT * FROM [" + Path.GetFileName(FilePath) + "]";
da = new OleDbDataAdapter(cmd);
da.Fill(dt);
cmd = null;
conn.Close();
}
File.Delete(Path.GetDirectoryName(FilePath) + "/schema.ini");
return dt;
}
Perhaps something like this:
tbl.Rows[0].Delete();
DataRow r = tbl.Rows[0];
foreach(DataColumn c in tbl.Columns)
{
tbl.Columns[c.ColumnName].ColumnName = r[c.ColumnName].ToString();
}
tbl.Rows[0].Delete();
There is no built-in way to tell OLEDB to use the second row for the headers instead of the first row.
You will have to open the CSV file, remote the first row, and save it again. Fortunately, this is fairly easy to do:
var lines = File.ReadAllLines(oldFileName);
File.WriteAllLines(newFileName, lines.Skip(1));
(Add .ToArray() after Skip(1) if you are using a .NET version < 4.)

Comparing values in Data Table in c#

I have loaded Two Excel files in two datable now i have to check that the Specific value of column one of DataTable1 exist in specific cloumn of DataTable 2 or not. I have only one output in rich Text Box which is wrong . What should i do
string connectionStringold = Application.StartupPath + "\Language-Resources-3.0" + ".xls";
string connstrold = "Provider=Microsoft.Jet.Oledb.4.0;Data Source=" + connectionStringold + ";Extended Properties=Excel 8.0";
OleDbConnection connold = new OleDbConnection(connstrold);
string strSQLold = "SELECT * FROM [Resources$]";
OleDbCommand cmdold = new OleDbCommand(strSQLold, connold);
OleDbDataAdapter daold = new OleDbDataAdapter(cmdold);
DataTable dtold = new DataTable();
daold.Fill(dtold);
// dataGridView1.DataSource = dtold;
string connectionString = Application.StartupPath + "\\x_Lang_Res" + ".xls";
string connstr = "Provider=Microsoft.Jet.Oledb.4.0;Data Source=" + connectionString + ";Extended Properties=Excel 8.0";
OleDbConnection conn = new OleDbConnection(connstr);
string strSQL = "SELECT * FROM [Chinese$]";
OleDbCommand cmd = new OleDbCommand(strSQL, conn);
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
// dataGridView1.DataSource = dt;
foreach (DataRow row in dt.Rows)
{
string aa = row[1].ToString();
foreach (DataRow rowold in dtold.Rows)
{
string old = rowold[3].ToString();
if (!rowold[3].ToString().Contains(aa))
{
richTextBox1.Text = aa + "\n\r";
}
}
}
You are setting the result to the RTB.Text property each time.
if (!rowold[3].ToString().Contains(aa))
{
richTextBox1.Text = aa + "\n\r";
}
You need to use += to append it.
if (!rowold[3].ToString().Contains(aa))
{
richTextBox1.Text += aa + "\n\r";
}
or even better use
RTB.AppendText( string.Format( "....." , a , b );
Try Replacing this part of the code
if (!rowold[3].ToString().Contains(aa))
{
richTextBox1.Text = aa + "\n\r";
}
With this
if (aa!=old)
{
richTextBox1.Text = richTextBox1.Text + aa + "\n\r";
}

Categories