C# Error reading Excel file with OleDbDataAdapter - c#

I'm trying to read an ".xlsx" file using an OleDbDataAdapter. Please read until the end of the post before answering. Here is the code I'm using:
private DataTable ExtractDataFromFile(string fileName)
{
DataTable sheetData = new DataTable();
using (OleDbConnection conn = this.returnConnection(fileName))
{
try{
conn.Open();
OleDbDataAdapter sheetAdapter = new OleDbDataAdapter("select * from [Sheet1$]", conn);
sheetAdapter.Fill(sheetData);
}
catch(Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
}
}
return sheetData;
}
private OleDbConnection returnConnection(string fileName)
{
return new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties=Excel 12.0;");
}
But I'm getting a peculiar error. The Excel files I have to query have been given to me by a client, and I get the following error when I try to open them
External table is not in the expected format
Here is the catch:
I've noticed that if I open one of the Excel files and manually save it once and close the file, then I can query the file with my program!

Are you sure, you have create the xlsx file using Microsoft office? This file could be an open xml document, but maybe not created by MS Office, so the MS oledbadapter cannot read it. If you open and save it then it probably converts it to MS version of open xml and then oledbadapter can read it.
You can look into DocumentFormat.OpenXml to read xlsx files.

Related

How to import different format Excel files into a SQL Server database

