Data not fills correctly in DataTable using OleDbDataAdapter - c#

When I try to import excel sheet, it does not fetches some integer values. I am using DevExpress GridControl for exporting data from Grid. After export I change value of some cell's(which have blank value) to integer let's say 123 then on import it does not fetches that integer value in DataTable.
I have posted same issue on DevExpress support center "Export values in Improper Cell". They said the issue is from MSDN not by their control's. Please download the sample from given DevExpress link & also watch the video attached for more detailed information.
I have used following code for import.
private System.Data.DataTable GetDataTableFromFile(string fileName)
{
string query = string.Empty;
//// string connectionString = "provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + fileName + "';Extended Properties=Excel 8.0;";
string connectionStringV12 = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=Excel 12.0;";
string connectionStringV4 = "Provider=Microsoft.Jet.OLEDB.4.0;Data source={0};Extended Properties=Excel 8.0;";
System.Data.DataTable dataTable = new System.Data.DataTable();
OleDbConnection obedbConnection = new OleDbConnection(string.Format(connectionStringV4, fileName));
try
{
if (obedbConnection.State != ConnectionState.Open)
{
obedbConnection.Open();
}
}
catch (Exception)
{
////Diff. Connetion String
obedbConnection = new OleDbConnection(string.Format(connectionStringV12, fileName));
}
////Get First SheetName From Xls File
string sheetName = GetSheetNameFromFile(obedbConnection);
if (sheetName != null)
{
////Query for Reading all Data from File
query = "select * from [" + sheetName + "]";
}
if (!string.IsNullOrEmpty(query))
{
OleDbDataAdapter data = new OleDbDataAdapter(query, obedbConnection);
data.Fill(dataTable);
}
return dataTable;
}
/// <summary>
/// Gets First SheetName of excel File
/// </summary>
/// <param name="con">Connection object.</param>
/// <returns>return sheet name.</returns>
private string GetSheetNameFromFile(OleDbConnection con)
{
try
{
if (con.State != ConnectionState.Open)
{
con.Open();
}
var oledbTableSchema = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "Table" });
if (oledbTableSchema.Rows.Count > 0)
{
string sheetName = oledbTableSchema.Rows[0].ItemArray[2].ToString();
if (string.IsNullOrEmpty(sheetName))
{
throw new Exception("Sheet Not Found");
}
return sheetName;
}
return string.Empty;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
So, Can any one please help me to solve this issue?

Adding the IMEX = 1 property to my connection string, solved my issue.
string connectionStringV4 = "Provider=Microsoft.Jet.OLEDB.4.0;Data source={0};Extended Properties=Excel 8.0;IMEX=1;";
There is also similar behavior reported in the below thread
Not able to read integer in excel file consistantly
For more detailed answer please go to following link :
Data not fills correctly in DataTable using OleDbDataAdapter

Related

c# provider for excel not registered

