I am trying to read an excel sheet using this code
Dictionary<string, DataTable> tables = new Dictionary<string, DataTable>();//Microsoft.Jet.OLEDB.4.0
string sConnection = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0;HDR=yes'", filePath);
OleDbConnection oleExcelConnection = new OleDbConnection(sConnection);
foreach(string sheet in Sheets)
{
DataTable dt = GetDataTable("SELECT * from [" + sheet + "$]", sConnection);
tables.Add(sheet, dt);
}
After I run it got this exception The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.
and I downloaded the component from here 'https://www.microsoft.com/en-us/download/confirmation.aspx?id=23734'
and worked correctly but when I deploy it it doesn't work
anyone can help ?
Please use execlDatareader for nugget package and use this code .Please change path to user file location.
execldatareader work everywhere but ole db must be installed on machine if u goes live with ole db can give u error.
string path1 = Path.Combine(HttpContext.Server.MapPath("~/App_Data/" + sessionManagement.GetUserId()), Path.GetFileName(model.FileName));
FileStream stream = System.IO.File.Open(path1, FileMode.Open, FileAccess.Read);
IExcelDataReader reader = null;
DataSet result = new DataSet();
try
{
if (path1.EndsWith(".xls"))
{
reader = ExcelReaderFactory.CreateBinaryReader(stream);
reader.IsFirstRowAsColumnNames = true;
}
if (path1.EndsWith(".xlsx"))
{
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
reader.IsFirstRowAsColumnNames = true;
}
result = reader.AsDataSet();
reader.Close();
}
catch (Exception ex)
{
Dispose();
}
DataTable dt = result.Tables[0];
Your MS ACE driver version (x86 / x64) must match targeted platform of your VS solution. Click on Project menu>Properties. Select "Build" tab. On your screen, locate a.combobox placed immediate right of label [Platform target:].change value of combobox from "Any CPU" to x86 or x64 whichever version you have and you will get rid of that error.
Related
The program i got is able to load CSV and Excel files in to a datagridview.
This works perfectly fine except the CSV files retain old data.
For example, the CSV file has 30 values. i load the data in to the datagridview and it works fine.
I close the application and i then edit the CSV file removing 26 of the rows. The next time i open the application and load the file it still get's the version with 30 values even tho that file no longer exists.
To be clear, i open and edit the file in Notepad and it works as intended, but even after editing it in notepad my Winform application seems to load the previous version. Even if i rename the file it still takes the data that should no longer exist. Even after completely restarting the PC the file still retains data that should not exist.
BUT! If i move the file to a different folder (add new folder and just throw it in there) it does load the new data...
EDIT:
It seems that it is actually loading all CSV files in the folder. (including older versions)
what could cause this problem? Seeing the Excel files are not experiencing this problem.
The code used:
private void OpenExcel()
{
OpenFileDialog openFileDialog1 = new OpenFileDialog
{
InitialDirectory = #"C:\",
Title = "Browse Text Files",
CheckFileExists = true,
CheckPathExists = true,
DefaultExt = "txt",
FilterIndex = 2,
RestoreDirectory = true,
ReadOnlyChecked = true,
ShowReadOnly = true,
Filter = "Excel Worksheets|*.csv"
};
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
FileLocation = openFileDialog1.FileName;
GetExcelSheetNames(openFileDialog1.FileName);
MyConnection = new OleDbConnection(connString);
MyCommand = new OleDbDataAdapter("select * from [" + SheetName + "]", MyConnection);
MyCommand.TableMappings.Add("Table", "TestTable");
Datatable_Temp = new DataTable();
MyCommand.Fill(Datatable_Temp);
MyConnection.Close();
}
else
{
Canceled = true;
}
}
private string GetExcelSheetNames(string excelFile)
{
OleDbConnection objConn = null;
DataTable dt = null;
string CSVOrNot = excelFile.Substring(excelFile.Length - 3);
try
{
// Connection String.
if (CSVOrNot == "csv")
{
connString = string.Format(#"Provider=Microsoft.Jet.OleDb.4.0; Data Source={0};Extended Properties=""Text;HDR=YES;FMT=Delimited""", Path.GetDirectoryName(excelFile));
}
else
{
connString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" + excelFile + ";Extended Properties=Excel 12.0;";
}
// Create connection object by using the preceding connection string.
objConn = new OleDbConnection(connString);
// Open connection with the database.
objConn.Open();
// Get the data table containg the schema guid.
dt = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
MessageBox.Show("No Data Found");
return null;
}
SheetName = dt.Rows[0]["TABLE_NAME"].ToString();
return SheetName;
}
catch
{
return null;
}
finally
{
// Clean up.
if (objConn != null)
{
objConn.Close();
objConn.Dispose();
}
if (dt != null)
{
dt.Dispose();
}
}
}
i Found the issue, it was different then i thought.
Seeing older versions of the file were also in the folder i didn't notice that it wasn't taking an older version of itself but it was simply merging all CSV files in to the output.
I searched for this instead and found the following post:
c# reading csv file gives not a valid path
i added an if clause to see if the file is a csv file and then use the following:
Because the difference between opening an Excel or a CSV file is is that the Excel file asked for path and file name while CSV only wants the path and later on a query to select the file...a bit odd but ok.
MyCommand = new OleDbDataAdapter("SELECT * FROM [" + Path.GetFileName(openFileDialog1.FileName) + "]", MyConnection);
We have an application where the data in Excel file (present in shared path) moves to Database. In case of any error, the files moves to error folder by writing the error in a log file.It uses a windows service for the operation.
Sometimes the file doesn't have any error still moves to error folder by writing log External table is not in the expected format. But the same file uploading again for once or multiple times, its moving to Database without any errors.
The windows service, DB and shared path are present in XP Server. Application was running fine all these years. But in the recent days, above mentioned problem is occurring for almost every file.
We have installed Microsoft 2003, 2007,2012 office components and access engines too. But still the issue still persists.
I am mentioning the Windows service code below. Pls help. Thanks in advance.
using System.IO;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Data.Common;
namespace Impexp_Service
{
public partial class Service1 : ServiceBase
{
System.Timers.Timer T1 = new System.Timers.Timer();
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
///start
///
{
SqlConnection strconnection = new SqlConnection();
strconnection.ConnectionString = #"Data Source=XXXXXX;Initial Catalog=XXXX;User ID=XX;Password=XXXXXX;";
strconnection.Open();
// To get the all files placed at the shared path
DirectoryInfo directory = new DirectoryInfo(#"D:\Impexp\Data\");
FileInfo[] files = directory.GetFiles("*.xlsx");
foreach (var f in files)
{
string path = f.FullName;
// TO establish connection to the excel sheet
string excelConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1\";";
//Create Connection to Excel work book
OleDbConnection excelConnection = new OleDbConnection(excelConnectionString);
excelConnection.Open();
//Create OleDbCommand to fetch data from Excel
OleDbCommand cmd = new OleDbCommand("Select * from [Report$]", excelConnection);
DbDataReader dr = cmd.ExecuteReader();
// OleDbDataReader dReader;
// dReader = cmd.ExecuteReader();
SqlBulkCopy sqlBulk = new SqlBulkCopy(strconnection);
//Give your Destination table name
sqlBulk.DestinationTableName = "imp_master_test";
sqlBulk.WriteToServer(dr);
excelConnection.Close();
File.Delete(path);
// To move error files to the error folder
/// end
T1.Interval = 20000;
T1.Enabled = true;
T1.Start();
T1.Elapsed += new System.Timers.ElapsedEventHandler(T1_Elapsed);
}
}
}
void T1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
T1.Enabled = false;
try
{
SqlConnection strconnection = new SqlConnection();
strconnection.ConnectionString = #"Data Source=10.91.XXXXXX;Initial Catalog=XXXXX;User ID=XXXXX;Password=XXXXX;";
strconnection.Open();
// To get the all files placed at the shared path
DirectoryInfo directory = new DirectoryInfo(#"D:\Impexp\Data\");
FileInfo[] files = directory.GetFiles("*.xlsx");
foreach (var f in files)
{
string path = f.FullName;
// TO establish connection to the excel sheet
string excelConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1\";";
//Create Connection to Excel work book
OleDbConnection excelConnection = new OleDbConnection(excelConnectionString);
try
{
excelConnection.Open();
//Create OleDbCommand to fetch data from Excel
OleDbCommand cmd = new OleDbCommand("Select * from [Report$]", excelConnection);
DbDataReader dr = cmd.ExecuteReader();
// OleDbDataReader dReader;
// dReader = cmd.ExecuteReader();
SqlBulkCopy sqlBulk = new SqlBulkCopy(strconnection);
//Give your Destination table name
sqlBulk.DestinationTableName = "imp_master_prod";
sqlBulk.WriteToServer(dr);
excelConnection.Close();
File.Delete(path);
}
// To move error files to the error folder
catch (Exception exp)
{
excelConnection.Close();
File.Move(path, Path.Combine(#"D:\Impexp\error\", f.Name));
string path1 = #"D:\Impexp\error\error.txt";
if (File.Exists(path1))
{
// Create a file to write to.
using (StreamWriter sw = File.AppendText(path1))
{
sw.WriteLine("File : " + path + " : " + exp.Message);
sw.Flush();
}
}
T1.Enabled = true;
T1.Start();
}
}
strconnection.Close();
// End of TRY 1
}
catch (UnauthorizedAccessException UAEx)
{
string path1 = #"D:\Impexp\error\error.txt";
if (File.Exists(path1))
{
// Create a file to write to.
using (StreamWriter sw = File.AppendText(path1))
{
sw.WriteLine(UAEx.Message);
sw.Flush();
}
}
T1.Enabled = true;
T1.Start();
}
catch (PathTooLongException PathEx)
{
string path1 = #"D:\Impexp\error\error.txt";
if (File.Exists(path1))
{
// Create a file to write to.
using (StreamWriter sw = File.AppendText(path1))
{
sw.WriteLine(PathEx.Message);
sw.Flush();
}
}
T1.Enabled = true;
T1.Start();
}
T1.Enabled = true;
T1.Start();
}
protected override void OnStop()
{
}
}
}
I did some searching regarding the OLEDB coms and newer versions of Excel. It seems as though a great many people are having compatibility issues with them.
Unfortunately, it doesn't look like Microsoft is giving this any attention. Microsoft announced the depreciation of OLEDB functionality many years ago, and they have stopped adding any kind of internal support in their Office products and SQL servers. In fact,
The official shutdown date for MSAccess Web Apps and Web Databases was April 2018. That being the case, an update to the server, the client version of windows, or the client version of Excel may have triggered this, and it doesn't look like there is going to be a fix. I myself have started using 3rd party packages (free ones are available) to handle the interop with office products because I was tired of banging my head against the wall to create workarounds. Honestly, I don't know why Access still exists if they are taking away the ability to programmatically connect to an Access database.
I know this doesn't fix your problem, but it's better to face the truth and move on than to try to fix something that isn't going to fix.
Looking at this question, this appears to be an issue with reading the excel file, not the SQL table. Try changing the Excel connection string.
string excelConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1\";";
to
string excelConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=Excel 12.0;HDR=Yes;IMEX=1\";
Also, looking at another answer, the root cause could be uploading newer versions of excel.
Are you using an Excel 2007 file with a connection string that uses: Microsoft.Jet.OLEDB.4.0 and Extended Properties=Excel 8.0?
You can change the string to some other as below:
public static string path = #"C:\src\RedirectApplication\RedirectApplication\301s.xlsx";
public static string connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=Excel 12.0;";
OR
Change the connection string from the link below:
http://www.connectionstrings.com/excel-2007
I am using a function in order to open an .xls file with multiple worksheets and copy the entire content into a .csv file.
Everything works just fine on my local machine: no exceptions, no errors etc.
But when I am running it on windows server 2012R I am getting an exception when the connection is opened.
Here is the code where I am trying to open an OleDB connection and then query through the file:
static void ConvertExcelToCsv(string excelFilePath, string csvOutputFile, int worksheetNumber)
{
// connection string
var cnnStr = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelFilePath + ";Extended Properties=\"Excel 8.0;HDR=no;Format=xls\"");
var cnn = new OleDbConnection(cnnStr);
// get schema, then data
var dt = new DataTable();
try
{
cnn.Open();
var schemaTable = cnn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (schemaTable.Rows.Count < worksheetNumber) throw new ArgumentException("The worksheet number provided cannot be found in the spreadsheet");
string worksheet = schemaTable.Rows[worksheetNumber - 1]["table_name"].ToString().Replace("'", "");
string sql = String.Format("select * from [{0}]", worksheet);
var da = new OleDbDataAdapter(sql, cnn);
da.Fill(dt);
....
The excelFilePath is my source excel file (.xls) and csvOutputFile is the file were the content is going to be passed to.
Does anyone has any ideas why I am getting this exception??
I need this code C# working for files excel 2003 and 2007 version.
I can't get this C# code working to convert excel file (xls) on csv file.
If try with excel file extension xlsx it's all ok but if try with extension xls I have error in this line:
result.Tables[0].TableName.ToString();
My code below, what's wrong?
code-behind
FileUploadControl.SaveAs(Server.MapPath("/public/") + filename);
System.IO.FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read);
Excel.IExcelDataReader excelReader = Excel.ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet();
excelReader.Close();
result.Tables[0].TableName.ToString();
string csvData = "";
int row_no = 0;
int ind = 0;
while (row_no < result.Tables[ind].Rows.Count)
{
for (int i = 0; i < result.Tables[ind].Columns.Count; i++)
{
csvData += result.Tables[ind].Rows[row_no][i].ToString() + ",";
}
row_no++;
csvData += "\n";
}
keys = GetUniqueKey(8).ToUpper();
output = System.Web.HttpContext.Current.Server.MapPath("/public/target_" + keys.ToString() + ".csv");
StreamWriter csv = new StreamWriter(#output, false);
csv.Write(csvData);
csv.Close();
Excel can be of two types:
Binary - Excel 2003 and older - xls
Zip - based on Open Office XML standards - Excel 2007 onwards - xlsx
You should try to use following for older excel format files:
ExcelReaderFactory.CreateBinaryReader(stream);
Use any Xls to Xslx conversation tool. You can try Aspose libraries. I think it's licensed but you can try trail version.
You can do all other conversions as well using these libraries.
Here's how I do it - OLEDB - get the first sheet name, and remove all empty rows. Replace //whatever you need to do with your logic.
//Your Method signature
{
//create connection string
var connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path +
";Extended Properties='Excel 12.0;HDR=Yes;IMEX=1'";
//process
using (var conn = new OleDbConnection(connStr))
{
conn.Open();
//programatically get the first sheet, whatever it is named.
var sheetName = GetSheetNames(conn)[0].SheetNameOf;
var adapter = new OleDbDataAdapter(String.Format("SELECT * FROM [{0}]", sheetName), connStr);
var ds = new DataSet();
adapter.Fill(ds, "anyNameHere");
var data = ds.Tables["anyNameHere"];
//copy and remove blank lines
var resData = data.Clone();
var filteredData = data.Rows.Cast<DataRow>().Where(
row => !row.ItemArray.All(
field => field is DBNull ||
field == null ||
(String.IsNullOrEmpty(field.ToString().Trim())))
);
filteredData.CopyToDataTable(resData, LoadOption.OverwriteChanges);
var newData = resData.AsEnumerable();
//whatever you need to do
}
public List<SheetName> GetSheetNames(OleDbConnection conn)
{
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
DataTable excelSchema = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
var sheetNames = (from DataRow row in excelSchema.Rows
where !row["TABLE_NAME"].ToString().Contains("FilterDatabase")
select new SheetName { SheetNameOf = row["TABLE_NAME"].ToString() }
).ToList();
conn.Close();
return sheetNames;
}
You can use Aspose.Cells to convert excel file like xls or xlsx into csv format with the following simple code.
string filePath = #"F:\Downloads\source.xlsx";
Workbook workbook = new Workbook(filePath);
workbook.Save("output.csv", SaveFormat.CSV);
Note: I am working as developer evangelist at Aspose.
I have exported the data from database using HttpContext with formatting of table, tr and td. I want to read the same file and convert into datatable.
<add name="Excel03ConString" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='HTML Import;HDR={1};IMEX=1'" />
<add name="Excel03ConString" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='Excel 8.0;HDR={1};IMEX=1'" />
private DataTable GetTableFromExcel()
{
DataTable dt = new DataTable();
try
{
if (exclFileUpload.HasFile)
{
string FileName = Path.GetFileName(exclFileUpload.PostedFile.FileName);
string Extension = Path.GetExtension(exclFileUpload.PostedFile.FileName);
string FolderPath = Server.MapPath(ConfigurationManager.AppSettings["FolderPath"]);
//string NewFileName = string.Format("{0}_{1}", DateTime.Now.ToString().Replace("/", "").Replace(" ", "").Replace(":", ""), FileName);
string FilePath = Path.Combine(string.Format("{0}/{1}", FolderPath, FileName));
exclFileUpload.SaveAs(FilePath);
string conStr = "";
switch (Extension)
{
case ".xls": //Excel 97-03
conStr = ConfigurationManager.ConnectionStrings["Excel03ConString"].ConnectionString;
break;
case ".xlsx": //Excel 07
conStr = ConfigurationManager.ConnectionStrings["Excel07ConString"].ConnectionString;
break;
}
conStr = String.Format(conStr, FilePath, true);
OleDbConnection connExcel = new OleDbConnection(conStr);
OleDbCommand cmdExcel = new OleDbCommand();
OleDbDataAdapter oda = new OleDbDataAdapter();
cmdExcel.Connection = connExcel;
connExcel.Open();
DataTable dtExcelSchema;
dtExcelSchema = connExcel.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string SheetName = dtExcelSchema.Rows[0]["TABLE_NAME"].ToString();
connExcel.Close();
connExcel.Open();
cmdExcel.CommandText = "SELECT * From [" + SheetName + "]";
oda.SelectCommand = cmdExcel;
oda.Fill(dt);
connExcel.Close();
File.Delete(FilePath);
}
}
catch (Exception ex)
{
}
return dt;
}
When using the second connection string I am getting error "External table is not in the expected format on connection.Open()." But when using the first, I am getting error on reading the sheet name.
Please tell me how to read the sheet or, directly, data from Excel.
I think This Third party dll-(ExcellDataReader) may help solve your problem.
FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read);
//1. Reading from a binary Excel file ('97-2003 format; *.xls)
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
//...
//2. Reading from a OpenXml Excel file (2007 format; *.xlsx)
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
//...
//3. DataSet - The result of each spreadsheet will be created in the result.Tables
DataSet result = excelReader.AsDataSet();
//...
//4. DataSet - Create column names from first row
excelReader.IsFirstRowAsColumnNames = true;
DataSet result = excelReader.AsDataSet();
//5. Data Reader methods
while (excelReader.Read())
{
//excelReader.GetInt32(0);
}
//6. Free resources (IExcelDataReader is IDisposable)
excelReader.Close();
I found this online:
C# Excel file OLEDB read HTML IMPORT
Here they say:
Instead of using the sheetname, you must use the page title in the
select statement without the $. SELECT * FROM [HTMLPageTitle]
In that post they also link to this manual, which may come in handy, but is too long to copy here:
http://ewbi.blogs.com/develops/2006/12/reading_html_ta.html
If that doesn't work, I t think you will have to recreate the original excel so it remains an excel file, and not HTML (if that is at all possible in your scenario)
You may be facing this issue due to different reasons. There are different solutions for this one of them is to make your solution debug as x86. Here is how you can change it to x86.
Right click on sloution from Visual studio.
Click configuration Manager
Select x86 from Active solution platform if available
If not available click New and select or type x86 and click ok.
Rebuild solution and run you application.
If this deos not solve your problem you may have to install 32 bit version of office system drivers. Here is a complete article explaining the problem.
After a deep research I found the solution.
First convert the particular Excel file to an html page by using the following code.
File.Move(Server.MapPath("~/Foldername/ExcelName.xls",Path.ChangeExtension(Server.MapPath("~/Foldername/ExcelName.xls"), ".html"));
we have to download HTML string and extract content. tag contains and tags but it may have style properties. So first we have to avoid these style properties and after we can get required content from table.
string url = Server.MapPath("~/FolderName/Excelname.html");
WebClient wc = new WebClient();
string fileContent = wc.DownloadString(url);
Here we have to format HTML tags for avoid style properties.
const string msgFormat = "table[{0}], tr[{1}], td[{2}], a: {3}, b: {4}";
const string table_pattern = "<table.*?>(.*?)</table>";
const string tr_pattern = "<tr.*?>(.*?)</tr>";
const string td_pattern = "<td.*?>(.*?)</td>";
const string a_pattern = "";
const string b_pattern = "<b>(.*?)</b>";
After through looping we can find <tr> and <td> elements. Then we can get content within <td></td> tags by using this method.
private static List<string> GetContents(string input, string pattern)
{
MatchCollection matches = Regex.Matches(input, pattern, RegexOptions.Singleline);
List<string> contents = new List<string>();
foreach (Match match in matches)
contents.Add(match.Value);
return contents;
}
Then we can insert imported records to database by each row.
Reference link here