I have a requirement where I need to import different Excel files of different suppliers into a SQL Server database. I have created SSRS package for which I need to manually put data in my format, which I have created and then import using SSRS package. What would be the best and fastest way to import different format Excels into SQL Server database using C#?
Break this down into two steps:
1) Save the file somewhere - it's very common to see this:
string saveFolder = #"C:\temp\uploads"; //Pick a folder on your machine to store the uploaded files
string filePath = Path.Combine(saveFolder, FileUpload1.FileName);
FileUpload1.SaveAs(filePath);
Now you have your file locally and the real work can be done.
2) Get the data from the file. Your code should work as is but you can simply write your connection string this way:
string excelConnString = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties="Excel 12.0";", filePath);
You can then think about deleting the file you've just uploaded and imported.
To provide a more concrete example, we can refactor your code into two methods:
private void SaveFileToDatabase(string filePath)
{
String strConnection = "Data Source=.\\SQLEXPRESS;AttachDbFilename='C:\\Users\\Hemant\\documents\\visual studio 2010\\Projects\\CRMdata\\CRMdata\\App_Data\\Database1.mdf';Integrated Security=True;User Instance=True";
String excelConnString = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0\"", filePath);
//Create Connection to Excel work book
using (OleDbConnection excelConnection = new OleDbConnection(excelConnString))
{
//Create OleDbCommand to fetch data from Excel
using (OleDbCommand cmd = new OleDbCommand("Select [ID],[Name],[Designation] from [Sheet1$]", excelConnection))
{
excelConnection.Open();
using (OleDbDataReader dReader = cmd.ExecuteReader())
{
using(SqlBulkCopy sqlBulk = new SqlBulkCopy(strConnection))
{
//Give your Destination table name
sqlBulk.DestinationTableName = "Excel_table";
sqlBulk.WriteToServer(dReader);
}
}
}
}
}
private string GetLocalFilePath(string saveDirectory, FileUpload fileUploadControl)
{
string filePath = Path.Combine(saveDirectory, fileUploadControl.FileName);
fileUploadControl.SaveAs(filePath);
return filePath;
}
You could simply then call SaveFileToDatabase(GetLocalFilePath(#"C:\temp\uploads", FileUpload1));
Consider reviewing the other Extended Properties for your Excel connection string. They come in useful!
Other improvements you might want to make include putting your Sql Database connection string into config, and adding proper exception handling. Please consider this example for demonstration only!

Converting ibfs (Downloaded Excel files from websites) files to .xls/.xlsx file format without installing Office using C# Asp.net Web application

I have a requirement where I need to format input files from different resources. My application receives input (xls/xlsx/ibfs) files through file upload and performs condition checks and generates formatted output in .xlsx file format. All my input files are reports generated by different online public data reporting websites. When I downloaded in excel format some websites are producing in “WFServlet.ibfs” file formats.
This is not a duplicate post. I tried different approaches and followed suggestions here and tried several ways but didn't solve my issue. Sorry for the long post. I want to have seniors advise or help to solve this problem.
I’m able to handle xls and xlsx file formats with using C# OLEDB ACE engine. It’s working perfectly fine in my local machine and also in my locally hosted IIS server. But when I upload .ibfs file formats I’m getting issues.
Sample input
Here I'm posting my most effective two different approaches:
Approach 1 (Using Microsoft Office Interop)
Approach 2 (Using third party EPPlus library)
1. Approach 1 (Using Microsoft Office Interop):
In this approach, I used Microsoft Interop dlls. Initially before conversion I changed the extension of .ibfs to .xls and then I used Microsoft Interop to convert xls into xlsx file format. In this approach its working fine in my local machine. But it’s not working in my local IIS server (In my local IIS server I’m able change the extension from .ibfs to .xls but after that it’s not creating xlsx file from xls). I added dlls of Office12 "Microsoft.Office.Interop.Excel.dll" and "Office.dll" to my project reference.
But with this approach I may have a problem in future. Currently Office is installed in my local machine, but when we move code to the server there we don’t have Office installed and client don’t want to install Office in the server. I'm not sure whether it will work in the server with the same dll's without installing the office.
Below is the code:
Step 1: Change extention from .ibs to .xls and call conversion method, if user uploaded file is .ibfs file type
string path ="C:\\testinput\\";
string extension = Path.GetExtension(InputFile.FileName); // get the extension of user upload file
string fileName = "testFile"+ extension; // make a new name to assign to the user uplaoded file
InputFile.SaveAs(path + fileName); // save the user uploaded file into the testinput folder with testFile file name
inputFileWithPath = path + fileName; // copy the path of saved file "C:\\testinput\\testFile+extenstion"
newPath = inputFileWithPath; // used if input file is of .ibfs or .xls extn
if (extension.Equals(".IBFS") || extension.Equals(".ibfs"))
{
//input user uploaded file extension is .ibfs , If file already exist in the upload folder path then delete the old one before File.Move
if (File.Exists(newPath + ".ibfs"))
{
File.Delete(newPath);
}
else
{
newPath = Path.ChangeExtension(inputFileWithPath, ".xls"); // chnage the file extension from .ibfs to .xls
File.Move(inputFileWithPath, newPath); // move the new file .xls to testinput path
inputFileWithPath = excelComm.convertExel(newPath); // convert the .xls file into .xlsx file format
}
}
Step 2 Now conversion logic from .xls to xlsx using Interop
public string convertExel(string FilePath)
{
string path = "";
var app = new Microsoft.Office.Interop.Excel.Application();
try
{
if (File.Exists(FilePath + "x")) // check if file with .xlsx is already exist, if exist delete it
{ File.Delete(FilePath + "x"); }
else
{
var wb = app.Workbooks.Open(FilePath);
wb.SaveAs(Filename: FilePath + "x", FileFormat: Microsoft.Office.Interop.Excel.XlFileFormat.xlOpenXMLWorkbook);
path = FilePath + "x";
wb.Close();
}
} // end of try
catch (Exception ex)
{
string errorMsg = "";
CatchException(ex, errorMsg);
}
return path;
}
2. Approach 2 (Using third party EPPlus library):
I downloaded EPPlus.dll and added to my project reference. I used below code. Which is basically changes the extension of .ibfs to xls and calls the convertExcel methods, where it converts the xls into dataset from that dataset , I copied data table into to the workbook sheet and saved it as .xlsx file. But it is not working.
Below is the code sample
Step 1: Change extension from .ibs to .xls and call conversion method, if user uploaded file is .ibfs file type
Step 1 is same as above as mentioned in Approach 1.
Step 2: Conversion from .xls to xlsx using EPPlus library. For this I followed solution from C# - convert xls file to xlsx without office components
public string convertExel(string FilePath)
{
string path = "";
try
{
if (File.Exists(FilePath + "x"))// check if file with .xlsx is already exist, if exist delete it
{File.Delete(FilePath + "x");}
else
{
string fileName = Path.GetFileNameWithoutExtension(FilePath);
string filePathXlsx = "C:\\testinput\\"+ fileName + ".xlsx ";
using (ExcelPackage epackage = new ExcelPackage())
{
ExcelWorksheet excel = epackage.Workbook.Worksheets.Add("Sheet1");
DataSet ds = ReadExcelFile(FilePath); // Causing Error HERE
DataTable dtbl = ds.Tables[0];
excel.Cells["A1"].LoadFromDataTable(dtbl, true);
System.IO.FileInfo file = new System.IO.FileInfo(filePathXlsx);
epackage.SaveAs(file);
path = filePathXlsx;
} // end of using
}// end of else
}//end of try
catch (Exception ex)
{
string errorMsg = "";
CatchException(ex, errorMsg);
}
return path;
} // end of method
// generate dataset from excel file
private static DataSet ReadExcelFile(string FilePath)
{
string constr = "";
DataSet ds = new DataSet();
string extension = Path.GetExtension(FilePath);
if (extension.Equals(".xls", StringComparison.CurrentCultureIgnoreCase))//Checking for the extentions, if XLS connect using ACE OleDB
{
constr = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + FilePath + ";Extended Properties=\"Excel 8.0;IMEX=1;HDR=YES\"";
}
//Use ACE OleDb if xlsx extention
else if (extension.Equals(".xlsx", StringComparison.CurrentCultureIgnoreCase))
{
constr = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;IMEX=1;HDR=YES\"", FilePath);
}
else
{
constr = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + FilePath + ";Extended Properties=\"Excel 8.0;IMEX=1;HDR=YES\"";
}
using (OleDbConnection conn = new OleDbConnection(constr))
{
conn.Open(); // causing error HERE
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
DataTable dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); // Get all Sheets in Excel File
foreach (DataRow dr in dtSheet.Rows) // Loop through all Sheets to get data
{
string sheetName = dr["TABLE_NAME"].ToString();
cmd.CommandText = "SELECT * FROM [" + sheetName + "]"; // Get all rows from the Sheet
DataTable dt = new DataTable();
dt.TableName = sheetName;
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
ds.Tables.Add(dt);
} // end of for
cmd = null;
conn.Close();
} // end of using
return ds;
}
Its giving me error “System.Data.OleDb.OleDbException (0x80004005): External table is not in the expected format.
at System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, OleDbConnection connection)”
Its changing the extension from .ibfs to xls but after that its not generating any xlsx file. I tried with different connection strings, ACE, Jet engines with Xml format, HTML import, with single quotes and double quotes but nothing is working. Is it problem with the downloaded web excel file in any specific format which is not supported by OLEDB? I'm not sure how to handle such type of specific formats.
I appreciate if any one can give me any idea how I can solve the problem with the 'ibfs' file formats.
My Latest update: I tried with the Spire.XLS but it didn't work with '.ibfs' file formats. Its just working fine with xls and xlsx formats.
Just one request, please only suggest open-source dll's. I can't install any software in client machine (server). I have only option to use open-source libraries like EPPlus or anything supported by just dll's without any installation. Thank you.
Try replacing Extended Properties=\"Excel 12.0;IMEX=1;HDR=YES\" with Extended Properties=\"Excel 12.0 Xml;IMEX=1;HDR=YES\" in
//Use ACE OleDb if xlsx extention
else if (extension.Equals(".xlsx", StringComparison.CurrentCultureIgnoreCase))
{
constr = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;IMEX=1;HDR=YES\"", FilePath);
}
If IBFS files are Excel files, you can try using Essential XlsIO. I couldn't find any IBFS files to check with.
The whole suite of controls is available for free (commercial applications also) through the community license program if you qualify. The community license is the full product with no limitations or watermarks.
Note: I work for Syncfusion.

