How to handle invalid characters in OleDb Excel import? - c#

I am importing excel files to my application and sometimes worksheets column names have "$" sign in it. I receive this Exception:
System.Data.OleDb.OleDbException was unhandled
Message=''6um$'$' is not a valid name. Make sure that it does not include invalid characters or punctuation and that it is not too long.
In this sheet "6um$" is a column name.
This is my code:
OleDbConnection con = new System.Data.OleDb.OleDbConnection(connectionString);
OleDbDataAdapter cmd = new System.Data.OleDb.OleDbDataAdapter(
"select * from [" + worksheetName + "$]", con);
con.Open();
System.Data.DataSet excelDataSet = new DataSet();
cmd.Fill(excelDataSet);
con.Close();
Any ideas how to handle this situation?
Edit:
I thought the problem was having $ in column name. But turns out, The problem is having $ sign in worksheet name!

Ok, I figured out the solution:
For some reason, the worksheets that I renamed myself have extra $ sign (no idea why, there is no $ sign in the excel but OLEDB returns them with extra $ something like this '6um$'$'). I trim the first $ off and use this code to check is there is any extra $ sign still left:
char delimiterChars = '$';
string[] words = worksheetName.Split(delimiterChars);
worksheetName=words[0];

if (Directory.Exists(serverPath))
{
string FileExist = sp + "book1.xlsx"; ;
string Exten = Path.GetExtension(FileExist);
string g = "sheet1";
if (File.Exists(FileExist))
{
if (Exten == ".xlsx")
{
string connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + FileExist + ";Extended Properties=Excel 12.0";
OleDbConnection oledbConn = new OleDbConnection(connString);
try
{
// Open connection
oledbConn.Open();
string query = String.Format("select * from [{0}$]", g);
// Create OleDbCommand object and select data from worksheet Sheet1
OleDbCommand cmd = new OleDbCommand(query, oledbConn);
// Create new OleDbDataAdapter
OleDbDataAdapter oleda = new OleDbDataAdapter();
oleda.SelectCommand = cmd;
// Create a DataSet which will hold the data extracted from the worksheet.
DataSet ds = new DataSet();
// Fill the DataSet from the data extracted from the worksheet.
oleda.Fill(ds, "sheetdt");
GridView1.DataSource = ds.Tables[0].DefaultView;
GridView1.DataBind();
}
catch (Exception ex)
{
LblSuccess.Text = ex.Message;
}
finally
{
// Close connection
oledbConn.Close();
}
}
}
}

Related

Get first table with GetSchema

I'm trying to get the first sheet of an Excel File:
try
{
string constring = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + filepath + ";Extended Properties=Excel 12.0;";
OleDbConnection conn = new OleDbConnection(constring);
conn.Open();
DataTable myTables = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
var myTableName = conn.GetSchema("Tables").Rows[0].Table;
string sqlquery = string.Format("SELECT * FROM [{0}]", myTableName);
OleDbDataAdapter da = new OleDbDataAdapter(sqlquery, conn);
da.Fill(dt);
MessageBox.Show(Convert.ToString(dt.Rows.Count));
return dt;
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error", MessageBoxButton.OK,
MessageBoxImage.Error);
return dt;
}
What am I doing wrong?
EDIT:
The following error is show up:
The Microsoft Office Access database engine could not find the 'Tables' object.
This works with Visual Basic:
Try
Dim constring As String = "Provider=Microsoft.ACE.OLEDB.12.0;" &
"Data Source=" & filepath &
";Extended Properties=Excel 12.0;"
Dim conn As New OleDbConnection(constring)
conn.Open()
Dim myTables As DataTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, "TABLE"})
Dim myTableName = conn.GetSchema("Tables").Rows(0)("TABLE_NAME")
Dim sqlquery As String = String.Format("SELECT * FROM [{0}]", myTableName)
Dim da As New OleDbDataAdapter(sqlquery, conn)
da.Fill(dt)
conn.Close()
MsgBox(dt.Rows.Count)
Return dt
Catch ex As Exception
MsgBox(Err.Description, MsgBoxStyle.Critical)
Return dt
End Try
I'm trying to replicate it with C#.
The error line seems to be this one:
var myTableName = conn.GetSchema("Tables").Rows[0].Table;
It tries to replicate the following line in VB code:
Dim myTableName = conn.GetSchema("Tables").Rows(0)("TABLE_NAME")
Here it is all put together. The # sign preceding the file path string take the string and does not use the \ as an escape. In the interpolated string we do want the escape character for the embedded double quotes. The using block ensures that your connection is closed and disposed. I displayed the result in a combo box.
private void opCode()
{
string filePath = #"C:\Users\xxx\Documents\Excel\TestImport.xlsx";
string conString = $"Provider = Microsoft.ACE.OLEDB.12.0; Data Source = {filePath} ; Extended Properties = \"Excel 12.0; HDR = YES;\"";
Debug.Print(conString);
DataTable dt;
using (OleDbConnection cn = new OleDbConnection(conString))
{
cn.Open();
dt = cn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
}
var exSheets = (from dRow in dt.AsEnumerable()
select dRow["TABLE_Name"]).ToArray();
cbo1.Items.AddRange(exSheets);
}
****NOTE: The Linq query does not necessarily return the sheets in
the order that appear in the workbook

How to Convert Excel Value from scientific notation to excel C#

