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)} …
Related
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;"""
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
I'm using an OleDbConnection to create an Excel file:
String bewegungenDateiname = System.IO.Path.ChangeExtension(System.IO.Path.GetTempFileName(), ".xls");
string strConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source="
+ System.IO.Path.GetDirectoryName(bewegungenDateiname) + #"\" + System.IO.Path.GetFileName(bewegungenDateiname)
+ #";Extended Properties='Excel 8.0;HDR=YES'";
using (System.Data.OleDb.OleDbConnection objConn = new System.Data.OleDb.OleDbConnection(strConnectionString))
using (System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand("", objConn))
{
objConn.Open();
cmd.CommandText = "CREATE TABLE [Test] ([MyDecimal] DECIMAL NULL)";
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
Decimal value = 12.34m;
cmd.Parameters.AddWithValue("#P01", value);
cmd.CommandText = "INSERT INTO [Test$] ([MyDecimal]) VALUES (#P01)";
cmd.ExecuteNonQuery();
}
System.Diagnostics.Process.Start(bewegungenDateiname);
Now when Excel 2013 opens the Excel file it will Show:
MyDecimal
1234
So in my case Excel is losing the dot. Now I'm running a german Version of Windows/Office and if I use the following line to add the Parameter it will work:
cmd.Parameters.AddWithValue("#P01", value.ToString());
German localization of numbers uses a colon instead of the dot to separate the fractions from the number value (meaning 12,34 instead of 12.34). So it seems the OleDbConnection uses the wrong culture variant to write the Excel file?
I fear my Version might break with a different Version of Excel or a different locale - is there a way to fix this and get decimal values to Excel without such risks?
I would use some other way to create Excel files, if it is without this flaw.
With Excel 2013 try using the following:
strConnectionString = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=""Excel 12.0;HDR=No;IMEX=1""", _filePath)
I have no idea if it will solve the problem.
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
This is my first attempt to read an Excel 2007 file via ADO.net, and I must be missing something b/c when I try to run the query, I get an exception. When I started looking, it's b/c the table (worksheet) isn't there. Can someone please tell me what I'm doing wrong?
Here is my code:
string cs = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=My File.xlsx;Extended Properties=""Excel 12.0;IMEX=1;""";
using (OleDbConnection con = new OleDbConnection(cs))
{
con.Open();
string query = "SELECT * FROM [Sheet1$]";
OleDbCommand cmd = new OleDbCommand(query, con);
OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
DataTable dt = new DataTable();
DataTable worksheets = con.GetSchema("Tables");
adapter.Fill(dt);
.
.
.
}
Take a look at the accepted answer here
The First Column of the excel file to put in string variable C#?
It works for Excel 2003 but I think it could easily be adapted to work with 2007.