How to read data from Excel in Asp.Net - asp.net

I am trying to read datas from an uploaded xls. I have used this code part:
OleDbConnection connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath(fileName) + ";Extended Properties=Excel 8.0");
if (connection.State == ConnectionState.Closed)
connection.Open();
string query = "select * from [Sheet1$]";
OleDbDataAdapter da = new OleDbDataAdapter(query, connection);
DataSet ds = new DataSet();
da.Fill(ds);
But I get this error: External table is not in the expected format.
I am pretty sure I am giving the correct path. I was working and it is not. if it works then it wont fill the datatable. It gives an error that says that Sheet1$ object can not be found. Any help?

are you sure the excel version is correct? you may also want to wrap the extended properties in quotes as well. I would also recommend cleaning up your resources so you don't create memory leaks.
var path = Server.MapPath(fileName);
//where 8.0 may be a different version: 9 - 12?
var connectionString = string.Format(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended ""Properties=Excel 8.0""", path);
using(var connection = new OleDbConnection(connectionString))
using(var command = connection.CreateCommand())
{
connection.Open();
command.CommandText = "select * from [Sheet1$]";
var table = new DataTable();
using(var reader = command.ExeucteReader())
{
table.Load(reader);
return table;
}
}

Have a look at this thread:
Excel "External table is not in the expected format."
Maybe you should change provider as they suggest.
One other option is to use the OpenXML SDK to read the excel file. This could get you started:
http://msdn.microsoft.com/en-us/library/ff921204.aspx

string savePath = "/Assets/UploadedFiles/";
string fileName = "Activity.xls";
savePath += fileName;
OleDbConnection conn= new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Server.MapPath(savePath) + ";Extended Properties='Excel 12.0;HDR=YES'");
if (conn.State == ConnectionState.Closed)
conn.Open();
string query = "select * from [Sheet1$]";
OleDbDataAdapter da = new OleDbDataAdapter(query, conn);
DataSet ds = new DataSet();
da.Fill(ds, "Activities");
dt = ds.Tables[0];
conn.Close();

save the file in the hard disk, then add a reference to Microsoft Excel 12.0 Object Library and declare the using:
using Excel = Microsoft.Office.Interop.Excel;
then instantiate a class and load the file to read the cell values, example:
Excel.Application xlApp ;
Excel.Workbook xlWorkBook ;
Excel.Worksheet xlWorkSheet ;
object misValue = System.Reflection.Missing.Value;
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Open("file.xls", 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
MessageBox.Show(xlWorkSheet.get_Range("A1","A1").Value2.ToString());
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
EDIT 1:
If you don't want to install Office in the server, you can use the excellibrary that works similar, simple as (from the author page) :
// open xls file
Workbook book = Workbook.Load(file);
Worksheet sheet = book.Worksheets[0];
// traverse cells
foreach (Pair<Pair<int, int>, Cell> cell in sheet.Cells)
{
dgvCells[cell.Left.Right, cell.Left.Left].Value = cell.Right.Value;
}
// traverse rows by Index
for (int rowIndex = sheet.Cells.FirstRowIndex;
rowIndex <= sheet.Cells.LastRowIndex; rowIndex++)
{
Row row = sheet.Cells.GetRow(rowIndex);
for (int colIndex = row.FirstColIndex;
colIndex <= row.LastColIndex; colIndex++)
{
Cell cell = row.GetCell(colIndex);
}
}

Related

Getting error from accessing DataReader value (accessing joined table results in SqlDataReader)

UPDATE - PROBLEM SOLVED
Just in case to retrieve all data at once, using a single SQL statement to retrieve joined table results, but couldn't access it and received error below
Exception details: System.IndexOutOfRangeException: crsName
By the way, anyone please suggest a more convenient way to deal with a GridView that need to display a JOIN result.
Instead of this approach - https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.datacontrolfieldcollection.add?view=netframework-4.8
BoundField courseBF = new BoundField();
courseBF.DataField="courseName";
courseBF.HeaderText="Course Name";
//Which is stated in Microsoft Document
Here's the code receive error
string userID = (string)Session["userID"];
string sql = "SELECT courseID from gpaSem where stuID=#userID";
string temp = "";
string temp02 = "";
string[] crsID;
string[] crsName;
string[] grade;
SqlConnection con = new SqlConnection(cs);
SqlCommand cmd = new SqlCommand(sql, con);
cmd.Parameters.AddWithValue("#userID", userID);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
temp += ("!" + dr["courseID"]);
}
crsID = temp.Split('!');
crsID = crsID.Skip(1).ToArray();//course ID get
dr.Close();
con.Close();
con.Open();
temp = "";
foreach (string crs in crsID)
{
sql = "SELECT G.grade AS grade, C.crsName AS crsName FROM gpaSem G, course C WHERE G.courseID=C.courseID AND G.courseID=#courseID";
cmd.Parameters.AddWithValue("#courseID", crs);
dr = cmd.ExecuteReader();
if(dr.Read())
{
temp += "!" + dr["crsName"];//error
temp02 += "!" + dr["grade"];
}
}
crsName = temp.Split('!');
crsName = crsName.Skip(1).ToArray();//course name get
grade = temp02.Split('!');
grade = grade.Skip(1).ToArray();//grade get
dr.Close();
con.Close();
My point is, is that I should explicitly use JOIN in SQL statement or the way I access the value is wrong?

Import a Excel sheet into MS SQL database

I have Excel 2007 and Visual Web Developer Express 2010.
I would like to import Sheet1 of an xlsx file the reader then add the data to a dataset and placing that data in a MS SQL database.
string ExcelConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\myFolder\myExcel2007file.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES";
string SQLConStr = "got connection string that works";
OleDbConnection ExcelConnection = new OleDbConnection(ExcelConStr);
using (ExcelConnection)
{
string sql = string.Format("Select * FROM [{0}]", "Sheet1$");
OleDbCommand command = new OleDbCommand(sql, ExcelConnection);
ExcelConnection.Open();
using (OleDbDataReader dr = command.ExecuteReader())
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(SQLConStr))
{
bulkCopy.DestinationTableName = "dbo.databaseName";
bulkCopy.WriteToServer(dr);
}
}
}
I need something like bulkcopy that is free and easy to use if someone may make a recommendation.
Without bulk copy it will also work.. try this it will work 100% for .csv and .xlsx both... I m using it..
string header = "No";
string sql = string.Empty;
DataTable dt = new DataTable();
string pathOnly = string.Empty;
string fileName = string.Empty;
pathOnly = Path.GetDirectoryName(path);
fileName = Path.GetFileName(path);
if (IsFirstRowHeader) { header = "Yes"; }
String cs = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\"Excel 12.0;HDR=" + header + ";IMEX=1;\"";
OleDbConnection con = new OleDbConnection(cs);
if (con.State == ConnectionState.Closed) con.Open();
#region use to find sheet and fire query on sheetname
DataTable dtsheets = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
String[] excelSheets = new String[dtsheets.Rows.Count];
int i = 0;
// Add the sheet name to the string array.
foreach (DataRow row in dtsheets.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
i++;
}
if (extension == ".csv") sql = "SELECT * FROM [" + fileName + "]";
else sql = "SELECT * FROM [" + excelSheets[0] + "]";
#endregion
OleDbCommand command = new OleDbCommand(sql, con);
OleDbDataAdapter adapter = new OleDbDataAdapter(command);
dt.Locale = CultureInfo.CurrentCulture;
adapter.Fill(dt);
con.Close();

OleDb - Retrieving Excel worksheet names also retrieves Defined Names

I am trying to retrieve a list of the worksheets in an Excel workbook, but the collection I get back has both the sheet names and the data column id's, which seem to be called 'Defined Names' in the original xlsx xml. Can you tell me how to return only the worksheet names?
The code I'm using is along the lines of:
OleDbConnection connExcel = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;"
+ #"Data Source=" + FilePath + ";"
+ #"Extended Properties=""Excel 8.0;HDR=Yes;""");
OleDbCommand cmdExcel = new OleDbCommand();
cmdExcel.Connection = connExcel;
connExcel.Open();
DataTable testTable = connExcel.GetSchema("Tables");
The contents of the resulting testTable collection contain entries under TABLE_NAME of:
DATA1
DATA2
DATA3
DATA4
DATA5
Sheet1$
TEST1
-TEST2
TESTHKEY
TESTKEYS
TESTVKEY
They all have a TABLE_TYPE of TABLE.
The original workbook corresponding to the above would have 1 worksheet containing 5 columns, the first row would contain a header. I'm only interested in the Sheet1$ entry. The spreadsheet is
created in Excel 2010, I'm trying to process it in an ASP.NET 4 app written in C#. Potentially, the worksheet name may have been changed so I can't guarrantee that it will always be Sheet1$.
My first thoughts were wrong so I came up with this as a workaround. The actual worksheet names returned should always end with $, so I hacked it to check for that. Messy but you get the general idea I'm sure.
OleDbConnection connExcel = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;"
+ #"Data Source=c:\test.xlsx;"
+ #"Extended Properties=""Excel 12.0 Xml;HDR=Yes;""");
OleDbCommand cmdExcel = new OleDbCommand();
cmdExcel.Connection = connExcel;
connExcel.Open();
DataTable testTable = connExcel.GetSchema("Tables");
String[] excelSheets = new String[testTable.Rows.Count];
int i = 0;
foreach (DataRow row in testTable.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
if (excelSheets[i].EndsWith("$"))
{
Console.WriteLine(excelSheets[i] = row["TABLE_NAME"].ToString());
i++;
}
else
{
i++;
}
}
Console.ReadLine();
I had a similar issue but with the exception that it showed me Sheets that didn't exist in Excel. Even though this post is a bit old now, maybe somebody finds this and finds it helpful.
My Code:
//OpenFileDialog
try
{
OpenFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
OpenFileDialog.Filter = "XLSX Files(*.xlsx)|*.xlsx|All Files (*.*)|*.*";
OpenFileDialog.ShowDialog();
}
catch (Exception ex)
{
//some Error Message
}
//read into Combobox
try
{
OleDbConnection con = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + OpenFileDialog.FileName + ";Extended Properties=Excel 12.0;");
con.Open();
DataTable dt = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
con.Close();
this.Combobox.Items.Clear();
for (int i = 0; i < dt.Rows.Count; i++)
{
String sheetName = dt.Rows[i]["TABLE_NAME"].ToString();
sheetName = sheetName.Substring(0, sheetName.Length - 1);
//cheap Filter to filter out unneeded/wrong sheets
if (sheetName.Replace("'", " ").Replace("$", " ").TrimStart().TrimEnd().Contains("#") != true)
{
this.Combobox.Items.Add(sheetName.Replace("'", " ").Replace("$", " ").TrimStart().TrimEnd());
}
}
}
catch (Exception Ex)
{
//some Error Message
}
This might not be the best solution, but it works quite well for me.
private static string EXCEL_CONNECTIONSTRING = string.Format("Provider=Microsoft.ACE.OLEDB.12.0; data source={0}; Extended Properties=Excel 12.0;", "#{FILENAME}");
private IEnumerable<string> GetWorksheetNames(string excelFile)
{
var currentConnectionString = EXCEL_CONNECTIONSTRING.Replace("#{FILENAME}", excelFile);
using (OleDbConnection connection = new OleDbConnection(currentConnectionString))
{
OleDbCommand cmdExcel = new OleDbCommand();
cmdExcel.Connection = connection;
connection.Open();
DataTable dt = connection.GetSchema("Tables");
IEnumerable<string> excelSheets = dt.Rows.Cast<DataRow>().Select(row => row["TABLE_NAME"].ToString());
dt.Dispose();
connection.Close();
return excelSheets;
}
}

