I have a project that adds and deletes dates , add paragraph have the following code:
Set dbs = CurrentDb
dbs.Execute " INSERT INTO TMP " _
E " ( diaMes ) VALUES ( " _
& "' " & Tmp7 & "' ) "
where tmp7 is date type like dd-mm-yyyy and works perfectly
delete is the following code:
Set dbs = CurrentDb
dbs.Execute " DELETE * FROM TMP " _
And " where diaMes = # " & tmp7 & " # " ;
The problem is that delete only the day to more than 12 ,I understand , If day equals less than 12 is interpreted as mm-dd-yyyy
the tmp7 is a string concatenation string.
How do I force a SQL Pass dd-mm-yyyy ?
Access uses American Date format, so even when you pass DD/MM/YYYY it will think MM/DD/YYYY. As you clearly see the dates over 12 are understood correctly. Example 13/10/2014 will be understood as 13th October 2014. But 7/10/2014 in our eyes is 7th October 2014, but ambigious to Access so it interprets it as 10th July 2014.
So your trouble could be avoided by formatting it correctly. Try using this,
Set dbs = CurrentDb
dbs.Execute "DELETE * FROM TMP WHERE diaMes = " & _
Format(tmp7, "\#mm\/dd\/yyyy\#")
Related
I have a form with one text box, two combo boxes (dropdowns), and two text boxes with input masks for mm/dd/yyyy 99/99/0000;0;_
I am attempting to use all of these fields as filters for a subform.
I have the controls set to fire after update and run a sub that builds a SELECT * INTO sql string for a temp Table that is then sourceobject'ed back to the subform.
In code I have for each control I have code building a snippet of the Where statement for the final sql. the snippet grows as needed, is labeled "Filter"
Some other non-Finished Code....
If Not IsNull(txtDateFrom) Then
If i > 1 Then Filter = Filter & " AND " & "([Date_LastSaved] >= " & Me.txtDateFrom & ")" & " And " & "([Date_LastSaved] <= " & Me.txtDateTo & ")"
End If
Dim sql As String
sql = "SELECT * INTO tmpTable FROM tblReview"
If Not IsNull(Filter) Then
sql = sql & " WHERE " & Filter
End If
My issue and question is that I am testing this one specific situation where there will be Filter = Filter & " AND " & "DATE_STUFF"
where the final sql looks like...
SELECT * INTO tmpTable FROM tblReview WHERE ReviewStatus = 'Quoted' AND ([Date_LastSaved] >= 09/12/2018) And ([Date_LastSaved] <= 10/16/2018)
which should have some result with the test data. Yet, the tmpTable is empty.
This is only happening when I apply a date range criteria.
I tried BETWEEN but could not nail down the syntax.
Any insight is greatly appreciated, Thanks!
UPDATE:
Answer:
If i > 1 Then Filter = Filter & " AND " & "([Date_LastSaved] >= #" & Me.txtDateFrom & "#)" & " And " & "([Date_LastSaved] <= #" & Me.txtDateTo & "#)"
If you want to use dates then they must be quoted. If you just say 10/16/2018 then you are dividing the integer 10 by 16 by 2018 which will yield an integer zero. It will then convert the dates to an integer to do the compare, which will yield a much bigger number, and thus you get no rows.
Any date testing should always be done using date types rather than strings. I think in msaccess you can surround it in #, but not sure. Just research this.
I am trying to create an option on my Access database that deletes all records between 2 dates.
I code I have below does not seem to work consistently. For example, if my database has dates 01/01/18 to 01/30/18, and the range I specify is exactly 01/01/18 to 01/30/18, then it works and deletes all data.
But if I specify any other date range (like 01/01 - 01/15), it will fail and no records will be deleted.
The [Trade Date] is in short text format instead of date, but all the entries are in MM/DD/YY. Would prefer to keep it this way unless that is the issue and no other alternatives.
Please let me know what I am doing wrong or could do better. Thank you in advance.
Dim trFrmDat As String
Dim trToDat As String
Dim dbsDelete As DAO.Database
Dim qdfToDelete As DAO.QueryDef
Dim countString As String
Dim count As Long
Set dbsDelete = CurrentDb
trFrmDat = InputBox("Trade Date To Be Deleted From [MM/DD/YY]:")
trToDat = InputBox("Trade Date To Be Deleted To [MM/DD/YY]:")
If Len(trFrmDat) <> 8 Or Len(trToDat) <> 8 Then
MsgBox ("The correct date or answer has not been entered. Process Aborted.")
Exit Sub
Else
countString = "SELECT COUNT(PK_ID) FROM AR_Consolidated WHERE [Trade Date] BETWEEN " & trFrmDat & " AND " & trToDat & ""
count = dbsDelete.OpenRecordset(countString).Fields(0).Value
Set qdfToDelete = dbsDelete.CreateQueryDef("", "DELETE FROM AR_Consolidated WHERE [Trade Date] BETWEEN " & trFrmDat & " AND " & trToDat & "")
qdfToDelete.Execute dbFailOnError
MsgBox ("" & count & " records have been deleted from AR_Consolidated")
End If
EDIT:
I ended up using one of the suggestions below, but still had formatting issues with the date, so I conceded I cannot keep the actual field as short text. I just injected an alter line and everything works perfectly.
DoCmd.RunSQL "ALTER TABLE AR_Consolidated ALTER COLUMN [Trade Date] Datetime"
In order to represent a date value in Jet SQL, you need to surround it with #, such that your SQL ends up something like this:
DELETE FROM AR_Consolidated WHERE [Trade Date] BETWEEN #01/01/18# AND #01/30/18#
Note that in general, combining strings with user inputs to make SQL statements is a bad idea. Aside from issues similar to yours -- properly representing date or other literals in SQL statements -- you are also liable to SQL injection, where a malicious user inserts additional SQL statements or clauses that cause your code to fail or do something unwanted. For example, the user could pass in as the second parameter the following string:
01/01/18 OR 1 = 1
and the resulting SQL statement:
DELETE FROM AR_Consolidated WHERE [Trade Date] BETWEEN 01/01/18 AND 01/01/18 OR 1 = 1
would delete all the records in AR_Consolidated.
The correct way to avoid both classes of issues is to use parameterized queries.
Dim sql As String
sql = _
"PARAMETERS FromDate DATETIME, TillDate DATETIME; " & _
"DELETE FROM AR_Consolidated " & _
"WHERE [Trade Date] BETWEEN FromDate AND TillDate"
Dim qdfToDelete As DAO.QueryDef
Set qdfToDelete = dbsToDelete.CreateQueryDef("", sql)
qdfToDelete.Parameters("FromDate") = trFromDate
qdfToDelete.Parameters("TillDate") = trToDate
'You may have to convert the string values to dates first
qdfToDelete.Execute dbFailOnError
For a comprehensive description of how to avoid SQL injection when programming against Jet / ACE, see the Microsoft Access and COM / Automation pages on bobby-tables.com.
I would take a different approach and use parameters instead of string concatenation.
The query's SQL would be something like this:
PARAMETERS [prmDateFrom] DateTime, [prmDateTo] DateTime;
DELETE *
FROM AR_Consolidated
WHERE [Trade Date] Between [prmDateFrom] And [prmDateTo];
Then to call my query in VBA:
Sub Something()
Dim trFrmDat As String
Dim trToDat As String
trFrmDat = InputBox("Trade Date To Be Deleted From [MM/DD/YY]:")
trToDat = InputBox("Trade Date To Be Deleted To [MM/DD/YY]:")
If Len(trFrmDat) <> 8 Or Len(trToDat) <> 8 Then
MsgBox ("The correct date or answer has not been entered. Process Aborted.")
Exit Sub
End If
Dim qdf As DAO.QueryDef
Dim count As Long
Set qdf = CurrentDb().QueryDefs("QueryName")
With qdf
.Parameters("[prmDateFrom]").Value = CDate(trFrmDat)
.Parameters("[prmDateTo]").Value = CDate(trToDat)
.Execute dbFailOnError
count = .RecordsAffected
End With
MsgBox " " & count & " records have been deleted from AR_Consolidated"
End Sub
However, you need to enhance your input validation as a normal string with 8 characters which cannot be converted to a date would cause a runtime error.
You can validate the input and then format the values:
trFrmDat = InputBox("Trade Date To Be Deleted From [MM/DD/YY]:")
trToDat = InputBox("Trade Date To Be Deleted To [MM/DD/YY]:")
If IsDate(trFrmDat) And IsDate(trToDat) Then
trFrmDat = Format(CDate(trFrmDat), "yyyy\/mm\/dd")
trToDat = Format(CDate(trToDat), "yyyy\/mm\/dd")
countString = "SELECT COUNT(PK_ID) FROM AR_Consolidated WHERE [Trade Date] BETWEEN #" & trFrmDat & "# AND #" & trToDat & "#"
End If
and similar for the delete SQL.
Using Access 2013
I have table in Access where Column "DueDate" is defined as "Date/Time"
System default date format is dd/mm/yyyy
Want to change List's Row Source through VBA, based on value in a textbox "txtDueDateUpto".
So, that I get all the task where the dude date is less than equal to the date entered by user in "txtDueDateUpto"
mySql = "SELECT TaskTbl.TaskID "
& " FROM TaskTbl " _
& " WHERE " _
& " DueDate is not Null and " _
& " Format (DueDate," & """dd/mm/yyyy""" & ") <= " & Format(CDate(Me.txtDueDateUpto.Value), "dd/mm/yyyy") _
Me.listTask.RowSource = mySql
I have 3 Tasks for testing purpose.
where DueDate is saved as
TaskID DueDate
1 25-17-2015
2 01-07-2015
3 29-06-2015
and, value in txtDueDateUpto is 06-07-2015
txtDueDateUpto format property is set to "Short Date"
I was expecting taskID 2,3 to be returned, with the given SQL, but I am getting taskID 2
I sat all night, trying many permutations and combinations, but cannot get what is that, I am doing wrong.
newbie for Access VBA. Pls help, thanks in advance.
Always handle dates as dates, not strings, no exceptions.
If your textbox has been assigned a date/time format, you don't even have to use CDate or DateValue because Access then reads that value as of data type Date.
However, you must concatenate the value with the SQL code as a properly formatted string expression of the date value:
mySql = "SELECT TaskTbl.TaskID "
& " FROM TaskTbl " _
& " WHERE " _
& " DueDate is not Null and " _
& " DueDate <= #" & Format(Me!txtDueDateUpto.Value, "yyyy\/mm\/dd") & "#"
If you are going to format the dates as strings -- and compare them -- then always use YYYY-MM-DD format:
& " Format (DueDate," & """yyyy-mm-dd""" & ") <= " & Format(CDate(Me.txtDueDateUpto.Value), "yyyy-mm-dd") _
However, I'm pretty sure that MS Access can just do date comparisons without the conversion:
DueDate <= CDate(Me.txtDueDateUpto.Value)
I have a page that displays results in a SQL database. And then I have another page that lets me edit whichever row I want to edit. One of the fields are dates. If added into the database through one of my pages it gets put in with the format (YEAR-MN-DY)(2014-04-11). When I go to UPDATE the date it then does arithmetic on the date. For example. If the date is currently 2014-04-11 and I update/change the date to 2010-01-01 it will replace the date with "2008" which is 2010 -1 - 1.
The variable is a string that is received through a HTML form.
strSQL = "UPDATE sales SET cust_id = " & intcust_id & ", agent_id = " & intagent_id & ", saledate = " & strsaledate & " WHERE sale_id = " & intsale_id & ""
Is the SQL query I am running.
Also, the DATE is VARCHAR2 in the database and used as a string throughout my VB code. I kept it this way because not everyone enters the date the same and this is for simplicity.
The subtraction is occurring because the date is not being interpreted as a date, but as a number because it is missing its quotes.
Before
strSQL = "UPDATE sales SET cust_id = " & intcust_id & ", agent_id = " & intagent_id & ", saledate = " & strsaledate & " WHERE sale_id = " & intsale_id & ""
After
strSQL = "UPDATE sales SET cust_id = " & intcust_id & ", agent_id = " & intagent_id & ", saledate ='" & strsaledate & "' WHERE sale_id = " & intsale_id & ""
The answer from WorkSmarter tackles the problem. I think however you should not use string concatenation. It is wide open to sql-injections and it is indeed much nicer, simpler and less error prone to use parameters. Something like
strSQL = "UPDATE sales SET cust_id = #custid, agent_id = #agentid, saledate = #salesdate WHERE sale_id = #saleid"
set custid = cmd.CreateParameter("#custid", adChar,adInput,10, incust_id)
set agentid = cmd.CreateParameter("#cagentid", adInteger,adInput,0, ) ...
I'm asuming you have an ADODB.Command by the name of cmd. By doing it like this you are making your code a lot safer and, in my opinion, more readable since you don't have to worry about quotes and single quotes all the time. There is a clear distinction between the sql command and the params/values involved.
You can find good documentation on parameter on http://www.w3schools.com/asp/met_comm_createparameter.asp
A friend and I have been trying for hours with little progress to a get a piece of code right for an invoicing system we're designing as a project.
We are trying to update the field InvoiceNo to a value (worked out earlier in the VisualBasic code), where the CustomerNo is the is a specific value and the FinishDate is between two dates. At first I was trying to use TO_DATE but then we realized that wasn't the same in the SQL that Access uses (after much searching).
This has been the simple statement I've been using to just test and try to get something working to then translate into VisualBasic and put in our variables. It's a little easier to read so I thought I'd provide it.
UPDATE tblJob SET tblJob.InvoiceNo = '8' WHERE tblJob.CustomerNo = '1' AND (tblJob.FinishDate BETWEEN cdate(format('08/09/2013', '##/##/####')) AND cdate(format('03/10/2013', '##/##/####')));
I have a feeling after looking at a few examples that our date is meant to be without an forward slashes. So I tried that and it wasn't working either.
Here's the VisualBasic code that has come out of all of this, it's exactly the same but using some variables rather than our set values that I've been using for testing.
DoCmd.RunSQL ("UPDATE tblJob SET tblJob.InvoiceNo = '" & newInvoiceNo & "' WHERE tblJob.CustomerNo = '" & VbCustNo & "' AND (tblJob.FinishDate BETWEEN cdate(format('" & Forms![frmMainMenu][txtFirstDate] & "', '##/##/####')) AND cdate(format('" & Forms![frmMainmenu][txtEndDate] & "', '##/##/####')));")
We had a look at: Convert a string to a date in Access and it helped us realize that it was cdate(format()) rather than TO_DATE as it is in Oracle. But we just can't seem to get it to run properly, any help would be much appreciated.
If you will be running the query from within an Access application session, you can let the db engine use the Access expression service to grab the values from the text boxes on your form.
Dim db As DAO.Database
Dim strUpdate As String
strUpdate = "UPDATE tblJob" & vbCrLf & _
"SET InvoiceNo = '" & newInvoiceNo & "'" & vbCrLf & _
"WHERE CustomerNo = '" & VbCustNo & "'" & vbCrLf & _
"AND FinishDate BETWEEN Forms!frmMainMenu!txtFirstDate AND Forms!frmMainmenu!txtEndDate;"
Debug.Print strUpdate
Set db = CurrentDb
db.Execute strUpdate, dbFailOnError
Set db = Nothing
However, if you prefer to build the literal date values from those text boxes into your UPDATE statement, you can use Format().
"AND FinishDate BETWEEN " & _
Format(Forms!frmMainmenu!txtFirstDate, "\#yyyy-m-d\#") & _
" AND " & Format(Forms!frmMainmenu!txtEndDate, "\#yyyy-m-d\#") & ";"
Either way, using a string variable to hold your UPDATE statement gives you an opportunity to examine the completed statement you're asking the db engine to execute.
You can view the output from Debug.Print in the Immediate window (go there with Ctl+g). For troubleshooting, you can copy the statement text from there and then paste it into SQL View of a new Access query.