For some projects I need the options of exporting and importing from/to an Excel.
For that I'm using that code:
private void myButton12_Click(object sender, EventArgs e)
{
string path = string.Empty;
string ext = string.Empty;
OpenFileDialog file = new OpenFileDialog();
if (file.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
path = file.FileName;
ext = System.IO.Path.GetExtension(path);
if(ext == ".xls" || ext == ".xlsx")
{
Console.WriteLine("ok");
DataTable dt = new DataTable();
dt = ReadExcel(path, ext);
dataGridView13.DataSource = dt;
}
}
}
public DataTable ReadExcel(string fileName, string fileExt)
{
string conn = string.Empty;
DataTable dtexcel = new DataTable();
if (fileExt.CompareTo(".xls") == 0)
conn = #"provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + ";Extended Properties='Excel 8.0;HRD=Yes;IMEX=1';"; //for below excel 2007
else
conn = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties='Excel 16.0;HDR=NO';"; //for above excel 2007
using (OleDbConnection con = new OleDbConnection(conn))
{
try
{
OleDbDataAdapter oleAdpt = new OleDbDataAdapter("select * from [Sheet1$]", con); //here we read data from sheet1
oleAdpt.Fill(dtexcel); //fill excel data into dataTable
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
return dtexcel;
}
Problem is that I get that Exception:
The provider 'Microsoft.ACE.OLEDB.12.0' is not registered on the local computer.
After looking on the internet, I seems like it come from the x86 configuration need that I tried... I've also tried switching for some others, but none of them worked,
I really can't find any solution to my problem,
Any idea where the problem can be?
Thanks
If you run your app in X64 Target CPU you need "AccessDatabaseEngine_X64.exe" , if you run your app in X86 you need "AccessDatabaseEngine.exe" fromthe page below :
https://www.microsoft.com/en-us/download/details.aspx?id=13255

Failed to read correct date from excel (oledb)

We are trying to automate some of the processes that our done daily, for this we have made some Excel files which store the instruction for these processes. In a few such excel files we are using =TODAY() function to populate the cell with today's date.
Now while trying to read these excel files, I am not able to get the correct date in the datatable if excel is not opened at least once on a particular date. The date picked is from the last time the excel file was opened. This is causing a major problem while automating the problem at hand.
I would want to know if this can be achieved using OLEDB drivers and if not what other options are there?
This is the code for reading from the excel, the datasource is constructed at runtime.
private string excelObject = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=YES\"";
public DataTable GetSchema()
{
DataTable dtSchema = null;
if (this.Connection.State != ConnectionState.Open) this.Connection.Open();
dtSchema = this.Connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
return dtSchema;
}
public DataTable ReadTable(string tableName, string criteria)
{
try
{
DataTable resultTable = null;
if (this.Connection.State != ConnectionState.Open)
{
this.Connection.Open();
onReadProgress(10);
}
string cmdText = "Select * from [{0}]";
if (!string.IsNullOrEmpty(criteria))
{
cmdText += " Where " + criteria;
}
OleDbCommand cmd = new OleDbCommand(string.Format(cmdText, tableName));
cmd.Connection = this.Connection;
OleDbDataAdapter adpt = new OleDbDataAdapter(cmd);
onReadProgress(30);
DataSet ds = new DataSet();
onReadProgress(50);
adpt.Fill(ds, tableName);
onReadProgress(100);
if (ds.Tables.Count == 1)
{
return ds.Tables[0];
}
else
{
return null;
}
}
catch
{
MessageBox.Show("Table Cannot be read");
return null;
}
}

Why does OleDbDataAdapter leave artifacts when filling a DataTable?

I wrote some methods which are supposed to fetch a DataTable for each WorkSheet in a Excel file:
Step 1 is to get the names of all sheets included in a .xlsx file:
private static List<string> GetSheetNames(string filePath)
{
List<string> sheetNames = new List<string>();
DataTable dt = null;
try
{
OleDbConnection connection = new OleDbConnection("provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + filePath + "';Extended Properties='Excel 12.0 Xml;HDR=YES;'");
connection.Open();
dt = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
return null;
}
// Add the sheet name to the string array.
foreach (DataRow row in dt.Rows)
{
sheetNames.Add(row["TABLE_NAME"].ToString());
}
}catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
return sheetNames;
}
Step 2 is to read every sheet and return an according DataTable:
private static DataTable ReadExcelSheet(string filePath,string sheetName)
{
DataTable table = new DataTable();
ValidateSheetName(ref sheetName);
try
{
OleDbConnection connection;
DataSet DtSet;
OleDbDataAdapter cmd;
connection = new OleDbConnection("provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + filePath + "';Extended Properties='Excel 12.0 Xml;HDR=YES;'");
cmd = new OleDbDataAdapter("select * from ["+sheetName+"]", connection);
cmd.TableMappings.Add("Table", sheetName.Replace("$",string.Empty));
DtSet = new DataSet();
cmd.Fill(DtSet);
table = DtSet.Tables[0];
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
return table;
}
Both methods are called from this last method which returns a List<DataTable>:
private static List<DataTable> ConvertExcelToTables(string filePath)
{
List<string> sheetNames = GetSheetNames(filePath);
List<DataTable> tableList = new List<DataTable>();
foreach(string sheetName in sheetNames)
{
tableList.Add(ReadExcelSheet(filePath,sheetName));
}
return tableList;
}
There is also a little helper method which should be irrelevant for the question:
private static void ValidateSheetName(ref string sheetName)
{
sheetName = sheetName.EndsWith("$") ? sheetName : sheetName + "$";
}
If I take one sheet from a example file it looks like this:
Now no matter if I just look into the DataTable while debugging or if I bind it as a DataSource of a DataGridView the result looks a little weird:
My guess is that this might have to do with Excel sheets beginning counting with 1 not with 0. But even if this is the case I can't really think of a solution. Or did I miss something. Actually this is a pity because this seems to be a clean solution imo.
No, the problem is caused by
HDR=YES;
in your connection string.
Change it to
HDR=NO;
HDR=YES means that the first line of your Excel sheets is assumed to contain the fields' names of your table. But this is not the case with the sheet shown as an example. Indeed the OleDb provider cannot determine the name of the second column (it's blank) and thus it assigns the default value (the letter F followed by the progressive number of the column)
You could find a lot of examples and explanations about connectionstrings for excel at connectionstrings.com

How can I read the rows of an Excel csv or xls file into an ASP.NET app from a remote location using C#?

Here's my situation. I'm designing a program that takes Excel files (which may be in csv, xls, or xlsx format) from a remote network drive, processes the data, then outputs and stores the results of that process. The program provides a listbox of filenames that are obtained from the remote network drive folder using the method detailed in the accepted answer here. Once the user selects a filename from the listbox, I want the program to find the file and obtain the information from it to do the data processing. I have tried using this method to read the data from the Excel file while in a threaded security context, but that method just fails without giving any kind of error. It seems to not terminate. Am I going about this the wrong way?
Edit - (Final Notes: I have taken out the OleDbDataAdapter and replaced it with EPPlus handling.)
I was able to scrub sensitive data from the code, so here it is:
protected void GetFile(object principalObj)
{
if (principalObj == null)
{
throw new ArgumentNullException("principalObj");
}
IPrincipal principal = (IPrincipal)principalObj;
Thread.CurrentPrincipal = principal;
WindowsIdentity identity = principal.Identity as WindowsIdentity;
WindowsImpersonationContext impersonationContext = null;
if (identity != null)
{
impersonationContext = identity.Impersonate();
}
try
{
string fileName = string.Format("{0}\\" + Files.SelectedValue, #"RemoteDirectoryHere");
string connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.14.0; data source={0}; Extended Properties=Excel 14.0;", fileName);
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM Sheet1", connectionString);
DataSet ds = new DataSet();
adapter.Fill(ds, "Sheet1");
dataTable = ds.Tables["Sheet1"];
}
finally
{
if (impersonationContext != null)
{
impersonationContext.Undo();
}
}
}
Additional Edit
Now xlsx files have been added to the mix.
Third Party
Third party solutions are not acceptable in this case (unless they allow unrestricted commercial use).
Attempts - (Final Notes: Ultimately I had to abandon OleDb connections.)
I have tried all of the different connection strings offered, and I have tried them with just one file type at a time. None of the connection strings worked with any of the file types.
Permissions
The User does have access to the file and its directory.
Your connection string might be the issue here. As far as I know, there isn't 1 that can read all xls, csv, and xlsx. I think you're using the XLSX connection string.
When I read xls, i use the following connection string:
#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + sFilePath + ";Extended Properties='Excel 8.0;HDR=YES;IMEX=1;'"
Having said that, I recommend using a 3rd party file reader/parser to read XLS and CSV since, from my experience, OleDbDataAdapter is wonky depending on the types of data that's being read (and how mixed they are within each column).
For XLS, try NPOI https://code.google.com/p/npoi/
For CSV, try http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader
For XLSX, try EPPlus http://epplus.codeplex.com/
I've had great success with the above libraries.
Is it really important that you use an OleDb interface for this? I've always done it with Microsoft.Office.Excel.Interop, to wit:
using System;
using Microsoft.Office.Interop.Excel;
namespace StackOverflowExample
{
class Program
{
static void Main(string[] args)
{
var app = new Application();
var wkbk = app.Workbooks.Open(#"c:\data\foo.xls") as Workbook;
var wksht = wkbk.Sheets[1] as Worksheet; // not zero-based!
for (int row = 1; row <= 100; row++) // not zero-based!
{
Console.WriteLine("This is row #" + row.ToString());
for (int col = 1; col <= 100; col++)
{
Console.WriteLine("This is col #" + col.ToString());
var cell = wksht.Cells[row][col] as Range;
if (cell != null)
{
object val = cell.Value;
if (val != null)
{
Console.WriteLine("The value of the cell is " + val.ToString());
}
}
}
}
}
}
}
As you will be dealing with xlsx extension, you should rather opt for the new connection string.
public static string getConnectionString(string fileName, bool HDRValue, bool WriteExcel)
{
string hdrValue = HDRValue ? "YES" : "NO";
string writeExcel = WriteExcel ? string.Empty : "IMEX=1";
return "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + fileName + ";" + "Extended Properties=\"Excel 12.0 xml;HDR=" + hdrValue + ";" + writeExcel + "\"";
}
Above is the code for getting the connection string. First argument expects the actual path for file location. Second argument will decide whether to consider first row values as column headers or not. Third argument helps decide whether you want to open the connection to create and write the data or simply read the data. To read the data set it to "FALSE"
public static ReadData(string filePath, string sheetName, List<string> fieldsToRead, int startPoint, int endPoint)
{
DataTable dt = new DataTable();
try
{
string ConnectionString = ProcessFile.getConnectionString(filePath, false, false);
using (OleDbConnection cn = new OleDbConnection(ConnectionString))
{
cn.Open();
DataTable dbSchema = cn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dbSchema == null || dbSchema.Rows.Count < 1)
{
throw new Exception("Error: Could not determine the name of the first worksheet.");
}
StringBuilder sb = new StringBuilder();
sb.Append("SELECT *");
sb.Append(" FROM [" + sheetName + fieldsToRead[0].ToUpper() + startPoint + ":" + fieldsToRead[1].ToUpper() + endPoint + "] ");
OleDbDataAdapter da = new OleDbDataAdapter(sb.ToString(), cn);
dt = new DataTable(sheetName);
da.Fill(dt);
if (dt.Rows.Count > 0)
{
foreach (DataRow row in dt.Rows)
{
string i = row[0].ToString();
}
}
cn.Dispose();
return fileDatas;
}
}
catch (Exception)
{
}
}
This is for reading 2007 Excel into dataset
DataSet ds = new DataSet();
try
{
string myConnStr = "";
myConnStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=MyDataSource;Extended Properties=\"Excel 12.0;HDR=YES\"";
OleDbConnection myConn = new OleDbConnection(myConnStr);
OleDbCommand cmd = new OleDbCommand("select * from [Sheet1$] ", myConn);
OleDbDataAdapter adapter = new OleDbDataAdapter();
adapter.SelectCommand = cmd;
myConn.Open();
adapter.Fill(ds);
myConn.Close();
}
catch
{ }
return ds;

Unable to read excel sheet using ExcelReader in ASP.Net?

I am using IExcelDataReader to reader to read a excel sheet using following code:
private static IExcelDataReader FetchDataReaderForExcel(HttpPostedFile file)
{
IExcelDataReader dataReader = null;
if (null != file)
{
string fileExtension = Path.GetExtension(file.FileName);
switch (fileExtension)
{
case ".xls":
dataReader = ExcelReaderFactory.CreateBinaryReader(file.InputStream);
break;
case ".xlsx":
dataReader = ExcelReaderFactory.CreateOpenXmlReader(file.InputStream);
break;
default:
dataReader = null;
break;
}
}
return dataReader;
}
When i am reading the excel sheet using this method sometime i am not able to read the data correctly. Sometime it is not able to read column other time it is not able to read the entire data. I need to format each column to normal text and then upload again, it works then. Excel contains data contains integer, string, datetime, hyperlink. Can anyone tell me what could be the problem or alternative for this?
I'm using oledb and it works perfect for me. Here is my example:
using (OleDbConnection con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Filename + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\""))
{
//
string listName = "Sheet1";
con.Open();
try
{
DataSet ds = new DataSet();
OleDbDataAdapter odb = new OleDbDataAdapter("select * from [" + listName + "$]", con);
odb.Fill(ds);
con.Close();
foreach (DataRow myrow in ds.Tables[0].Rows)
{
Object[] cells = myrow.ItemArray;
if (cells[0].ToString().Length > 0 || cells[1].ToString().Length > 0 || cells[2].ToString().Length > 0)
{
/*
cells[0]
cells[1]
cells[2]
are getting values
*/
}
}
}
catch (Exception ex)
{
return null;
}
}
OLEDB.12.0 works with both .xls and .xlsx
If you are Uploading the file ,and the file has Many sheets in it and you want to read all the sheets you can follow this method....first write the Code for FileUPload and save the uploaded file in a path....using that path you can read the files
/// <summary>
/// This method retrieves the excel sheet names from
/// an excel workbook & reads the excel file
/// </summary>
/// <param name="excelFile">The excel file.</param>
/// <returns></returns>
#region GetsAllTheSheetNames of An Excel File
public static string[] ExcelSheetNames(String excelFile)
{
DataTable dt;
string connString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelFile + ";Extended Properties='Excel 12.0;HDR=Yes'";
using (OleDbConnection objConn = new OleDbConnection(connString))
{
objConn.Open();
dt =
objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
return null;
}
string[] res = new string[dt.Rows.Count];
for (int i = 0; i < res.Length; i++)
{
string name = dt.Rows[i]["TABLE_NAME"].ToString();
if (name[0] == '\'')
{
//numeric sheetnames get single quotes around
//remove them here
if (Regex.IsMatch(name, #"^'\d\w+\$'$"))
{
name = name.Substring(1, name.Length - 2);
}
}
res[i] = name;
}
return res;
}
}
#endregion
//You can read files and store the data in a dataset use them
public static DataTable GetWorksheet(string excelFile,string worksheetName)
{
string connString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelFile + ";Extended Properties='Excel 12.0;HDR=Yes'";
OleDbConnection con = new System.Data.OleDb.OleDbConnection(connString);
OleDbDataAdapter cmd = new System.Data.OleDb.OleDbDataAdapter("select * from [" + worksheetName + "$]", con);
con.Open();
System.Data.DataSet excelDataSet = new DataSet();
cmd.Fill(excelDataSet);
con.Close();
return excelDataSet.Tables[0];
}
Else U can use this method to read the excel file
Just Add the reference
click on the "AddReference" on solution explorer ,click on com tab and Add this reference
Microsoft.Office.Interop.Excel
And add this namespace in your code behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Excel = Microsoft.Office.Interop.Excel;
using System.IO;
using System.Data;
static void Main(string[] args)
{
string Path = #"C:\samples\SEP DUMPS.xls";
// initialize the Excel Application class
Excel.Application app = new Excel.Application();
//Excel.Worksheet NwSheet;
Excel.Range ShtRange;
// create the workbook object by opening the excel file.
Excel.Workbook workBook = app.Workbooks.Open(Path,0,true,5,"","",true,Excel.XlPlatform.xlWindows,"\t",false,false, 0,true,1,0);
// Get The Active Worksheet Using Sheet Name Or Active Sheet
Excel.Worksheet workSheet = (Excel.Worksheet)workBook.ActiveSheet;
int index = 1;
// that is which cell in the excel you are interesting to read.
object rowIndex = 1;
object colIndex1 = 1;
object colIndex2 = 5;
object colIndex3 = 4;
System.Text.StringBuilder sb = new StringBuilder();
try
{
while (((Excel.Range)workSheet.Cells[rowIndex, colIndex1]).Value2 != null)
{
rowIndex =index;
string firstName = Convert.ToString( ((Excel.Range)workSheet.Cells[rowIndex, colIndex1]).Value2);
string lastName = Convert.ToString(((Excel.Range)workSheet.Cells[rowIndex, colIndex2]).Value2);
string Name = Convert.ToString(((Excel.Range)workSheet.Cells[rowIndex, colIndex3]).Value2);
string line = firstName + "," + lastName + "," + Name;
sb.Append(line); sb.Append(Environment.NewLine);
Console.WriteLine(" {0},{1},{2} ", firstName, lastName,Name);
index++;
}
Writetofile(sb.ToString());
ShtRange = workSheet.UsedRange;
Object[,] s = ShtRange.Value;
}
catch (Exception ex)
{
app.Quit();
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
Hope this helps you..........If u have any doubts Ask me...

Categories