How to populate the excelsheetcloumn names into a dropdown list?

Hi i have an excel sheet with headers,i want to populate those headers into a dropdown list...
can any one help me with the select statement and procedure
i am working on a code i dnt know whether its correct or not
DropDownList list = new DropDownList();
string connectionstring = String.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=""Excel 8.0;HDR=YES;IMEX=1;""", Excelpath);
string query1 = String.Format("select * from [{0}]", DDlist.SelectedItem.Text);
// OleDbDataAdapter dataAdapter = new OleDbDataAdapter(query1, connectionstring);
using (OleDbConnection conn1 = new OleDbConnection(connectionstring))
{
OleDbCommand odc1 = new OleDbCommand(string.Format(query1, conn1));
conn1.Open();
OleDbDataReader dr;
dr = odc1.ExecuteReader();
while (dr.Read())
{
list.Items.Add(dr[column.ColumnName].ToString());
}
dr.Close();
conn1.Close();
}
in this method i am geting an error at this line
dr = odc1.ExecuteReader();Error:ExecuteReader: Connection property has not been initialized.
can any one help mw with this, thanks in advance
try this it may work.....
foreach (DataTable table in DS.Tables)
{
foreach (DataColumn column in table.Columns)
{
DropDownList list = new DropDownList();
string connectionstring = String.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=""Excel 8.0;HDR=YES;IMEX=1;""", Excelpath);
string query1 = String.Format("select * from [{0}]", DDlist.SelectedItem.Text);
using (OleDbConnection conn1 = new OleDbConnection(connectionstring))
{
OleDbCommand odc1 = new OleDbCommand(query1, conn1);
conn1.Open();
DataTable dte = null;
DataSet ds = new DataSet();
dte = conn1.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = odc1;
objAdapter1.Fill(ds, "xldata");
for (int i = 0; i < ds.Tables[0].Columns.Count; i++)
{
list.Items.Add(ds.Tables[0].Columns[i].ColumnName.ToString());
}
conn1.Close();
}
I think you are not passing Connection to OleDBCommand. So try,
OleDbCommand odc1 = new OleDbCommand(query1, conn1);
The OleDbCommand class has two main parameters to be passed for a proper execution. That are Query and connection object. In your code you are passing the connection, but it is placed inside the String.Format(), so place it outside. See the code below....
OleDbCommand odc1 = new OleDbCommand(string.Format(query1, conn1));
TO
OleDbCommand odc1 = new OleDbCommand(query1, conn1);

