I am using OLEDB object to read an Excel file and return data in a datatable. The following Excel sheet has two columns, which imported, but I want to read the Excel row number as well, with my data.
This is the code I am using to read the Excel file:
private DataTable ImportExcel2007(String strFilePath)
{
if (!File.Exists(strFilePath)) return false;
String strExcelConn = "Provider=Microsoft.ACE.OLEDB.12.0;"
+ "Data Source=" + strFilePath + ";"
+ "Extended Properties='Excel 8.0;HDR=Yes'";
OleDbConnection connExcel = new OleDbConnection(strExcelConn);
OleDbCommand cmdExcel = new OleDbCommand();
try
{
cmdExcel.Connection = connExcel;
//Check if the Sheet Exists
connExcel.Open();
DataTable dtExcelSchema;
//Get the Schema of the WorkBook
dtExcelSchema = connExcel.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
connExcel.Close();
//Read Data from Sheet1
connExcel.Open();
OleDbDataAdapter da = new OleDbDataAdapter();
DataSet ds = new DataSet();
string SheetName = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
cmdExcel.CommandText = "SELECT * From [" + SheetName + "]";
//Range Query
//cmdExcel.CommandText = "SELECT * From [" + SheetName + "A3:B5]";
da.SelectCommand = cmdExcel;
da.Fill(ds);
connExcel.Close();
return ds.Table[0];
}
catch
{
return null;
}
finally
{
cmdExcel.Dispose();
connExcel.Dispose();
}
}
I can manage it by incremented number with new column in data table, but can I apply a WHERE clause with a SELECT statement to return data from different row numbers (where applying an incremented row number may fail)?
Unfortunately, OLEDB doesn't allow you to select based on row number. You can use something like this:
int rowNum = 0;
foreach (DataTable dt in ds.Tables)
{
dt.Columns.Add("RowNum",typeof(Int32));
rowNum = 1;
foreach (DataRow dr in dt.Rows)
{
dr["RowNum"] = rowNum++;
}
}
Related
I want to view the Excel data with headers inside datagridview.
I have tried changing HDR=Yes to HDR=No. It shows all the data but I have headers on the Excel file.
I changed this code:
string pathconn = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=No;IMEX=1\";";
To:
string pathconn = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=No;IMEX=1\";";
This is my Excel data:
You have to put in the column name the text of the first row of the datatable.
Then delete the row.
Datatable dtExcel = importaExcelaDT(filePath);
for(int i = 0; i < dtExcel.Columns.Count; i++)
{
string columnName = dtExcel.Rows[0][i].ToString();
if (columnName == "") //throws error if column name is empty
columnName = " ";
dtExcel.Columns[i].ColumnName = columnName;
}
dtExcel.Rows.RemoveAt(0);
yourDataGridView.DataSource = dtExcel;
I get data with headers with this function.
public DataTable importaExcelaDT(string file)
{
DataTable dt = new DataTable();
DataTable dtExcel = new DataTable();
OleDbCommand cmdExcel = new OleDbCommand();
string cadenaConexion = "provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + file + "';Extended Properties = \"Excel 12.0 Xml;HDR=No;IMEX=1\";";
OleDbConnection olConexion = new OleDbConnection(cadenaConexion);
olConexion.Open();
OleDbDataAdapter oda = new OleDbDataAdapter();
dt = olConexion.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
string sheet = dt.Rows[0]["TABLE_NAME"].ToString();
cmdExcel.Connection = olConexion;
cmdExcel.CommandText = "SELECT * FROM [" + sheet + "]";
oda.SelectCommand = cmdExcel;
oda.Fill(dtExcel);
olConexion.Close();
olConexion.Dispose();
oda.Dispose();
return dtExcel;
}
I am trying to retrieve values of the first column from the Excel sheet called "SP$".
I have the path:
string path = #"C:\Users\atsurkanu\Desktop" + #"\TemplateClientExtraction_IDEAFIMIT_Conero_QUARTER_20170127.xlsm";
string connectionString = string.Format(#"provider=Microsoft.ACE.OLEDB.12.0;data source={0};Extended Properties=Excel 12.0;", path);
string sheetName = "SP$";
and some code like this one:
using (OleDbConnection con = new OleDbConnection(connectionString))
{
try
{
var dataTable = new DataTable();
con.Open();
var tableschema = con.GetSchema("Tables");
var firstsheet = tableschema.Rows[0]["SP$"].ToString();
string name_query = "SELECT A4 FROM [" + firstsheet + "]";
OleDbDataAdapter da = new OleDbDataAdapter(name_query, con);
da.Fill(dataTable);
con.Close();
But it doesn't work. Please, tell me, how I cat retrieve the first column from Excel sheet.
UPDATE:
I am not sure how it works, but it helps:
var dataTable = new DataTable();
con.Open();
var tableschema = con.GetSchema("Tables");
// To get the first sheet name you use the first row and the column named TABLE_NAME
var firstsheet = tableschema.Rows[0]["TABLE_NAME"].ToString();
string name_query = "SELECT F1 FROM [" + "SP$" + "] WHERE F1 <> ''";
OleDbDataAdapter da = new OleDbDataAdapter(name_query, con);
da.Fill(dataTable);
foreach (DataRow dataRow in dataTable.Rows)
{
foreach (var item in dataRow.ItemArray)
{
listWithElementsFromSPfirstColumn.Add((string)item);
}
}
You can't use "A4" and hope that OleDb understands the row/columns conventions of Excel. For OleDb the sheet is just a DataTable and you need to load it all or provide a WHERE condition to filter the rows you want to retrieve.
It is not clear if your sheet has HEADERs or not. You need to add to your connectionstring the key HDR=NO or HDR=YES. In case the headers are missing then OleDb assign automatically the column names with F1, F2, F3 and so on.
So you can query your sheet with something like this or change the F1 to the header of the column A.
using (OleDbConnection con = new OleDbConnection(connectionString))
{
try
{
var dataTable = new DataTable();
con.Open();
var tableschema = con.GetSchema("Tables");
// To get the first sheet name you use the first row and the column named TABLE_NAME
var firstsheet = tableschema.Rows[0]["TABLE_NAME"].ToString();
string name_query = "SELECT F1 FROM [" + firstsheet + "] WHERE F1 <> ''";
OleDbDataAdapter da = new OleDbDataAdapter(name_query, con);
da.Fill(dataTable);
}
catch .....
}
Now it is up to you to read the datatable and use the content of the column F1 (the A column for Excel)
My application imports a sheet from an excel file with only the header column names into a new dataGridView Table. To keep it easy lets say the Column names are; Name, City, State, Status. I "hard code" the first 2 entries as Jack, Detroit, MI, Missing; and Mike, Chicago, IL, Missing. Next I import an XML file that adds more entries. I have the code looking for the original 2 entries, if found, I want it to "update" or "re-edit" the Missing to Found. (I want this to happen ONLY in the dataGridView Table. The sql examples I'm finding are all aimed at updating the original database. I want it to only update the dataGridView table.
This code is designed to update the excel file.
sql = "UPDATE " + myNameRange + " SET " + mySET + "' WHERE " + myWHERE + "'";
Is there a way I can do something like this only to change the data in the dataGridView?
Method to bring in sheets from excel
public static void loadData(string SheetName, DataGridView MyDataGrid, string filePathMain)
{
string pathCon = "Provider=Microsoft.Ace.OLEDB.12.0; Data Source=" + filePathMain + ";Extended Properties=\"Excel 8.0; HDR=YES;IMEX=3;READONLY=FALSE\";";
OleDbConnection conn = new OleDbConnection(pathCon);
OleDbCommand cmd = new OleDbCommand("select * from [" + SheetName + "]", conn);
conn.Open();
OleDbDataAdapter myDataAdapter = new OleDbDataAdapter(cmd);
DataTable dt = new DataTable();
myDataAdapter.Fill(dt);
//MessageBox.Show( dt.Rows.Count.ToString());
MyDataGrid.Tag = dt.Rows.Count.ToString();
MyDataGrid.DataSource = dt;
OleDbCommand updateCmd = new OleDbCommand("UPDATE [" + SheetName + "]");
myDataAdapter.UpdateCommand = updateCmd;
conn.Close();
}
Here I'm hard coding the data into the table. This works.
DataTable dt = ((DataGridView)TC).DataSource as DataTable;
DataRow row0 = dt.NewRow();
row0["Name"] = "Jack";
row0["Status"] = "MISSING";
dt.Rows.Add(row0);
DataRow row1 = dt.NewRow();
row1["Name"] = "Mike";
row1["Status"] = "MISSING";
dt.Rows.Add(row1);
dgvThing.DataSource will give you the data that is bound to your DataGridView and you can minipulate this without modifying your original data source i.e. the excel file.
Edit: In this case, you would loop through the rows to find your person and update their status like so.
DataTable dt = ((DataGridView)TC).DataSource as DataTable;
foreach (DataRow row in dt.Rows)
{
if (row["Name"].Equals("Jack"))
row["Status"] = "Found";
}
I have an excel file with one worksheet. I'm using MicroSoft.Office.Interop.Excel to read this file and then perform further execution.
Here is my code:
connString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + strNewPath + ";Extended Properties=Excel 8.0;";
conn = new OleDbConnection(connString);
if (conn.State == ConnectionState.Closed)
conn.Open();
System.Data.DataTable dt = null;
dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
But, worksheet is not in the data table object.
Where you have mentioned the table(WorkSheet) name ??
DataTable schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,
new object[] {null, null, null, "TABLE"});
//Get the First Sheet Name
string firstSheetName = schemaTable.Rows[0][2].ToString();
//Query String
string sql = string.Format("SELECT * FROM [{0}],firstSheetName);
Refer here MSDN
In case if you want to play around refer Reading Excel files from C#
OleDbConnection oconn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + "; Extended Properties=Excel 12.0;");
//After connecting to the Excel sheet here we are selecting the data
//using select statement from the Excel sheet
oconn.Open();
DataTable dbSchema = oconn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dbSchema == null || dbSchema.Rows.Count < 1)
{
throw new Exception("Error: Could not determine the name of the first worksheet.");
}
string firstSheetName = dbSchema.Rows[0]["TABLE_NAME"].ToString();
string tbstrat = "M1000";
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = oconn;
cmd.CommandText = "select * from [" + firstSheetName + "B8:" + tbstrat + "]";
OleDbDataAdapter adap = new OleDbDataAdapter();
DataTable dt = new DataTable();
adap.SelectCommand = cmd;
adap.Fill(dt);
oconn.Close();
Even you can try this
var adapter = new OleDbDataAdapter("SELECT * FROM [workSheetNameHere$]", connectionString);
var ds = new DataSet();
adapter.Fill(ds, "NameHere");
DataTable data = ds.Tables["NameHere"];
I have an excel sheet similar to :
I want to read data columns header:All,col1,col2,col3,col4,col5
and get all cell data.for example cell in Row = 2 and column 2 = 0
I currently write this code :
OleDbDataAdapter dbAdapter = new OleDbDataAdapter("SELECT top 5 * FROM " + excelSheets[j], connString);
DataTable fooData = new DataTable();
dbAdapter.Fill(fooData);
foreach (DataRow row in fooData.Rows)
{
Response.Write(row[0].ToString());
//Response.Write(row[1].ToString());
}
but it return just a data table with 1 column and just row 1..5 text.
How I can do this?
Please say answer without using Linq to Excel Provider and Open Xml.
Edit 1:
string file_name = "C:\\Book1.xlsx";
string connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + file_name + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\"";
objConn = new OleDbConnection(connString);
objConn.Open();
dt = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
Response.Write("Not Exist");
}
String[] excelSheets = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
i++;
}
// Loop through all of the sheets if you want too...
for (int j = 0; j < excelSheets.Length; j++)
{
OleDbDataAdapter dbAdapter = new OleDbDataAdapter("SELECT top 100 * FROM " + excelSheets[j], connString);
DataTable fooData = new DataTable();
dbAdapter.Fill(fooData);
foreach (DataRow row in fooData.Rows)
{
Response.Write(row[0].ToString());
}
}
You get the column name for the first column for example by fooData.Columns[0].ColumnName - see http://msdn.microsoft.com/en-us/library/system.data.datacolumn.columnname.aspx
EDIT:
Change the SELECT to SELECT * FROM AND use Fill (0, 5, new DataTable[] { fooData }).
"SELECT * FROM [" + excelSheets[j] + "$A1:C5]"
Try this one. It should return all of the cells from A1 to C5.
The driver that you selected is for Excel 2007 ("Provider=Microsoft.ACE.OLEDB.12.0" in your connectionString). Is your Excel file 2007 or 2010?
For Only data column header for logic is here:
string filePath = "C:\\Book1.xlsx";
string connString = string.Empty;
if (path.EndsWith(".xlsx"))
{
//2007 Format
connString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 8.0;HDR=No'", path);
}
else
{
//2003 Format
connString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='Excel 8.0;HDR=No'", path);
}
using (OleDbConnection con = new OleDbConnection(connString))
{
using (OleDbCommand cmd = new OleDbCommand())
{
//Read the First Sheet
cmd.Connection = con;
con.Open();
DataTable dtExcelSchema = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
con.Close();
string firstSheet = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
//Read the Header Row
cmd.CommandText = "SELECT top 1 * From [" + firstSheet + "]";
using (OleDbDataAdapter da = new OleDbDataAdapter(cmd))
{
DataTable HeaderColumns = new DataTable();
da.SelectCommand = cmd;
da.Fill(HeaderColumns);
List<string> Filedata = new List<string>();
foreach (DataColumn column in HeaderColumns.Columns)
{
string columnName = HeaderColumns.Rows[0][column.ColumnName].ToString();
Filedata.Add(columnName);
ViewBag.Data = Filedata;
}
}
}
}