Reputation: 61
I have delete and append functions that build Table1 based on inputs from the user. Therefore Table1 has a different number of records appending to it for every user.
My SQL code works to find the dates, but it only does it once, I need to loop the SQL code for the length of the table. I'm not great at coding, I tried a while statement, not sure if I can use variable Z in the criteria for that, but I want it to run until the due_date in the record with the smallest ID value has been filled.
Here's what I tried:
Private Sub Command7_Click()
Y = DMax("ID", "Table1", BuildCriteria("Due_date", dbDate, "Null"))
A = DMin("ID", "Table1", BuildCriteria("Due_date", dbDate, "Not Null"))
X = DMin("ID", "Table1")
Z = DLookup("Due_date", "Table1", BuildCriteria("ID", dbLong, CStr(X)))
B = DLookup("Duration", "Table1", BuildCriteria("ID", dbLong, CStr(Y)))
C = DLookup("Due_date", "Table1", BuildCriteria("ID", dbLong, CStr(A)))
E = DateAdd("d", -B, C)
Dim SQL As String
SQL = "UPDATE Table1 " & _
"SET " & BuildCriteria("Due_date", dbDate, CStr(E)) & " " & _
"WHERE " & BuildCriteria("ID", dbLong, CStr(Y))
While Z Is Null
DoCmd.RunSQL SQL
End While
End Sub
To illustrate:
The goal would be to click once and the whole table fills
Upvotes: 1
Views: 1859
Reputation: 107567
Consider actually no For
loop, no BuildCriteria
and even no VBA SQL. Save the update query as an MS Access action query object that is run on button click.
Specifically, you would need several domain functions --DLookUp
, DSum
, and DMax
-- where you calculate a running sum of duration days (i.e., a correlated aggregate computation) and then DateAdd
the result to the DueDate of the corresponding maximum ID
with no missing DueDate.
SQL
UPDATE myTable d
SET d.DueDate = DateAdd("d", -1 * DSum("Duration", "DueDateDuration", "ID >= " & d.ID),
DLookUp("DueDate", "DueDateDuration", "ID = " &
DMax("ID", "DueDateDuration", "DueDate IS NOT NULL")
)
)
WHERE d.DueDate IS NULL;
VBA
Private Sub Command7_Click()
DoCmd.OpenQuery "mySavedUpdateQuery" ' WITH WARNINGS
CurrentDb.Execute "mySavedUpdateQuery" ' WITHOUT WARNINGS
End Sub
To demonstrate on sample data:
Before Update (mytable)
ID Item Duration DueDate
2674 Issue 1 2/18/2019
2675 Shipping 1 2/19/2019
2678 Completed 0 2/20/2019
2679 Issue 1
2680 Shipping 10
2681 Other 6
2682 Buy Off 6
2683 Punch List 3
2684 Completed 0 3/29/2019
After Update (mytable)
ID Item Duration DueDate
2674 Issue 1 2/18/2019
2675 Shipping 1 2/19/2019
2678 Completed 0 2/20/2019
2679 Issue 1 3/3/2019
2680 Shipping 10 3/4/2019
2681 Other 6 3/14/2019
2682 Buy Off 6 3/20/2019
2683 Punch List 3 3/26/2019
2684 Completed 0 3/29/2019
Upvotes: 0
Reputation: 16015
Your variable Z
contains the result returned by the DLookup
function when evaluated as the fourth line of the definition of your sub Command7_Click
; the value of this variable will not change unless the variable is redefined.
The intent of your code is somewhat obscured by the use of your BuildCriteria
function, so it is difficult to advise the best way to write the code...
Edit: BuildCriteria is a new one for me - thanks to @Andre for pointing this out.
Since the content of your SQL statement is static, there should be no need for a loop, as nothing is changing within the loop - the SQL statement will update all records which meet your criteria and will do nothing for every subsequent iteration (unless, that is, the value to which you are updating the records also fulfils the selection criteria).
EDIT
Based on your additional explanations & screenshots, you could approach the task by iterating over a recordset sorted by your ID
field and successively calculating the appropriate Due_date
for each record - something like:
Private Sub Command7_Click()
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim dat As Date
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset("select * from Table1 order by ID desc")
With rst
If Not .EOF Then
.MoveFirst
Do Until .EOF
If Not IsNull(!Due_date) Then
dat = !Due_date
Else
dat = DateAdd("d", -!Duration, dat)
.Edit
!Due_date = dat
.Update
End If
.MoveNext
Loop
End If
.Close
End With
Set rst = Nothing
Set dbs = Nothing
End Sub
Though based on your screenshots, it seems that you are trying to use Access like an Excel spreadsheet.
Upvotes: 1