I'm trying to get how many records were affected by a query, to know if it succeeds, if it doesn't I'll run another query.
I'm getting the parameter from a form that supposes to open the query and check
UPDATE attendance SET attendance.[attendance days] = [Forms]![attendace updater]![days]+[attendance days],
attendance.[attendance hours] = [Forms]![attendace updater]]![hours]+[attendance hours]
WHERE (((attendance.[id])=[Forms]![attendace updater]]![id]) AND ((attendance.year)=
[Forms]![attendace updater]]![year]) AND ((attendance.month)=[Forms]![attendace updater]]!
[month]));
In the attendance table: month is a number, year is a number, attendance days is a number, attendance hours is a number, but id is a text...
thanks :)
Private Sub btn_Click()
'create reference to you database object
Dim myDb As dao.Database
Set myDb = CurrentDb
'create ref to query definition object within scope of database object
Dim qdf as QueryDef
Set qdf = myDb.QueryDefs("queryName")
qdf.Execute
MsgBox qdf.RecordsAffected
End Sub
If the db.execute is expecting a parameter it's probably because it's not escaping a quote properly.
If you want to be able to see how many records WILL BE affected before running the query instead of just how may were affected after you run it you can use something like this:
SELECT COUNT(*) AS RecordCount FROM [MyTable] WHERE <Same WHERE clause as the UPDATE I am testing>
For the specific query:
SELECT COUNT(*) AS RecordCount
FROM attendance
WHERE (((attendance.[id])=[Forms]![attendace updater]]![id]) AND ((attendance.year)= [Forms]![attendace updater]]![year]) AND ((attendance.month)=[Forms]![attendace updater]]![month]))
Edit:
From VBA, you can use DCount. The exmple below assumes you are running the VBA in the context of the [attendace updater] form:
DCount("*","attendance","id='" & Me.id & "' AND year=" & Me.year & " AND month=" & Me.month)
Related
basic question.
I need to delete all null/blank rows of a table in my database. Trouble is there is no way to know how many fields there are, or the names of the fields before the delete. And I need to verify every field is null/blank before deleting. Not sure how to query for this in Access VBA.
In all the examples I find, they have a field name they can test for blanks.
Thanks in advance.
Change TestTabke to your table name. If you have an AutoNumber field, it must be skipped. I am using DAO. If you want ADO, convert the following code.
Function DeleteEmptyRows()
Dim db As DAO.database
Set db = CurrentDb
Dim rs As DAO.recordSet
Set rs = db.OpenRecordset("TestTable")
Do Until rs.EOF
For inx = 0 To rs.Fields.Count - 1
If IsNull(rs.Fields(inx).Value) Or Len(Trim(rs.Fields(inx).Value)) = 0 Then
Else: Exit For
End If
Next
If rs.Fields.Count = inx Then
rs.Delete
End If
rs.MoveNext
Loop
End Function
I followed the tips by others to produce an access query.
I have two tables. See figure1. And the result is figure2.
Figure1
http://img.libk.info/f1.png http://img.libk.info/f1.png
Figure2
http://img.libk.info/f2.png http://img.libk.info/f2.png
The method to generate the result query is solved in another question.
The query script :
TRANSFORM Nz(Count([number]),0) AS CountValue
SELECT Table1.ID
FROM Table1, Table2
WHERE (((Table2.number) Between [table1].[start] And [table1].[end]))
GROUP BY Table1.ID
PIVOT DatePart("yyyy",[ndate]);
My question is:
Is there anyway to write back the query result to table 1?
I want to add two new columns in table 1. And be able to add or update the query value to the field base on its "ID".
I'm not sure my description is clear or not. Hope you may understand and thanks for your help!
You won't be able to do it directly. However, here are two ways it could be done indirectly.
Method 1: Temp Table
This method is best for a quick-and-dirty one-time solution.
Create a Make-Table query based on your query and use it to make a temporary table.
Use the temporary table joined to [Table 1] to update your two new fields.
Delete the temporary table
Method 2: VBA Routine
This method is best when you want a repeatable method. It's overkill if you're only going to do it once. However, if you want calculated values for every year, you'll need to run it again.
Read the query into a recordset
Loop through the Recordset and for each ID, either
Run a sql statement to update table 1, or
open a second recordset querying by the ID and Edit/Update
Here's a simple version that updates the value for a single year.
Public Sub UpdateAnnualTotal(ByVal nYear As Long)
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim sSQL As String
Dim sId As String
Dim nTotal As Long
Set db = CurrentDb
sSQL = "SELECT [ID],[" & nYear & "_count"] FROM AnnualTotalsQuery"
Set rs = db.OpenRecordset(sSQL)
With rs
Do Until .EOF
sId = .Fields("ID").Value
nTotal = .Fields(nYear & "_count").Value
sSQL = "UPDATE [Table 1] SET [" & nYear & "_count"] = " & nTotal _
& " WHERE [ID] = '" & sId & "'"
db.Execute sSQL
.MoveNext
Loop
.Close
End With
End Sub
I have a query OUTPUT with cols DATE, TYPE, VALUE. I need to gather all the different dates into a variable so I can later create a CSV file for each unique DATE.
I tried creating a record set, and assigning the values of DATE to a variable as such:
Sub GetDates()
Dim rst As Recordset
Dim db As Database
Dim arrDates As Variant
Set db = CurrentDb
Set rst = db.OpenRecordset("SELECT Date FROM OUTPUT GROUP BY DATE; ")
arrDates = rst.GetRows()
but when I do:
For Each Item In arrDates
Debug.Print (Item)
Next
I only get one date printed (11/01/2012). If I run the query in Access, I see all 15 months.
I had to specify the number of rows:
arrDates = rst.GetRows(rst.RecordCount)
A better solution, as recommended by Remou:
Do Until rst.EOF
Debug.Print rst!Date
rst.MoveNext
Loop
Edit: I was reading the wrong MSDN help.
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
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