I have a application to read a excel cell value which is in scientific notation.
I have tried the below code :
decimal dec = Decimal.Parse("1.01703E+11", System.Globalization.NumberStyles.Any);
Result : 101703000000M
But the excel value is different from the result
This is the correct excel value "101703000026"
Connection method
public DataSet ReadExcelData(string Path)
{
OleDbConnection oledbConn = null;
try
{
// need to pass relative path after deploying on server
string path = System.IO.Path.GetFullPath(#Path);
oledbConn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties='Excel 12.0;HDR=YES;IMEX=1;';");
oledbConn.Open();
OleDbCommand cmd = new OleDbCommand();
OleDbDataAdapter oleda = new OleDbDataAdapter();
DataSet ds = new DataSet();
// selecting distict list of Slno
cmd.Connection = oledbConn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM [DailySalesReport$]";
oleda = new OleDbDataAdapter(cmd);
oleda.Fill(ds);
// binding form data with grid view
return ds;
}
// need to catch possible exceptions
catch
{
return null;
}
finally
{
oledbConn.Close();
}
}
How can I get the correct value. Please advice.
This is my output

Why replace specific character in Column Name when Importing Excel to C# (WPF)

When import Microsoft Excel file to C# (WPF), specific characters in Column Names (Column Headers) will be replaced.
eg ! it becomes _, and . to #. How to stop it?
connectionString:
Provider=Microsoft.ACE.OLEDB.12.0; Data Source="+filePath+";Extended Properties="Excel 8.0;HDR=YES;CharacterSet=65001;";
And method:
public DataSet ImportExcel(string fileName)
{
tableList = null;
DataSet ds = new DataSet();
string connectionString = GetConnectionString(fileName);
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
// Get all Sheets in Excel File
DataTable dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
tableList = new string[dtSheet.Rows.Count];
// Loop through all Sheets to get data
foreach (DataRow dr in dtSheet.Rows)
{
string sheetName = dr["TABLE_NAME"].ToString();
tableList[dtSheet.Rows.IndexOf(dr)] = sheetName;
Console.WriteLine("TABLE_NAME: " + sheetName);
if (!sheetName.EndsWith("$"))
continue;
// Get all rows from the Sheet
cmd.CommandText = "SELECT * FROM [" + sheetName + "]";
DataTable dt = new DataTable();
dt.TableName = sheetName;
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
rowsCount += dt.Rows.Count;
ds.Tables.Add(dt);
}
cmd = null;
conn.Close();
}
return ds;
}
Basically you are limited to what characters are allowed in column names, these are letters, numbers and characters: ##$_ see here. The $ symbol and numbers aren't allowed to be the first character either.

How to read and get data from excel .xlsx

I have excel file with 2 tables. I need to read this tables and get all the values from this tables. But all for what I have is:
OleDbConnection cnn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\MigrateExelSql\Include\TestDb.xlsx; Extended Properties=Excel 12.0;");
OleDbCommand oconn = new OleDbCommand("select * from [Sheet1$]", cnn);
cnn.Open();
OleDbDataAdapter adp = new OleDbDataAdapter(oconn);
DataTable dt = new DataTable();
adp.Fill(dt);
And I don't uderstand what I need to write for get the all values from Username and Email tables. Here is the .xlsx table TestDb Please can somebody help me, because I'm googling the second day and I have no idea for what I must to do.
And when I try to get values by this method it return me an error:
var fileName = string.Format("{0}\\Include\\TestDb.xlsx", Directory.GetCurrentDirectory());
var connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0;", fileName);
var adapter = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", connectionString);
var ds = new DataSet();
adapter.Fill(ds, "Username");
var data = ds.Tables["Username"].AsEnumerable();
foreach (var item in data)
{
Console.WriteLine(item);
}
Console.ReadKey();
One more Edit:
string con =
#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\MigrateExelSql\Include\TestDb.xlsx; Extended Properties=Excel 12.0;";
using(OleDbConnection connection = new OleDbConnection(con))
{
connection.Open();
OleDbCommand command = new OleDbCommand("select * from [Sheet1$]", connection);
using(OleDbDataReader dr = command.ExecuteReader())
{
while(dr.Read())
{
var row1Col0 = dr[0];
Console.WriteLine(row1Col0);
}
}
}
Console.ReadKey();
This will read only first column, but when I try to read dr[1] it will return error: Index was outside bound of the array.
Your xlsx file contains only one sheet and in that sheet there is only one column.
A sheet is treated by the OleDb driver like a datatable and each column in a sheet is considered a datacolumn.
You can't read anything apart one table (Sheet1$) and one column (dr[0]).
If you try to read dr[1] then you are referencing the second column and that column doesn't exist in Sheet1.
Just to test, try to add some values in the second column of the Excel file.
Now you can reference dr[1].

Read alphanumeric characters from csv file in C#

I am using the following code to read my csv file:
public 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.ACE.OLEDB.12.0;"
+ "Data Source=\"" + dir + "\\\";"
+ "Extended Properties=\"text;HDR=Yes;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);
//fill the DataTable
dAdapter.Fill(dTable);
dAdapter.Dispose();
return dTable;
}
But the above doesn't reads the alphanumeric value from the csv file. it reads only i either numeric or alpha.
Whats the fix i need to make to read the alphanumeric values? Please suggest.
I suggest you use A Fast CSV Reader which does not have this issue and is much more faster.
Remove IMEX=1 from the connection string. I don't think you need it for CSV files.
Try this OleDBAdapter Excel QA I posted via stack overflow.
I have not tried this out, but it sounds interesting! LinqToExcel
they say it can be used on .CSV files as well...
hi all this code is gets alphanumeric values also
using System.Data.OleDb;
string ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + filepath + ";" + "Extended Properties="+(char)34+"Excel 8.0;IMEX=1;"+(char)34;
string CommandText = "select * from [Sheet1$]";
OleDbConnection myConnection = new OleDbConnection(ConnectionString);
myConnection.Open();
OleDbDataAdapter myAdapter = new OleDbDataAdapter(CommandText, myConnection);
ds = null;
ds = new DataSet();
myAdapter.Fill(ds);

Categories

Resources