Excel Jet OLE DB: Inserting a DateTime value - c#

OLEDB can be used to read and write Excel sheets. Consider the following code example:
using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\my\\excel\\file.xls;Extended Properties='Excel 8.0;HDR=Yes'")) {
conn.Open();
OleDbCommand cmd = new OleDbCommand("CREATE TABLE [Sheet1] ([Column1] datetime)", conn);
cmd.ExecuteNonQuery();
cmd = new OleDbCommand("INSERT INTO Sheet1 VALUES (#mydate)", conn);
cmd.Parameters.AddWithValue("#mydate", DateTime.Now.Date);
cmd.ExecuteNonQuery();
}
This works perfectly fine. Inserting numbers, text, etc. also works well. However, inserting a value with a time component fails:
using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\my\\excel\\file.xls;Extended Properties='Excel 8.0;HDR=Yes'")) {
conn.Open();
OleDbCommand cmd = new OleDbCommand("CREATE TABLE [Sheet1] ([Column1] datetime)", conn);
cmd.ExecuteNonQuery();
cmd = new OleDbCommand("INSERT INTO Sheet1 VALUES (#mydate)", conn);
cmd.Parameters.AddWithValue("#mydate", DateTime.Now); // <-- note the difference here
cmd.ExecuteNonQuery();
}
Executing this INSERT fails with an OleDbException: Data type mismatch in criteria expression.
Is this a known bug? If yes, what can be done to workaround it? I've found one workaround that works:
cmd = new OleDbCommand(String.Format(#"INSERT INTO Sheet1 VALUES (#{0:dd\/MM\/yyyy HH:mm:ss}#)", DateTime.Now), conn);
It basically creates an SQL statement that looks like this: INSERT INTO Sheet1 VALUES (#05/29/2011 13:12:01#). Of course, I don't have to tell you how ugly this is. I'd much rather have a solution with a parameterized query.

It appears to be a known bug https://connect.microsoft.com/VisualStudio/feedback/details/94377/oledbparameter-with-dbtype-datetime-throws-data-type-mismatch-in-criteria-expression
You might want to truncate the milisecond like this it appear to work for OleDbParameter:
DateTime org = DateTime.UtcNow;
DateTime truncatedDateTime = new DateTime(org.Year, org.Month, org.Day, org.Hour, org.Minute, org.Second);
And add this instead of the DateTime.Now into your parameter value.

The problem is the cell containing datetime value cannot be directly put into excel' column. You have to either insert the date component or the time component. The reason for failure is the default property of excel' cell is "values" instead of "datetime" in excel.

Related

Data type mismatch in criteria expression - started only recently

I use Access database. This error wasn't occurring 30 minutes ago.
ERROR is:
Data type mismatch in criteria expression.
OleDbConnection con = new OleDbConnection(Utility.GetConnection());
con.Open();
OleDbCommand cmd2 = new OleDbCommand("INSERT INTO Temsilci(isin_adi,isin_tanimi,verildigi_tarih,teslim_tarihi,sorumlu_marka,sorumlu_ajans,revize,Temsilci_isverenid)
values (#isinadi,#isintanimi,#vertarih,#testarih,#smarka,#sajans,#revize,#temsid)", con);
cmd2.Parameters.Add("isintanimi", txtMarkaAdi.Text);
cmd2.Parameters.Add("isinadi", txtisAdi.Text);
cmd2.Parameters.Add("smarka", txtMarkaTemsilcisi.Text);
cmd2.Parameters.Add("sajans", txtAjansTemsilcisi.Text);
cmd2.Parameters.Add("revize", txtSorumluKisiler.Text);
cmd2.Parameters.Add("vertarih", txtverilisTarihi.Text);
cmd2.Parameters.Add("testarih", txtTeslimTarihi.Text);
cmd2.Parameters.Add("temsid", Session["UserID"]);
cmd2.ExecuteNonQuery();
con.Close();
My database columns are:
ID = AutoNumber
isin_adi = Short Text
isin_tanimi = Long Text
verildigi_tarih= Date/Time
teslim_tarihi=Date/Time
sorumlu_marka = Short Text
sorumlu_ajans=Short Text
personel_id=Number
revize=Short Text
is_durum=Short Text
Temsilci_isverenid=Number
I Solved the problem. I realized the rank of parameters was not true. i change my code like that:
OleDbConnection con = new OleDbConnection(Utility.GetConnection());
con.Open();
OleDbCommand cmd2 = new OleDbCommand("INSERT INTO Temsilci(isin_adi,isin_tanimi,verildigi_tarih,teslim_tarihi,sorumlu_marka,sorumlu_ajans,revize,Temsilci_isverenid) values (#isinadi,#isintanimi,#vertarih,#testarih,#smarka,#sajans,#revize,#temsid)", con);
cmd2.Parameters.Add("isinadi", txtisAdi.Text);
cmd2.Parameters.Add("isintanimi", txtMarkaAdi.Text);
cmd2.Parameters.Add("vertarih", txtverilisTarihi.Text);
cmd2.Parameters.Add("testarih", txtTeslimTarihi.Text);
cmd2.Parameters.Add("smarka", txtMarkaTemsilcisi.Text);
cmd2.Parameters.Add("sajans", txtAjansTemsilcisi.Text);
cmd2.Parameters.Add("revize", txtSorumluKisiler.Text);
cmd2.Parameters.Add("temsid", Session["UserID"]);
cmd2.ExecuteNonQuery();
con.Close();
after that i get error like this :
You cannot add or change a record because a related record is required in table 'Personel'.
And i remove the relationship from 2 tables. And now it works normally.
I think access database have some bugs ,and even if code is correct, errors may accuired.
So i will move my database to SQL from ACCESS i think. Thanks guys.

Querying dBase file in C#

My problem specifically is I can't filter by a Date field.
Here is my code:
string connstr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\Tools;Extended Properties=dBASE IV;User ID=Admin;Password=;";
using (OleDbConnection con = new OleDbConnection(connstr))
{
string sql = "select USERNUMBER,FIRSTNAME,LASTNAME, LASTACCESS from EMP WHERE TERMINATED=\"Y\" AND [LASTACCESS]<\"2001/10/20\"";
OleDbCommand cmd = new OleDbCommand(sql, con);
con.Open();
OleDbDataReader reader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
It works fine if I omit the date field. I just can't figure out what the format is. If I look at the table with a dbf viewer utility the LASTACCESS field is in dd.mm.yyyy (with the periods as separators, but I don't know if that is just a behavior of the utility).
If I omit the forward slashes from the date field, it works but returns zero records (even though I know there are).
Try this and forget date time hell
string sql = "select USERNUMBER,FIRSTNAME,LASTNAME, LASTACCESS from EMP WHERE TERMINATED=\"Y\" AND [LASTACCESS]<#StartDate";
OleDbCommand cmd = new OleDbCommand(sql, con);
cmd.Parameters.AddWithValue("#StartDate", new DateTime(2001, 10, 20));
Just use parameters and forget about formatting them yourself .
The framework is here to help you and provide solutions already tested and working like a charm

Create a sheet into a workbook without headers ace.oledb

How can I create a named sheet without headers - just like the default sheet - via ace.oledb?
The create command for a sheet must be something like:
CREATE TABLE [MySheet] (field1 type, field2 type ..., fieldn type )
It creates MySheet and always insert (regardless of HDR extended property in connection string or the registry setting FirstRowHasNames) a first line in MySheet containing field1, field2...fieldn
Basically I don't want a "Table Header" there, I just need to insert values in a newly created named empty sheet.
This isn't pretty, but it's the only way I've found to create a new worksheet with nothing in it. The only problem I've discovered is that Oledb automatically creates a named range on the header cells specified in the CREATE command, but assuming you don't care about that then this should work fine.
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName +
";Mode=ReadWrite;Extended Properties=\"Excel 12.0 XML;HDR=NO\"";
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = conn;
cmd.CommandText = "CREATE TABLE [MySheet] (<colname> <col type>)"; // Doesn't matter what the field is called
cmd.ExecuteNonQuery();
cmd.CommandText = "UPDATE [MySheet$] SET F1 = \"\"";
cmd.ExecuteNonQuery();
}
conn.Close();
}

OleDbDataAdapter Update To dbf [Free Table] -Syntax Error()

When I insert through the OleDbCommand with direct values no problem, it's working fine
OleDbCommand OleCmd1 = new OleDbCommand("Insert into My_Diary (sl_no,reminder) values("+a1+",'CHECK VALUE')", OleCon1);
OleCmd1->ExecuteNonQuery();
But when I like to update through parameter its showing "Syntax Error"....I can't identify my mistake...
string MyConStr = "Provider=VFPOLEDB.1; Data Source='C:\\For_Dbf'; Persist Security Info=False";
InsSavDiaryCmd = "Insert into My_Table1 (sl_no,reminder) values (#sl_no,#reminder) ";
VFPDAp=gcnew OleDbDataAdapter();
VFPDApMy_Table1InsertCommand = gcnew OleDbCommand(InsSavDiaryCmd, OleCon1);
WithInsVar = VFPDAp.InsertCommand.Parameters;
WithInsVar.Add("#sl_no", OleDbType.Integer, 10, "sl_no");
WithInsVar.Add("#reminder", OleDbType.Char, 250, "reminder");
OleCon1.ConnectionString = MyConStr;
OleCon1.Open();
OleDbTransaction Trans=OleCon1.BeginTransaction();
//VFPDAp.DeleteCommand.Transaction = Trans;
//VFPDAp.UpdateCommand.Transaction = Trans;
VFPDAp.InsertCommand.Transaction = Trans;
VFPDAp.Update(MyDataTbl);
Trans.Commit();
OleCon1.Close();
The OleDbCommand doesn't use named parameters. You need to change the insert statement so that it uses questions.
InsSavDiaryCmd = "Insert into My_Table1 (sl_no,reminder) values (?, ?) ";
You need to make sure that you have a parameter for each question mark and make sure that the parameters are inserted in order of their use in the insert statement.
** If you'd like to use name parameters... you can try using VfpClient which is a project that I'm working on to make data access a little nicer from .Net.

Getting Oledb exception when updating column in excel

I am getting the following error "No value given for one or more required parameters." On the ExceuteNonQuery() line of the below code.
System.Data.OleDb.OleDbConnection finalConnection;
System.Data.OleDb.OleDbCommand myCommand = new System.Data.OleDb.OleDbCommand();
string sql = null;
finalConnection = new System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0; Data Source ='c:\\temp\\test.xlsx'; Extended Properties ='Excel 12.0 Xml;HDR=NO';");
finalConnection.Open();
myCommand.Connection = finalConnection;
foreach (VinObject v in VinList)
{
sql = "Update [Sheet1$] set O = ? where S = ?;";
myCommand.Parameters.Add(new OleDbParameter("#amt", v.CostNewAmt));
myCommand.Parameters.Add(new OleDbParameter("#vin", v.VIN));
myCommand.CommandText = sql;
myCommand.ExecuteNonQuery();
}
finalConnection.Close();
I have also tried using a separate command each time, same error.
foreach (VinObject v in VinList)
{
using (OleDbConnection con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0; Data Source ='c:\\temp\\test.xlsx'; Extended Properties ='Excel 12.0 Xml;HDR=No';"))
{
con.Open();
string query = #"UPDATE [Sheet1$] SET O = ? WHERE S = ?";
OleDbCommand cmd = new OleDbCommand(query, con);
cmd.Parameters.AddWithValue("#param1", v.CostNewAmt);
cmd.Parameters.AddWithValue("#param2", v.VIN);
cmd.ExecuteNonQuery();
con.Close();
}
}
I am able to modify that into an insert and insert into a new excel spreadsheet, but for the life of me cannot get this update to work. Any idea what I am doing wrong? Thanks for the help.
You're getting the error because Excel doesn't recognize the column letter aliases "O" and "S". It needs the actual column "name", which is the value of the cell in the first populated row. If there is not a valid value in that cell, or you have specified HDR=NO in your connection string, the columns will be named F1, F2...Fn. If you're not sure what the inferred column names are, examine the names using OleDbConnection.GetSchema(String,String[]) or OleDbDataReader.GetName(Int32).
Since you have specified HDR=NO in your connection string, your correct SQL will likely be
"Update [Sheet1$] set F15 = ? where F19 = ?;"
For future reference, check out:
How to query and display excel data by using ASP.NET, ADO.NET, and Visual C# .NET
How to transfer data to an Excel workbook by using Visual C# 2005 or Visual C# .NET
How To Use ADO.NET to Retrieve and Modify Records in an Excel Workbook With Visual Basic .NET. (Still lots of helpful info even if you are using C#)

Categories