we are using Macro to retrieve data from MS Access using Query. I have used greater than symbol ">" and i have also used "#" symbol to denote time. However, It is not retriving the actual result. It is taking only the current month value. But it is not considering value for the next month values.
Please help us in resolving the issue
expiry = "29/06/2016"
expiry = CDate(expiry)
sql = "select sum(quantity) from table1 where symbol = """ & symbol & """ and symbol_type=""TF"""
sql = sql & " and expiry_date > #" & expiry & "#;"
Dim rs As Recordset
Set rs = db.OpenRecordset(sql)
If Not rs.EOF Then
If Not IsNull(rs(0)) Then
pos_lookup = rs(0)
end if
' Debug.print sql
select sum(quantity) from table1 where symbol = "NET" and symbol_type="TF" and expiry_date > #29/06/2016#;
The issue was with the data type of the field. It was "Text". It works now that I changed it to "Date/Time" data type.
Related
I am trying to set a quantity value based on a sum of the current quantity and then subtracting an amount based on a quantity value in another table.
My current thought process is: If QuantityA is less than or equal to Quantity B then subtract QuantityA from Quantity B.
I am no expert on SQL and MS VBA, so I was wondering how I can make an if statement with the two different tables.
Private Sub Command23_Click()
If QuantityA <= QuantityB Then
QuantityB = QuantityB - QuantityA
Else
MsgBox "You can not hire that many" & ToolName & "as there is only" & [DEPARTMENT TOOLS (stocked)].Quantity & "available"
End If
MsgBox "Your hire request has been successful"
End Sub
Any help would be appreciated
You can achieve what you're asking by opening a recordset containing the results of a query and comparing the values returned by the query. In order to restrict the query to the proper quantities you need to pass in the ID of the tool you are checking.
#June7 is correct about saving calculated data. The only time you would want to save it is if you are keeping a log of events or if speed of join queries becomes an issue (unlikely given proper DB structure)
toolId might be stored in a text box control for example
Function Something_Click(toolId as string)
Dim rs as Recordset
' create a recordset containing data from the two tables
Set rs = CurrentDB.OpenRecordset("SELECT A.TOOL_QTY AS TOOL_QTY_A, " _
& " B.TOOL_QTY AS TOOL_QTY_B, A.TOOLNAME AS TOOLNAME" _
& " FROM TABLE1 AS A " _
& " INNER JOIN TABLE2 AS B ON A.TOOL_ID = B.TOOL_ID" _
& " WHERE A.TOOL_ID = '" & toolId & "'")
' compare the values in the table
If rs![TOOL_QTY_A] <= rs![TOOL_QTY_B] Then
' your true condition, for example
' MsgBox "Success"
Else
' your false condition, for example
' MsgBox "Oops, not enough of " & rs![TOOLNAME]
End If
' close the recordset
rs.close
End Function
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.
I have a cross tab query with 'mmm-yyyy' formatted dates for Fields in the Columns.
I have used the below Design to create the query.
Cross Tab Design View
The problem I am having is the dates are not sorting correctly from Dec-17 down to Jul-16 in descending order. This is going to be a dynamic query with months changing every month so I want to use an additional table of data to do the sorting (as opposed to entering a list of month names in the Properties window).
How would I fix my query to get it to do this please?
Thanks for your help
Unfortunately, no matter how joined tables are sorted, crosstab will sort columns by default in alphabetical order, hence Apr, Dec, ... begins the order. To change or even filter column order in crosstabs, you would specify values in PIVOT Col IN () clause of SQL statement.
Since you need a dynamic query consider creating a querydef in VBA to update the SQL behind the crosstab where you dynamically update the PIVOT Col IN () clause. Of course, pass begin and end dates as needed or by parameters:
Public Sub BuildCrossTab()
Dim db As Database
Dim qdef As QueryDef
Dim strSQL As String, dates As String
Dim i As Integer, monthsDiff As Integer
Set db = CurrentDb
' DELETE PREVIOUS SAVED QUERY
For Each qdef in db.QueryDefs
If qdef.Name = "AccuralsCrosstabQ" Then
db.Execute "DROP Table " & qdef.Name, dbFailOnError
End If
Next qdef
' LOOP THROUGH ALL MONTHS BACKWARDS
dates = "("
monthsDiff = DateDiff("m", #7/1/2016#, #12/1/2016#)
For i = monthsDiff To 0 Step -1
dates = dates & " '" & Format(DateAdd("m", i, #7/1/2016#), "mmm-yyyy") & "',"
Next i
dates = dates & ")"
dates = Replace(dates, ",)", ")")
' PREPARE SQL STRING
strSQL = "TRANSFORM SUM(a.[Amount $]) AS SumAmount" _
& " SELECT a.Company, a.[Accrual ID], SUM(a.[Amount $]) As [Total Amount $]" _
& " FROM [Accruals Raw Data] a " _
& " GROUP BY a.Company, a.[Accrual ID]" _
& " PIVOT Format(a.[Posted Date], ""mmm-yyyy"")" _
& " IN " & dates
' CREATE QUERY
Set qdef = db.CreateQueryDef("AccuralsCrosstabQ", strSQL)
Set qdef = Nothing
Set db = Nothing
End Sub
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
When I click a button in Excel, I have the query below that retrieves data from an Access DB.
It pulls data based on a date in a particular cell. This works fine.
However, the query is not able to retrieve based on the "greater than or equal to" condition.
It only pulls dates "equal to" what's in that cell reference.
Dim N As Date
N = Sheets("sheet1").Range("h3")
rs.Open "SELECT SID, Requestor, Comments, Updated_Date, Updated_By FROM CL WHERE datevalue(Updated_Date) >= '" & N & "'", cn
datevalue(Updated_Date) returns a Date/Time value. So compare it to a Date/Time value instead of a string. Use # characters to delimit the Date/Time value.
Dim strSelect As String
strSelect = "SELECT SID, Requestor, Comments, Updated_Date, Updated_By " & _
"FROM CL WHERE datevalue(Updated_Date) >= " & Format(N, "\#yyyy-m-d\#")
rs.Open strSelect, cn