i want to use data reader & update statement at same time

here is code
String[] month=new String[12]{"January","February","March","April","May","June","July","August","September","Octomber","November","December"};
int day = DateTime.Now.Day;
int mon= DateTime.Now.Month;
mon = mon - 1; //because month array is with 0
Label1.Text = day.ToString();
if (day==21)
{
int j = 1;
SqlCommand cmd1 = new SqlCommand();
cmd1.Connection = MyConn;
cmd1.CommandText = "SELECT No_of_times,Dustbin_no from mounthly_data";
SqlDataReader MyReader = cmd1.ExecuteReader();
while (MyReader.Read())
{
String a = MyReader["No_of_times"].ToString();
String b = MyReader["Dustbin_no"].ToString();
SqlCommand cmd = new SqlCommand();
cmd.Connection = MyConn;
cmd.CommandText = "update Yearly_data set [" + month[mon] + "]='"+a+"' where Dustbin_no='"+b+"'"; //just see ["+month[mon+"] it's imp
i = cmd.ExecuteNonQuery();
}
MyReader.Close();
}
i got error as
There is already an open DataReader associated with this Command which must be closed first.
I think you should give us the rest of the code above this code block because I'm not sure how a ExecuteNonQuery is using up a datareader. But from what I can gather, what you probably want is to open two separate connections. Only one datareader can be open per connection at a time. Either you use two separate connections or you could maybe use a datatable/dataset for the result of both your queries.
EDIT: From the rest of your code, yes, using two connections would be the simplest answer. When a reader is open, the connection associated with it is dedicated to the command that is used, thus no other command can use that connection.
I would recommend using a DataTable as this OLEDB example shows:
public static void TrySomethingLikeThis()
{
try
{
using (OleDbConnection con = new OleDbConnection())
{
con.ConnectionString = Users.GetConnectionString();
con.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM Customers";
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
foreach (DataRow row in dt.AsEnumerable())
{
cmd.CommandText = "UPDATE Customers SET CustomerName='Ronnie' WHERE ID = 4";
cmd.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}

Resources