get number of sheet in xls excel file - c#

how to get how many worksheet in file
string connectionString = String.Format(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=""Excel 8.0;HDR=no;IMEX=1;""", openFileDialog1.FileName);
now i want know how many worksheet in side given ?
what code i should i write ?
how can i know ?
thanks

While the question pointed to by Haris Hasan will allow you to extract the sheet names, if you just want the number of worksheets in a workbook, the following will do the trick:
string connectionString = String.Format(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=""Excel 8.0;HDR=no;IMEX=1;""", openFileDialog1.FileName);
int numberOfSheets = 0;
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
DataTable dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt != null)
{
foreach (DataRow row in dt.Rows)
{
if (row["TABLE_NAME"].ToString().EndsWith("$"))
{
numberOfSheets++;
}
}
}
}
EDIT:
Or, for a shorter version, use the following (thanks for jb for helping me on this one):
string connectionString = String.Format(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=""Excel 8.0;HDR=no;IMEX=1;""", openFileDialog1.FileName);
int numberOfSheets = 0;
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
DataTable dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt != null)
{
numberOfSheets = dt.AsEnumerable().Cast<DataRow>().Where(row => row["TABLE_NAME"].ToString().EndsWith("$")).Count();
}
}

Related

c# provider for excel not registered

For some projects I need the options of exporting and importing from/to an Excel.
For that I'm using that code:
private void myButton12_Click(object sender, EventArgs e)
{
string path = string.Empty;
string ext = string.Empty;
OpenFileDialog file = new OpenFileDialog();
if (file.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
path = file.FileName;
ext = System.IO.Path.GetExtension(path);
if(ext == ".xls" || ext == ".xlsx")
{
Console.WriteLine("ok");
DataTable dt = new DataTable();
dt = ReadExcel(path, ext);
dataGridView13.DataSource = dt;
}
}
}
public DataTable ReadExcel(string fileName, string fileExt)
{
string conn = string.Empty;
DataTable dtexcel = new DataTable();
if (fileExt.CompareTo(".xls") == 0)
conn = #"provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + ";Extended Properties='Excel 8.0;HRD=Yes;IMEX=1';"; //for below excel 2007
else
conn = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties='Excel 16.0;HDR=NO';"; //for above excel 2007
using (OleDbConnection con = new OleDbConnection(conn))
{
try
{
OleDbDataAdapter oleAdpt = new OleDbDataAdapter("select * from [Sheet1$]", con); //here we read data from sheet1
oleAdpt.Fill(dtexcel); //fill excel data into dataTable
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
return dtexcel;
}
Problem is that I get that Exception:
The provider 'Microsoft.ACE.OLEDB.12.0' is not registered on the local computer.
After looking on the internet, I seems like it come from the x86 configuration need that I tried... I've also tried switching for some others, but none of them worked,
I really can't find any solution to my problem,
Any idea where the problem can be?
Thanks
If you run your app in X64 Target CPU you need "AccessDatabaseEngine_X64.exe" , if you run your app in X86 you need "AccessDatabaseEngine.exe" fromthe page below :
https://www.microsoft.com/en-us/download/details.aspx?id=13255

How do you programmatically check if a spreadsheet has headers in C#

I am creating a winform application where every day, a user will select a xlsx file with the day's shipping information to be merged with our invoicing data.
The challenge I am having is when the user does not download the xlsx file with the specification that the winform data requires. (I wish I could eliminate this step with an API connection but sadly I cannot)
My first step is checking to see if the xlsx file has headers to that my file path is valid
Example
string connString = "provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + *path* + "';Extended Properties='Excel 12.0;HDR=YES;';";
Where path is returned from an OpenFileDialog box
If the file was chosen wasn't downloaded with headers the statement above throws an exception.
If change HDR=YES; to HDR=NO; then I have trouble identifying the columns I need and if the User bothered to include the correct ones.
My code then tries to load the data into a DataTable
private void loadRows()
{
for (int i = 0; i < deliveryTable.Rows.Count; i++)
{
DataRow dr = deliveryTable.Rows[i];
int deliveryId = 0;
bool result = int.TryParse(dr[0].ToString(), out deliveryId);
if (deliveryId > 1 && !Deliveries.ContainsKey(deliveryId))
{
var delivery = new Delivery(deliveryId)
{
SalesOrg = Convert.ToInt32(dr[8]),
SoldTo = Convert.ToInt32(dr[9]),
SoldName = dr[10].ToString(),
ShipTo = Convert.ToInt32(dr[11]),
ShipName = dr[12].ToString(),
};
Which all works only if the columns are in the right place.
If they are not in the right place my thought is to display a message to the user to get the right information
Does anyone have any suggestions?
(Sorry, first time posting a question and still learning to think through it)
I guess you're loading the spreadsheet into a Datatable? Hard to tell with one line of code. I would use the columns collection in the datatable and check to see if all the columns you want are there. Sample code to enumerate the columns below.
private void PrintValues(DataTable table)
{
foreach(DataRow row in table.Rows)
{
foreach(DataColumn column in table.Columns)
{
Console.WriteLine(row[column]);
}
}
}
private void GetExcelSheetForUpload(string PathName, string UploadExcelName)
{
string excelFile = "DateExcel/" + PathName;
OleDbConnection objConn = null;
System.Data.DataTable dt = null;
try
{
DataSet dss = new DataSet();
String connString = "Provider=Microsoft.ACE.OLEDB.12.0;Persist Security Info=True;Extended Properties=Excel 12.0 Xml;Data Source=" + PathName;
objConn = new OleDbConnection(connString);
objConn.Open();
dt = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
return;
}
String[] excelSheets = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
if (i == 0)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
OleDbCommand cmd = new OleDbCommand("SELECT * FROM [" + excelSheets[i] + "]", objConn);
OleDbDataAdapter oleda = new OleDbDataAdapter();
oleda.SelectCommand = cmd;
oleda.Fill(dss, "TABLE");
}
i++;
}
grdExcel.DataSource = dss.Tables[0].DefaultView;
grdExcel.DataBind();
lblTotalRec.InnerText = Convert.ToString(grdExcel.Rows.Count);
}
catch (Exception ex)
{
ViewState["Fuletypeidlist"] = "0";
grdExcel.DataSource = null;
grdExcel.DataBind();
}
finally
{
if (objConn != null)
{
objConn.Close();
objConn.Dispose();
}
if (dt != null)
{
dt.Dispose();
}
}
}
if (grdExcel.HeaderRow.Cells[0].Text.ToString() == "CODE")
{
GetExcelSheetForEmpl(PathName);
}
else
{
divStatusMsg.Style.Add("display", "");
divStatusMsg.Attributes.Add("class", "alert alert-danger alert-dismissable");
divStatusMsg.InnerText = "ERROR !!... Upload Excel Sheet in header Defined Format ";
}

Identify and load the Row Grouping in Excel using C#

I have a huge Excel file with around 50k rows. I am reading it using the following connection string
string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0 Xml;HDR=No;IMEX=1'", MyFilePath);
In this huge Excel file, the rows are grouped in nesting pattern. Meaning, lets say first 500 rows are grouped under Group A there is a sub group in that group comprising of rows from 300-400 as Group B and then again from 350-400
in Group C. Now when I read the excel file in my program, I get all the rows, but I cannot distinguish between the row grouping I mentioned above. Is there any smart way to identify and group them accordingly?
Here's a sample of my code.
rivate List<List<string>> ReadSheetData(string _query, bool _HasHeaders = true)
{
string conn = "";
if (!_HasHeaders)
conn = string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0 Xml;HDR=No;IMEX=1'", MyFilePath);
else
conn = this.conn;
List<List<string>> ret = new List<List<string>>();
using (OleDbConnection connection = new OleDbConnection(conn))
{
connection.Open();
try
{
OleDbCommand command = new OleDbCommand(_query, connection);
using (OleDbDataReader dr = command.ExecuteReader())
{
DataTable tbl = dr.GetSchemaTable();
while (dr.Read())
{
List<string> rowVals = new List<string>();
ret.Add(rowVals);
for (int i = 0; i < dr.FieldCount; i++)
{
dynamic cell = dr[i];
string value = cell != null ? cell.ToString() : "";
rowVals.Add(value);
}
}
}
}
catch (Exception ex)
{ }
}
ret.RemoveAll(a => a.All(b => b == "") == true);
return ret;
}

Calculate Excel value before import to SQL Server

I have problem about import to SQL Server, the scenario is to import excel file and calculate the value in column 3 and 4 (produce column 5) of the imported excel file. In my case, the calculation is in C#, not in excel. And then import to SQL Server (ASP.Net + C#). Any idea how to do this ?
This is my code (it's still give me error)
protected void btnImport_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
string FileName = Path.GetFileName(FileUpload1.PostedFile.FileName);
string Extension = Path.GetExtension(FileUpload1.PostedFile.FileName);
if (Extension == ".xlsx")
{
string path = string.Concat((Server.MapPath("~/tampung/" + FileUpload1.FileName)));
FileUpload1.PostedFile.SaveAs(path);
//make connection to excel workBook
using (OleDbConnection oledbcon = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=Excel 12.0;"))
{
OleDbCommand cmd = new OleDbCommand("SELECT * FROM [Sheet1$]", oledbcon);
OleDbDataAdapter ObjAdapter1 = new OleDbDataAdapter(cmd);
oledbcon.Open();
using (DbDataReader dr = cmd.ExecuteReader())
{
DataTable DT = new DataTable();
DT.Load(dr);
for (int i = 0; i < DT.Rows.Count; i++)
{
string Year = DT.Rows[i][0].ToString();
string StudentName = DT.Rows[i][1].ToString();
string Semester = DT.Rows[i][2].ToString();
decimal Value1 = Convert.ToDecimal(DT.Rows[i][3]);
decimal Value2 = Convert.ToDecimal(DT.Rows[i][4]);
decimal AverageValue = Convert.ToDecimal((Value1 + Value2) / 2);
}
string conString = #"Data Source=PETRELLI;Initial Catalog=demo;Integrated Security=True";
SqlBulkCopy bulkInsert = new SqlBulkCopy(conString);
bulkInsert.DestinationTableName = "student";
bulkInsert.WriteToServer(dr);
oledbcon.Close();
Array.ForEach(Directory.GetFiles(Server.MapPath("~/temp/")), File.Delete);
Label1.Text = "Succeeded";
}
}
}
else
{
Label1.Text = "Hi, it's error";
}
}
else
{
Label1.Text = "Please choose the right file excel";
}
}
The error should be coming from this line
bulkInsert.WriteToServer(dr);
This is happening because DT.Load(dr), that you called earlier, have looped through the dr already and has moved the pointer to the end, after which you can not use the dr again.
DT.Load(dr); //<-- this line already looped through the dr. dr can't be used after this line
Solution
Use the DT instead of dr since you already have DT populated with the required data by calling DT.Load(dr)

Reading columns from Excel, reformat cells

I am currently trying to read in cells from an excel spread sheet, and it seems to reformat cells when I don't want it to. I want it to come through as plan text. I have read a couple of solutions to this problem and I have implemented them, but I am still having the same issue.
The reader turns dates in numbers and numbers into dates.
Example:
Friday, January 29, 2016 comes out to be : 42398
and
40.00 comes out to be : 2/9/1900 12:00:00 AM
code:
string stringconn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + files[0] + ";Extended Properties=\"Excel 12.0;IMEX=1;HDR=NO;TypeGuessRows=0;ImportMixedTypes=Text\"";
try {
OleDbConnection conn = new OleDbConnection(stringconn);
OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM [CUAnswers$]", conn);
DataTable dt = new DataTable();
try {
printdt(dt);
I have tried
IMEX=0;
HDR=NO;
TypeGuessRows=1;
This is how I am printing out the sheet
public void printdt(DataTable dt) {
int counter1 = 0;
int counter2 = 0;
string temp = "";
foreach (DataRow dataRow in dt.Rows) {
foreach (var item in dataRow.ItemArray) {
temp += " ["+counter1+"]["+counter2+"]"+ item +", ";
counter2++;
}
counter1++;
logger.Debug(temp);
temp = "";
counter2 = 0;
}
}
I had a similar problem, except it was using Interop to read the Excel spreadsheet. This worked for me:
var value = (range.Cells[rowCnt, columnCnt] as Range).Value2;
string str = value as string;
DateTime dt;
if (DateTime.TryParse((value ?? "").ToString(), out dt))
{
// Use the cell value as a datetime
}
Editted to add new ideas
I was going to suggest saving the spreadsheet as comma-separated values. Then Excel converts the cells to text. It is easy to parse a CSV in C#.
That led me to think of how to programmatically do the conversion, which is covered in Convert xls to csv programmatically. Maybe the code in the accepted answer is what you are looking for:
string ExcelFilename = "c:\\ExcelFile.xls";
DataTable worksheets;
string connectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;" + #"Data Source=" + ExcelFilename + ";" + #"Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""";
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
connection.Open();
worksheets = connection.GetSchema("Tables");
foreach (DataRow row in worksheets.Rows)
{
// For Sheets: 0=Table_Catalog,1=Table_Schema,2=Table_Name,3=Table_Type
// For Columns: 0=Table_Name, 1=Column_Name, 2=Ordinal_Position
string SheetName = (string)row[2];
OleDbCommand command = new OleDbCommand(#"SELECT * FROM [" + SheetName + "]", connection);
OleDbDataAdapter oleAdapter = new OleDbDataAdapter();
oleAdapter.SelectCommand = command;
DataTable dt = new DataTable();
oleAdapter.FillSchema(dt, SchemaType.Source);
oleAdapter.Fill(dt);
for (int r = 0; r < dt.Rows.Count; r++)
{
string type1 = dr[1].GetType().ToString();
string type2 = dr[2].GetType().ToString();
string type3 = dr[3].GetType().ToString();
string type4 = dr[4].GetType().ToString();
string type5 = dr[5].GetType().ToString();
string type6 = dr[6].GetType().ToString();
string type7 = dr[7].GetType().ToString();
}
}
}

Categories