How to change the odc connection file paths in excel using c#

I have an excel file (embedded resource in a c# project) with multiple worksheets which get their data from SQL Server using connection information from odc file. I want to update the excel file to look for these odc files in a specific folder which I specify, so need to update the excel odc connection file path accordingly. How can I do this via c#, so for example, if I output the odc file to "d:\odcFiles\abc.odc", then I want to update the excel connection path to "d\odcFiles\abc.odc". Likewise for all other odc files. Any help would be very much appreciated.
The highlighted part is what I am referring to (location of the odc file), which I would like to change on the fly via c#:
One way, probably the simplest way, would be to edit the registry directly.
[Update]
I don't know about ODBC. But I've used this code to dynamically access excel files. It was for an asp.net app but the important DB stuff is there.
// using System.Data.OleDb
OleDbConnection ExcelConection = null;
OleDbCommand ExcelCommand = null;
OleDbDataReader ExcelReader = null;
OleDbConnectionStringBuilder OleStringBuilder = null;
try
{
OleStringBuilder =
new OleDbConnectionStringBuilder(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\MyExcel.xls;Extended Properties='Excel 8.0;HDR=Yes;IMEX=1';");
OleStringBuilder.DataSource = MapPath(#"~\App_Datav\MyExcelWorksheet.xls");
ExcelConection = new OleDbConnection();
ExcelConection.ConnectionString = OleStringBuilder.ConnectionString;
ExcelCommand = new OleDbCommand();
ExcelCommand.Connection = ExcelConection;
ExcelCommand.CommandText = "Select * From [Sheet1$]";
ExcelConection.Open();
ExcelReader = ExcelCommand.ExecuteReader();
GridView1.DataSource = ExcelReader;
GridView1.DataBind();
}
catch (Exception Args)
{
LabelErrorMsg.Text = "Could not open Excel file: " + Args.Message;
}
finally
{
if (ExcelCommand != null)
ExcelCommand.Dispose();
if (ExcelReader != null)
ExcelReader.Dispose();
if (ExcelConection != null)
ExcelConection.Dispose();
}

can not open excel file in c# for different format extension error

can not open excel file in c# because The file you are trying to open in a different format than specified file extension. Verify that the file is not corrupted and is from a trusted source before opening the file. Do you want to open the file now?
private void button1_Click(object sender, EventArgs e)
{
string fileName = Directory.GetCurrentDirectory();
fileName += "\\" + textBox1.Text + ".xls";
var connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties=\"Excel 12.0;IMEX=1;HDR=NO;TypeGuessRows=0;ImportMixedTypes=Text\"";
var conn = new OleDbConnection(connectionString);
conn.Open();
var sheets = conn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
var cmd = conn.CreateCommand();
/////////////////////// sheet 1
cmd.CommandText = "SELECT * FROM [" + sheets.Rows[0]["TABLE_NAME"].ToString() + "] ";
var adapter = new OleDbDataAdapter(cmd);
var ds = new DataSet();
adapter.Fill(ds);
DataTable dt = new DataTable();
dt = ds.Tables[0];
}
This is because the file is actually basically just a CSV file with an XLS extension to make it open in Excel.
it happens in new versions of Excel. Older ones will happily export them.
See this Microsoft doc for more information:
http://support.microsoft.com/kb/948615
One option is simply to rename the file name to .csv, and keep the user interface as saying that it is an Excel file (Excel is quite happy to read csv files). Given that Windows tends to hide the file extension, this seems like a fairly attractive option.
EDIT
"External table is not in the expected format." typically occurs when trying to use an Excel 2007 file with a connection string that uses: Microsoft.Jet.OLEDB.4.0 and Extended Properties=Excel 8.0
Go through:
Excel "External table is not in the expected format."
Hope its helpful.

Reading and checking .csv file and then uploading it to the sql server 2008 r2

I have got a page in which there is a file upload option where I have to upload/import the csv file. What I want to do is to check if the correct format of file is uploaded for instance if any other than csv file is uploaded, the system should give an error message. Also what I need to do is to check certain fields of the csv file for instance there are some mandatory fields in the csv file which should be there like name , postcode, How can I check that these fields are not empty . After performing these task, the system should automatically upload the csv file onto the sql sever 2008. Any ideas or tutorial ... will be highly appreciated.
Check out this thread:
Parsing CSV files in C#, with header
I believe this will let you extract it as you want and then easily shove it into a table in SQL Server.
try using Oledb. this codesnippet helps you read your csv file into a datatable which should be pretty easy to dump to a database.
public static DataTable ParseCSV(string path)
{
if (!File.Exists(path))
return null;
string full = Path.GetFullPath(path);
string file = Path.GetFileName(full);
string dir = Path.GetDirectoryName(full);
//create the "database" connection string
string connString = "Provider=Microsoft.Jet.OLEDB.4.0;"
+ "Data Source=\"" + dir + "\\\";"
+ "Extended Properties=\"text;HDR=No;FMT=Delimited\"";
//create the database query
string query = "SELECT * FROM " + file;
//create a DataTable to hold the query results
DataTable dTable = new DataTable();
//create an OleDbDataAdapter to execute the query
OleDbDataAdapter dAdapter = new OleDbDataAdapter(query, connString);
try
{
//fill the DataTable
dAdapter.Fill(dTable);
}
catch (InvalidOperationException /*e*/)
{ }
dAdapter.Dispose();
return dTable;
}
Check out the fast CSV reader over at codeproject.com
Another option would be to use SSIS.

Categories

Resources