C# get excel worksheets without office unsing OLEDB - excel

I read some of the other thread's about this topic, but it still dosn't work and I don't know why.
There is an exception: 'Microsoft.ACE.OLEDB.12.0'-Provider not registred on local machine. I already installed Database engine for Office 2007 and 2010.
Do you have any ideas?
OS: Win 7 Prof. 64 bit
static void Main(string[] args)
{
OleDbConnection connection = null;
DataTable Sheets = null;
String file = args[0];
String filePath = Path.GetDirectoryName(args[0]);
String connPath = "";
if(Path.GetExtension(file).Equals(".xls"))
connPath = "Provider=Microsoft.Jet.OleDb.4.0; Data Source=" + file + ";Extended Properties=Excel 8.0";
else
connPath = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + file + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1\"";
try
{
connection = new OleDbConnection(connPath);
connection.Open();
Sheets = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
...

Found it. You Need to complile the Project for x86 CPU. Any CPU wonnt work.
Thanks

Related

Got “External table is not in the expected format.” when reading Excel file

I saw several posts talking about the same issues, but none of the solution works for me.
My clients push their Excel (.xlsx) files to a network drive and I am using a program to read the files automatically using following code snippet.
Most of the time, the operations are successful, but there is one client's files always failed with “External table is not in the expected format.” However, if I open the file from Office 2010 in my local machine, then save it, then read it again, the operation will be successful. The only problem is my automation process is broken. I think there must be something wrong in that client's files compare to others, I won't be able to ask that client how to create the files. Is there any options from my side that I can try? Thank you so much in advance!
enter code here
private void Loadfile(string filename)
{
String sql = "Select * from [Sheet1$]";
String constr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filename + ";Extended Properties=Excel 12.0";
using (OleDbConnection objConn = new OleDbConnection(constr))
{
objConn.Open(); //<--Error will occur here
OleDbCommand objCmdSelect = new OleDbCommand(sql, objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
DataSet dsOriginal = new DataSet();
objAdapter1.Fill(dsOriginal);
...
}
}

Allowing VB.NET app to convert Excel Files to Datatable

My VB.NET app currently allows me to convert CSV files to a datatable thanks to the code provided by David in this question I posted: Previous Question
Now I am trying to allow .XLSX files to be imported to a datatable as well. Currently the code looks like this:
Private Function ConvertCSVToDataTable(ByVal path As String) As DataTable
Dim dt As DataTable = New DataTable()
Using con As OleDb.OleDbConnection = New OleDb.OleDbConnection()
Try
If System.IO.Path.GetExtension(path) = ".csv" Then
con.ConnectionString = String.Format("Provider={0};Data Source={1};Extended Properties=""Text;HDR=YES;FMT=Delimited""", "Microsoft.Jet.OLEDB.4.0", IO.Path.GetDirectoryName(path))
ElseIf System.IO.Path.GetExtension(path) = ".xlsx" Then
con.ConnectionString = String.Format("Provider={0};Data Source={1};Extended Properties=""Excel 12.0 XML;HDR=Yes;""", "Microsoft.ACE.OLEDB.12.0", IO.Path.GetDirectoryName(path))
End If
Using cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand("SELECT * FROM " & IO.Path.GetFileName(path), con)
Using da As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(cmd)
con.Open()
da.Fill(dt)
con.Close()
End Using
End Using
Catch ex As Exception
Console.WriteLine(ex.ToString())
Finally
If con IsNot Nothing AndAlso con.State = ConnectionState.Open Then
con.Close()
End If
End Try
End Using
Return dt
End Function
However, when I run the code using the .XLSX file, I get the following error:
{"The Microsoft Office Access database engine cannot open or write to
the file 'C:\Users\XSLXFilePath'. It is already opened exclusively by
another user, or you need permission to view and write its data."}
The file is not open anywhere else to my knowledge. And the app also runs fine when .CSV file is put through it instead. How do I get the app to properly work for .XLSX, or any Excel file format?
I think that the error is that from the connection string and the OLEDB Command:
ConnectionString
You don't have to use IO.Path.GetDirectoryName(path) it returns the directory name, you have to provide the file full path:
con.ConnectionString = String.Format("Provider={0};Data Source={1};Extended Properties=""Excel 12.0 XML;HDR=Yes;""", "Microsoft.ACE.OLEDB.12.0", path)
Refer to this link for excel connectionstring generation function: import data from excel 2003 to dataTable
OLEDB Command
You must provide the Worksheet name in the Command instead of the Filename:
Using cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand("SELECT * FROM [Sheet1$]" , con)
If the Sheet names is dynamic and you have to get the first sheet in the excel file:
Dim dbSchema as DataTable = con.GetOleDbSchemaTable (OleDbSchemaGuid.Tables, null)
Dim firstSheetname as String = dbSchema.Rows(0)("TABLE_NAME").ToString
Using cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand("SELECT * FROM [" & firstSheetname & "]" , con)
References
Reading from excel using oledbcommand
Read and Write Excel Documents Using OLEDB
Use can use the following connection string for .xlsx file.
I have used it and working fine.
P_FIle = ( File Name with path )
P_Con_Str = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & P_File & ";Extended Properties=""Excel 12.0 XML;HDR=Yes;"""

Proper way to get excel sheet names using C# and oledb

I'm trying to figure out why the behavior I'm seeing and the "documented" behavior are different. I've read both of these articles:Read and Write Excel Documents Using OLEDB and Working with MS Excel(xls / xlsx) Using MDAC and Oledb and this is text from the second link.
If you read in the second link it says:
To Retrieve Schema Information of Excel Workbook :
You can get the worksheets that are present in the excel workbook using GetOleDbSchemaTable. Use the following snippet.
DataTable dtSchema = null;
dtSchema = conObj.GetOleDbSchemaTable(
OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
Here dtSchema will hold the list of all workbooks. Say we have two workbooks : wb1, wb2. The above code will return a list of wb1, wb1$,wb2,wb2$. We need to filter out $ elements.
However when I run this code I only get "wb1$ and wb2$". I can easily remove the $ in code but I'm trying to make sure I'm not going to have code that breaks when I put it on a different computers/OS/environment and it behaves as is documented. Can somebody tell my what or if something changed since these were written or if I'm missing some key piece. Something to note this is being developed in VS2015, Windows 7 Pro, and Office 2010 installed.
//Connection String
//string connstring = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties='Excel 8.0;HDR=NO;IMEX=1';"; // Extra blank space cannot appear in Office 2007 and the last version. And we need to pay attention on semicolon.
//string connstring = Provider = Microsoft.JET.OLEDB.4.0; Data Source = " + path + "; Extended Properties = 'Excel 8.0;HDR=NO;IMEX=1'; "; //This connection string is appropriate for Office 2007 and the older version. We can select the most suitable connection string according to Office version or our program.
using (OleDbConnection conn = new OleDbConnection(_connectionString))
{
conn.Open();
//DataTable sheetNames = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); //Get All Sheets Name
DataTable sheetNames = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null); //Get All Sheets Name
// Loop through all Sheets to get data
foreach (DataRow dr in sheetNames.Rows)
{
string sheetName = dr["TABLE_NAME"].ToString();
//if (!sheetName.EndsWith("$"))
// continue;
Debug.Print(sheetName);
}
return sheetNames;
Thanks
dbl

sqlbulkcopy from Excel via ACE.OLEDB truncates text to 255 chars

Pretty straight-forward import using SqlBulkCopy:
string excelConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1;\"";
using (OleDbConnection excelConnection = new OleDbConnection(excelConnectionString))
{
excelConnection.Open();
OleDbCommand cmd = new OleDbCommand("Select " + fileID.ToString() + " as [FileID], * from [Sheet1$] where [Text] IS NOT NULL", excelConnection);
OleDbDataReader dReader = cmd.ExecuteReader();
using (SqlBulkCopy sqlBulk = new SqlBulkCopy(ConfigurationManager.ConnectionStrings["DBConnection"].ConnectionString))
{
sqlBulk.DestinationTableName = "table_name";
sqlBulk.ColumnMappings.Add(0, "FileID");
sqlBulk.ColumnMappings.Add(4, "Author");
sqlBulk.ColumnMappings.Add(3, "Title");
sqlBulk.ColumnMappings.Add(1, "Body");
sqlBulk.ColumnMappings.Add(2, "PublishedDate");
sqlBulk.BulkCopyTimeout = 600;
sqlBulk.WriteToServer(dReader);
}
}
Data goes in, no problem. Except the first column, which is mapped to Body (nvarchar(max)) gets truncated to 255 characters. I looked around, found some references to workaround that involves changing a registry setting. Set value to 0 to force full scan, not just first 8 rows, which is Excel's default, but that didn't help even after reboot. Looking for other ideas. Thank you.
I used ODBC instead of the OLEDB and it doesn't truncate the values
to 255 symbols anymore:
OdbcConnection con = new OdbcConnection(#"Driver={Microsoft Excel Driver
(*.xls)};DBQ=c:\temp\testbook.xls");
OdbcCommand cmd = new OdbcCommand(#"SELECT * FROM [Workbook1$]");
cmd.Connection = con;
OdbcDataAdapter da = new OdbcDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
you can use 2007 format driver to access XLSX files:
.... Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)} …

query for reading data from excel sheet in c#

Thanks Astander for replying to my query
I am here with more detailed query.
string cs = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + #"D:\\sample.xls;" + "Excel 12.0;HDR=YES;";
OleDbConnection Excelcon = new OleDbConnection(cs);
OleDbDataAdapter ad = new OleDbDataAdapter();
ad.SelectCommand = new OleDbCommand("SELECT *FROM [Sheet1$]", Excelcon);
DataTable dt = new DataTable();
ad.Fill(dt);
return dt;
I am getting error at the select statement that :
The Microsoft Office Access database engine could not find the object 'Sheet1$'. Make sure the object exists and that you spell its name and the path name correctly.
Hope someone can help me find a solution.
What worked for me is,
when file was created, it was stored in some specific location. In my case,C:/Documents.
I had manually changed the location to D:
this was what I had written
string connStringExcel = #"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=D:\example.xls;Extended Properties=""Excel 12.0;HDR=YES;""";`
So,the actual path should be
string connStringExcel = #"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=C:\A\Documents\example.xls;Extended Properties=""Excel 12.0;HDR=YES;""";`
So on giving the path of correct location,my query was solved.
Hope it helps someone else too.
// Create connection string variable. Modify the "Data Source"
// parameter as appropriate for your environment.
String sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + Server.MapPath("../ExcelData.xls") + ";" +
"Extended Properties=Excel 8.0;";
// Create connection object by using the preceding connection string.
OleDbConnection objConn = new OleDbConnection(sConnectionString);
// Open connection with the database.
objConn.Open();
// The code to follow uses a SQL SELECT command to display the data from the worksheet.
// Create new OleDbCommand to return data from worksheet.
OleDbCommand objCmdSelect =new OleDbCommand("SELECT * FROM myRange1", objConn);
// Create new OleDbDataAdapter that is used to build a DataSet
// based on the preceding SQL SELECT statement.
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
// Pass the Select command to the adapter.
objAdapter1.SelectCommand = objCmdSelect;
// Create new DataSet to hold information from the worksheet.
DataSet objDataset1 = new DataSet();
// Fill the DataSet with the information from the worksheet.
objAdapter1.Fill(objDataset1, "XLData");
// Bind data to DataGrid control.
DataGrid1.DataSource = objDataset1.Tables[0].DefaultView;
DataGrid1.DataBind();
// Clean up objects.
objConn.Close();
ref to thisLink

Resources