I'm trying to write a class that will read information from an excel file, but for some reason, it will only run exception-free if the file in question is open in excel. Otherwise, the class throws an OleDbException. The code is as follows:
String filename = #"C:\Users\me\Documents\File.xls";
string connString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filename + ";Extended Properties='Excel 8.0;HDR=YES'";
using (OleDbConnection conn = new OleDbConnection(connString))
{
conn.Open();
OleDbCommand selectCommand = new OleDbCommand("select * from [Sheet1$]", conn);
OleDbDataAdapter adapter = new OleDbDataAdapter(selectCommand);
DataTable dt = new DataTable();
adapter.Fill(dt);
int counter = 0;
foreach (DataRow row in dt.Rows)
{
String dataA= row["DataA"].ToString();
String dataB= row["DataB"].ToString();
Console.WriteLine(DataA+ " = " + dataB);
counter++;
if(counter>=40)
break;
}
The error is thrown on conn.Open(), and only occurs when I don't have File.xls open in excel at the same time. Can someone help me fix this? I am not well versed enough with OLEDB to figure out why this is happening. Thanks!
Related
I am building an app to read measurement data (saved as .xls files on our network) from comparators throughout our facility via a Webform. When I query this group of files I only retrieve the headers. My code (pretty standard) will read any other Excel file I can find. I tried to remove a file from the network and save it locally, as well as rename and save it from office 2016. Note - these are .xls files and I can't change that.
** - I just discovered that there are named ranges with the same name as the file. The results I am getting are just the values in the named range and not the data from the workbook.
Here is an example of how they are named (autogenerated) "R87_1RCR0009654S_COIN"
If I rename or remove the named range this works fine.
Is there a way I can change my select statement to read these?
Here is a code sample, not sure there if there is a change I can make here to read these files.
private string Excel03ConString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='Excel 8.0;HDR={1}'";
private string Excel07ConString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 8.0;HDR={1}'";
string conStr, sheetName;
conStr = string.Format(Excel03ConString, info.FullName, "YES");
string fullPathToExcel = info.FullName;
//Get the name of the First Sheet.
using (OleDbConnection con = new OleDbConnection(conStr))
{
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = con;
con.Open();
DataTable dtExcelSchema = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
sheetName = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
con.Close();
}
}
using (OleDbConnection con = new OleDbConnection(conStr))
{
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();
}
}
}
I have an issue that is very similar to a question already posted here but not resolved. This issue is that when my app reads from an excel file (can happen with a CSV too) with oledb and the file is already opened in Excel (not through the app, the user just has it opened separately) a new Excel will open the file in read-only mode. If the file isn't opened at all, no Excel comes up. It happens right when the connection is opened - conn.Open()
Here is a method for reference:
public static DataTable GetDataTableFromExcelSheet(string ExcelFilePath, string SheetName)
{
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ExcelFilePath + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1\"";
string query = "SELECT * from [" + SheetName + "$]";
System.Data.DataTable dt = new System.Data.DataTable();
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
using (OleDbDataAdapter dataAdapter = new OleDbDataAdapter(query, conn))
{
dataAdapter.Fill(dt);
}
conn.Close();
}
return dt;
}
Is there a way I can prevent Excel opening? Or at least not make it visible? (the app doesn't try to run the Excel app anywhere, the class doesn't even have interop)
I am getting list of excel files within specific directory as below
public void GetFilesList()
{
ListFiles = Directory.GetFiles(DefaultDirectory, "*.xlsx", SearchOption.AllDirectories);
foreach (string FilePath in ListFiles)
{
ImportExcel(FilePath);
}
}
then I am trying to add rows from each file within that directory into my datagridview as below
public void ImportExcel(string FilePath)
{
string ConnStr = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + FilePath + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";";
OleDbConnection Conn = new OleDbConnection(ConnStr);
OleDbDataAdapter DA = new OleDbDataAdapter("select * from [Sheet1$]", Conn);
DataTable dt = new DataTable();
if (dataGridView1.Rows.Count == 0)
{
DA.Fill(dt);
dataGridView1.DataSource = dt;
//Calculate record counts
L_Total_Rows.Text = "count: " + dataGridView1.Rows.Count.ToString("n0");
Conn.Close();
}
else
{
foreach (DataRow dr in dt.Rows)
{
dataGridView1.Rows.Add(dr);
dataGridView1.DataSource = dt;
}
}
}
my problem is that it import rows form one excel file only
it wont get into else condition it only get into the if condition then stops importing
another one question anyway to NOT use the sheet name at query [Sheet1$]? I don't know if it is possible the index of sheets ?
can I start importing the excel file form specific row like fourth row of excel file ?
How about you combine your result sets into one data table first:
DataTable dt = new DataTable();
using(OleDbDataAdapter a1 = new OleDbDataAdapter("select * from [Sheet1$]", Conn))
a1.Fill(dt);
using(OleDbDataAdapter a2 = new OleDbDataAdapter("select * from [Sheet1$]", Conn))
a2.Fill(dt);
the issue was solved by moving DataTable dt = new DataTable(); to the beginning of the class because each time I am calling ImportExcel(FilePath) method it will build new datatable so it will delete all old data and create new datatable and changed my method to below
public void ImportExcel(string FilePath)
{
string ConnStr = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + FilePath + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";";
OleDbConnection Conn = new OleDbConnection(ConnStr);
OleDbDataAdapter DA = new OleDbDataAdapter("select * from [Sheet1$]", Conn);
DA.Fill(dt);
DGV_Data.DataSource = dt;
//Calculate record counts
L_Rows_Count.Text = "Count: " + (DGV_Data.Rows.Count - 1).ToString("n0");
Conn.Close();
}
now there is a small problem still annoying me which is it will insert an empty row at datagriview between each imported excel file
public void LoadExcel_Click(object sender, EventArgs e)
{
OpenFileDialog fileDLG = new OpenFileDialog();
fileDLG.Title = "Open Excel File";
fileDLG.Filter = "Excel Files|*.xls;*.xlsx";
fileDLG.InitialDirectory = #"C:\Users\...\Desktop\";
if (fileDLG.ShowDialog() == DialogResult.OK)
{
string filename = System.IO.Path.GetFileName(fileDLG.FileName);
string path = System.IO.Path.GetDirectoryName(fileDLG.FileName);
excelLocationTB.Text = #path + "\\" + filename;
string ExcelFile = #excelLocationTB.Text;
if (!File.Exists(ExcelFile))
MessageBox.Show(String.Format("File {0} does not Exist", ExcelFile));
OleDbConnection theConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ExcelFile + ";Extended Properties=Excel 12.0;");
theConnection.Open();
OleDbDataAdapter theDataAdapter = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", theConnection);
DataSet DS = new DataSet();
theDataAdapter.Fill(DS, "ExcelInfo");
dataGridView1.DataSource = DS.Tables["ExcelInfo"];
formatDataGrid();
MessageBox.Show("Excel File Loaded");
toolStripProgressBar1.Value += 0;
}
}
Ok so I got this code off of Microsoft.
theDataAdapter.Fill(DS, "ExcelInfo");
This is the line that gave me the error.
Basically this code is supposed to use a dialog box to open the file and display it on the form. Whenever I opened an Excel file, it would give me this error. I even tried creating a blank excel file and it still gave me this.
Modified your code. added OleDbCommand to do the query selection. just try.
OleDbConnection theConnection = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Projects\Demo\Demo.xls;Extended Properties=Excel 8.0;");
theConnection.Open();
OleDbCommand theCmd = new OleDbCommand("SELECT * FROM [Sheet1$]", theConnection);
OleDbDataAdapter theDataAdapter = new OleDbDataAdapter(theCmd);
DataSet DS = new DataSet();
theDataAdapter.Fill(DS);
theConnection.Close();
I have seen this error before and it might not have anything to do with your code. The code below works fine, but if you are getting your source that has blocked the file, make sure you right-click the file and go to properties and check unblock. This could be if you are downloading the file from some source etc. A good test is to just open the exported excel file and save it and try again. Or copy the contents into a new excel file.
Again the code below works fine, but when I tried to import without unblocking or going into the file and saving it I was getting the same error. The error message is deceiving.
string excelconString = string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1""", filePath);
string excelQuery = "select col1 from [Sheet1$]";
DataSet ds = new DataSet();
DataTable dt = new DataTable();
using (var excelConn = new OleDbConnection(excelconString))
{
excelConn.Open();
using (var oda = new OleDbDataAdapter(excelQuery, excelConn))
{
oda.Fill(ds);
dt = ds.Tables[0];
}
}
I am trying to find the best way of selecting an excel spreadsheet (xls and xlsx) using a fileupload control and then parsing it with filestream object and then populating a dataset.
This is my code so far which does the job but how it differs is I am saving the excel spreadsheet to a folder in my solution then querying the data using Microsoft ACE OLEDB connection.
protected void btnUpload_Click(object sender, EventArgs e)
{
string connectingString = "";
if (ctrlFileUpload.HasFile)
{
string fileName =
Path.GetFileName(ctrlFileUpload.PostedFile.FileName);
string fileExtension =
Path.GetExtension(ctrlFileUpload.PostedFile.FileName);
//Path.GetExtension(ctrlFileUpload.PostedFile.ContentType);
string fileLocation =
Server.MapPath("~/App_Data/" + fileName);
ctrlFileUpload.SaveAs(fileLocation);
// Check whether file extension is xls or xslx
if (fileExtension == ".xls")
{
connectingString =
"Provider=Microsoft.ACE.OLEDB.4.0;Data Source=" +
fileLocation + ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=2\"";
}
else if (fileExtension == ".xlsx")
{
connectingString =
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" +
fileLocation + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=2\"";
}
// Create OleDb Connection and OleD Command
using (OleDbConnection con = new OleDbConnection(connectingString))
{
try
{
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
OleDbDataAdapter dAdapter = new OleDbDataAdapter(cmd);
//DataTable dtExcelRecords = new DataTable();
DataSet ds = new DataSet();
con.Open();
DataTable dtExcelSheetName = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string getExcelSheetName = dtExcelSheetName.Rows[0]["Table_Name"].ToString();
cmd.CommandText = "Select * FROM [" + getExcelSheetName + "]";
dAdapter.SelectCommand = cmd;
//dAdapter.Fill(dtExcelRecords);
dAdapter.Fill(ds);
//GridView1.DataSource = dtExcelRecords;
//GridView1.DataBind();
}
catch (Exception ex)
{
}
}
}
}
So to summarise I want to read the data in a spreadsheet and then bind it to a dataset but without saving the file to a physical path.
Is there a cleaner way of writing this code that I am missing. Thanks!!
I think it not possible to get data without save file to your server
If you can't save uploded file how can you give Data Source to your oleDbConnection string ??
you can delete file after finish this execution if you don't want to keep the file.
you can also refer this way https://stackoverflow.com/a/12420416/284240