I have the following VBA code for a .mdb Access file:
If DoCmd.RunSQL "SELECT DISTINCT Max(wk_ending_dt) FROM d2s_loader_performance" < (Date()-Weekday(Date())) Then
DoCmd.RunSQL "DELETE * FROM d2s_loader_performance_tbl WHERE wk_ending_dt = (Date()-Weekday(Date())-35)"
End If
It then highlights the following text: "SELECT DISTINCT Max(wk_ending_dt) FROM d2s_loader_performance" And gives the error Compile Error: Expected Then or GoTo.
Any ideas? I have a Then at the end of my conditional check, and to my understanding the double quotes are just for the SQL syntax. I'm using this If...Then condition to only allow record deletion if the max table date is less than the previous week's ending date.
You probably need to attack it this way:
Dim db as Database
Dim rec as Recordset
Set db = CurrentDB
Set rec = db.OpenRecordset ("SELECT DISTINCT Max(wk_ending_dt) FROM d2s_loader_performance")
If rec(0) < (Date()-Weekday(Date())) Then
DoCmd.RunSQL "DELETE * FROM d2s_loader_performance_tbl WHERE wk_ending_dt = #" & (Date()-Weekday(Date())-35) & "#"
EndIf
I'm assuming that "(Date()-Weekday(Date())-35)" part is supposed to be a calculation, so you need to surround it with ampersands (&), and dates in Access always need to have pound signs (#) before and after them if they're true Date fields.
The problem is that you can execute only action querys with DoCmd.RunSQL. So, you can't execute Select statement. For more info see this
My approach is to using something like this:
Sub SqlExecute()
Dim db As DAO.Database
Dim rsttemp As DAO.Recordset
Set db = CurrentDB
sql = "SELECT DISTINCT Max(wk_ending_dt) FROM d2s_loader_performance"
Set rsttemp = db.OpenRecordset(sql, dbOpenSnapshot)
If rsttemp(0)<(Date()-Weekday(Date())) Then
DoCmd.RunSQL "DELETE * FROM d2s_loader_performance_tbl WHERE wk_ending_dt #=" & (Date()-Weekday(Date())-35) & "#"
End If
Set rsttemp = Nothing
End Function
Related
I have built a query for duplicate records. I need to run some VBA code to check if the record is already in the table (query). If so, I need to delete the last record.
My form consists of a button with a value so that when you click the button, the data is insert into table
Dim qry As QueryDef
Set qry = CurrentDb.QueryDefs("duplicate records")
'which method do i use to see if the query got duplicate record'
With rstCategories
.MoveLast 0
End With
With rstCategories
rstCategories.Delete
End With
MsgBox "The problem already reported before!"
What I would do is run a quick query on your table:
Dim db as Database
Dim rec as Recordset
Set db = CurrentDB
Set rec = db.OpenRecordset ("SELECT * FROM MyTable WHERE MyValue = '" & Me.MyValue & "'")
If rec.EOF = true then
'No match found, so the value isn't in the table. Add it.
Else
'Match found. This value is already in the table.
MsgBox "This value is already in the table"
End If
ok i solved it
i created a query using the find duplicates query wizard.
then i insert this code in "form close"
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = Application.CurrentDb
Set rs = db.OpenRecordset("qry_Duplicates")
Do Until rs.EOF
rs.MoveFirst
rs.delete
rs.Close
Set rs = Nothing
Set rs = db.OpenRecordset("qry_Duplicates")
Loop
this code delete the entire row
I have a query that has CustID with mutiple Business affiliated with the CustID. I can't use Dlookup because it only returns one variable. I want to show on a form that for this custID, here are all the businesses it's affiliated it. I want the Businesses to show up into a field (business) in another table on the form.
I started out by this
Public Sub OpenRecordset()
Dim db As Database
Dim rs As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("Q:businesses")
Do While Not rs.EOF
T:Custinfo!business = NAME (I am lost in between on how to identify the custid and place the businesses into the table field as a Dlookup)
rs.movenext
Loop
rs.Close
Set rs = Nothing
db.Close
End Sub
I keep looking at other examples but can't seem to tie together where the dlookup replacement will take place and how will you have to put this on a form as a datasheet?
You don't need a DLookup. You could do one of two things:
1) Use a listbox and set the recordsource equal to your query (assuming Q:businesses has been appropriately defined to give the businesses as a result)
2) Still need your query to be appropriate, but you could create a string with all of the businesses in it:
Public Sub OpenRecordset()
Dim db As Database
Dim rs As Recordset
Dim StrBusinesses As String
Set db = CurrentDb
Set rs = db.OpenRecordset("qryBusinesses")
If rs.EOF and rs.BOF Then
MsgBox("No businesses exist for this Customer")
Exit Sub 'Or do whatever else you want if there are no matches
Else
rs.MoveFirst
End If
StrBusinesses = ""
Do While Not rs.EOF
StrBusinesses = StrBusinesses & rs!Business & ", "
rs.movenext
Loop
rs.Close
StrBusinesses = Left(StrBusinesses, Len(StrBusinesses) - 2)
Forms!MyForm.MyField = StrBusinesses 'Set the field equal to the string here
Set rs = Nothing
db.Close
End Sub
Of course this assumes that the query "Q:Business" is defined to get the appropriate info such as:
SELECT custID, business FROM tblBusinesses WHERE custID = X
where "X" is the custID you are looking for.
If you need to set the query dynamically, you will need to set a querydef.
EDIT to include querydef code***********************
Also changed the name of the query to "qryBusinesses" in the code above and below as I'm not sure whether you can make a query with a colon in it.
To set the querydef, put this at the beginning of the code:
Dim qdf As QueryDef
Set qdf = CurrentDb.QueryDefs("qryBusinesses")
qdf.SQL = "SELECT custID, business FROM tblBusinesses" _
& " WHERE custID = " & Forms!MyForm.CustID 'replace with actual form and field
This assumes that i) qryBusinesses exists already,
ii) custID is a number field
EDIT**************
If you define the query to look at the form itself, you would not need to set the sql, so if the query were defined (either in VBA or through the query wizard) as:
qdf.sql = "SELECT custID, business FROM tblBusinesses" _
& " WHERE custID = Forms!MyForm.CustID"
then you would not need to redefine the sql. However, it is a bit more dynamic to put the custID into the qdf itself as it is easier to debug any issues as you can see the exact sql that is being run in the original method.
I'm trying to make a Microsoft Access query depend on a value in another form's textbox.
This is the criteria, as it is now. Basically, any date between April 1st 2014, and March 31st 2015. This works well.
>=#2014-04-01# And <#2015-04-01#
I'd like to have a textbox with the year (with the current example 2014), and make the query criteria (2014, 2014+1) depend on this value.
I've tried to split the above syntax, then concatenate in the criteria, as such:
">=#" & "2014" & "-04-01# And <#" & "2015" & "-04-01#"
And I get an error "Data types in the criterion expression are incompatible".
1. Is it possible to concatenate in the query criteria?
I have also tried the SQL CONCAT(string1,string2,string3,..), to no avail.
If this is possible, then I guess I can use [Forms]![Form1].[Textbox1] and ([Forms]![Form1].[Textbox1] + 1) to replace the years.
If this is not possible...
2. Is there a better way to make the query criteria dynamic?
I tried to make the following solution work by creating a module with similar code:
Private m_varQueryParam As Variant
Public Function SetQueryParam(ByVal sValue as Variant)
m_varQueryParam = sValue
End Function
Public Function GetQueryParam() As Variant
GetQueryParam = m_varQueryParam
End Function
Query:
SELECT * FROM tblYourTable WHERE [FilterField] = GetQueryParam()
The VBA Code to launch the query will look like this.
SetQueryParam "your value here"
DoCmd.OpenQuery "qryYourQueryHere"
But I simply do not understand how to get this to work.
EDIT: I created a simple access database, to try to get this to work.
Textbox1, default value =Date()
bSave, button
tDateInfo, table: date (date/time), info (text) with random dates and info.
Query1:
SELECT tDateInfo.date, tDateInfo.info
FROM tDateInfo
WHERE (((tDateInfo.date)=GetQueryParam()));
Here's the form's vba code
Option Compare Database
Private Sub bSave_Click()
sValue = Me.TextBox1.Value
SetQueryParam (sValue)
End Sub
Here's the modules vba code
Option Compare Database
Option Explicit
'is this necessary?
Private m_varQueryParam As Variant
Public Function SetQueryParam(ByVal sValue As Variant)
m_varQueryParam = sValue
End Function
Public Function GetQueryParam() As Variant
GetQueryParam = m_varQueryParam
End Function
And the query criteria is GetQueryParam()
Thank you for your help.
Handling parameters and form fields is a little tricky with VBA. I created a simple table similar to yours as follows:
CREATE TABLE DateCalc (
ID AutoNumber,
FilterField DateTime
)
The following code will return your desired results:
Sub testthis()
Dim db As dao.database
Set db = CurrentDb ' use current database
Dim qd As dao.QueryDef
Set qd = db.CreateQueryDef("") ' create anaonymous querydef
' the SQL statement correctly concatenates the parameter (Useyear) and mm/dd strings
qd.sql = "SELECT * FROM DateCalc WHERE [FilterField] >= [UseYear]" & "-04-01 And [FilterField] < [UseYear]+1" & "-04-01"
qd!UseYear = Forms!DateCalc!txtYear ' set the value of se year from the Form WHICH MUST BE OPEN
' AND the TetBox filled with the year you desire - 2014 for this example.
Dim rs As dao.recordSet
Set rs = qd.OpenRecordset
MsgBox "ID=" & rs(0) & ", Date=" & rs(1)
End Sub
NEW VERSION
Sorry, there were a couple of date formatting problems with the first solution that the following code resolves. There are a number of other reasons for the error, so be sure the FormName is "DateCalc" and the TextBox is named "txtYear".
You should be able to generalize the following code for all your queries (do those actually work?). I pass the TableName in now as an example:
Sub DateFilter(TableName As String)
Dim db As dao.database
Set db = CurrentDb ' use current database
Dim qd As dao.QueryDef
Set qd = db.CreateQueryDef("") ' create anaonymous querydef
' the SQL statement correctly concatenates the parameter (Useyear) and mm/dd strings
Dim UseYear As Integer
UseYear = Forms!DateCalc!txtYear
Dim BegDate As Date
BegDate = CDate(UseYear & "-04-01")
Dim EndDate As Date
EndDate = CDate((UseYear + 1) & "-04-01")
qd.sql = "SELECT * FROM " & TableName & " WHERE [FilterField] >= [UseBegDate] And [FilterField] < [UseEndDate]"
qd!UseBegDate = BegDate
qd!UseEndDate = EndDate
Dim rs As dao.recordSet
Set rs = qd.OpenRecordset
Do While Not rs.EOF
MsgBox "ID=" & rs(0) & ", Date=" & rs(1)
rs.MoveNext
Loop
End Sub
I think I found a solution.
The following code defines the SQL as I require it, and changes the SQL for the Access query.
It's not ideal, because it requires me to rewrite all the SQL for the queries, but it works.
Sub ChangeQuery()
Dim Year, sqlTwo, StartDate, EndDate As String
Year = Me.txtYear.Value
StartDate = "4/1/" & Year
EndDate = "4/1/" & (Year + 1)
sqlTwo = "SELECT DateCalc.ID, DateCalc.FilterField FROM DateCalc WHERE (((DateCalc.FilterField)>=#" & StartDate & "# And DateCalc.FilterField<#" & EndDate & "#));"
tbTest.Value = sqlTwo
Dim oDB As Database
Dim oQuery As QueryDef
Set oDB = CurrentDb
Set oQuery = oDB.QueryDefs("Query1")
oQuery.SQL = sqlTwo
Set oQuery = Nothing
Set oDB = Nothing
End Sub
Private Sub Button_Click()
ChangeQuery
End Sub
I have an issue that I am trying to find a solution for.
I have a table, it looks something like this:
#myTable
id - Number
value - Text
models - Memo
I also have a table that looks something like this:
#myModels
id - Number
model - Text
notes - Memo
The #myTable.models value is a concatenation of different #myModels.model strings concatenated with the '|' character. For instance, it might have ModelA|ModelB|ModelC| or only ModelA|ModelC|
I need to filter the recordset from #myTable based on which model is currently selected. Right now I have something like this:
Dim sql As String
sql = "SELECT * FROM myTable"
Dim rs1 As Recordset
Set rs1 = DBO.Edit (sql)
sql = "SELECT model FROM myModels"
dim rs2 As Recordset
Set rs2 = DBO.Read (sql)
If Not rs2.BOF Then rs2.MoveFirst
While Not rs2.EOF
If Not rs1.BOF Then rs1.MoveFirst
While Not rs1.EOF
Dim models() As String
models = Split(rs1![models], "|")
Dim model As String
For Each model In models
If model = rs2.model Then
'Do some processing
End If
Next model
rs1.MoveNext
Wend
rs2.MoveNext
Wend
I was really hoping that I would be able to perform some type of regex on the query or in the filter, so it would possibly look something like this:
While Not rs2.EOF
rs1.Filter( "Insert Regex Here" )
If Not rs1.BOF Then rs1.MoveFirst
While Not rs1.EOF
' Do Some Processing here
rs1.MoveNext
Wend
rs2.MoveNext
Wend
I guess that my main issue is that the #myModels table has ~ 1000 records and is growing, while the #myTable table has more than 30k records in it. This takes an extremely long time to loop through when trying to loop through each record that many times.
Any solutions would be greatly appreciated.
did you try sql = "SELECT model FROM myModels where criteria"?
not sure what you mean by currently selected model but you can use tempVars to add temporary strings or whatever else you need
perhaps join in your sql?
can you specify in detail where is this model coming from and how its selected
Iterating over records in VBA is generally slower than a single SQL query. Running through a single SQL query would be faster than multiple loops with VBA:
SELECT myTable.*
FROM myTable, myModels
WHERE myTable.models LIKE "%" & myModels.model & "%"
In VBA:
Dim sql As String, rs As Recordset
sql = _
"SELECT * " & _
"FROM myTable, myModels " & _
"WHERE myTable.models LIKE ""*"" & myModels.model & ""*"""
Set rs = dbs.OpenRecordset(sql)
While Not rs.EOF
'Some processing here
Loop
Admittedly, this will still be slow, because this is an outer join, and because we're using the non-optimized LIKE operator.
If instead of the myTable.models field, you can add an intermediate table:
#myTableModels
tableID - number
modelID - number
with proper relationships, the resulting query will be near-instantaneous:
SELECT myTable.*
FROM (myTable
INNER JOIN myTableModels
ON myTable.id = myTableModels.tableID)
INNER JOIN myModels
ON myTableModels.modelID = myModels.ID
I have an Access Database and I'm using a pass through query to return records from an AS400 table. The connection string and pass through query work fine, but now I'm trying to populate the results of the p-t query into a local table within the db and my code is timing out. This is my first attempt at ADO so I'm disclaiming my code with "I'm not 100% sure what I'm doing!". Could you look at this and see if there is something obvious that I'm doing wrong? Any direction would be appreciated. Thank you in advance.
Sub mod_ADODBConnect()
Const NewTableName = "MyNewTable"
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim db As DAO.Database
Dim sSQL1 As String
Dim sSQL2 As String
sSQL1 = "SELECT ITMNUM, ITMDS, ITPKDS, MJCMCD, SBCMCD, STATUS, PRITIN, OGEXDT from PDBLLIB007.BLPMST07"
sSQL2 = "INSERT INTO ' & NewTableName & ' SELECT [" & sSQL1 & "].* from [" & sSQL1 & "]"
Set cn = New ADODB.Connection
cn.Open "Driver={Client Access ODBC Driver (32-bit)};" & _
"System=DC007; Uid=XXXXX; Pwd=XXXXXX; MgDSN=0; ConnType=2;" & _
"BlockSize=512; MaxFieldLen=2048; LazyClose=1; Prefetch=1; QueryTimeOut=0; Translate=1"
Set rs = New ADODB.Recordset
rs.Open sSQL1, cn, adOpenDynamic, adLockOptimistic
Do While Not rs.EOF
rs.MoveNext
Loop
Set db = CurrentDb
db.Execute ("sSQL2")
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
Set db = Nothing
End Sub
You have a pass-through query which works fine and returns the rows you want. Now you want to store those rows in a new local (Jet/ACE) table. Seems to me a simpler approach would be to use the pass-through as the data source in a new "make table" query.
SELECT * INTO MyNewTable FROM YourPassThruQuery;
Oops, looks like you meant to append those rows to an existing table.
INSERT INTO MyNewTable
SELECT * FROM YourPassThruQuery;
If the table structures don't match, you can use field lists for both tables.
INSERT INTO MyNewTable (fld1, fld2)
SELECT first_field, second_field FROM YourPassThruQuery;