迭代 table 并更新匹配的记录集 - 访问 - Vba
Iterate over a table and update matching recordset - Access - Vba
问题
我构建了一个跟踪系统,其中包含来自其他 table 的独特 workID
和 Id
。我有一个名为 multiplier 的列,如果满足某些条件,我想更改它。我想更改每条记录的乘数列,其中:日期是星期日并且在星期六之前(意味着星期六的日期需要在 table 中)并且具有与星期六相同的 ID。
基本上这是一个奖金系统,如果跑步者在周六和周日工作,那么在那个周日他将获得 2 的乘数。我在 table 中打开每个周日和周六的记录集并尝试匹配它们。但它会跳过一些东西,因为星期六后面并不总是星期天。
代码
sqlFindSat = "Select WorkID, Date, Task, ID, Multiplier from tblA where (weekday([date]) = 7) order by date, id, workId"
sqlFindSun = "select WorkID, Date, Task, ID, Multiplier from tblA where ( weekday([date]) = 1 ) order by date, id, workId"
Set fwSun = db.OpenRecordset(sqlFindSun)
Set fwSat = db.OpenRecordset(sqlFindSat)
Do While Not fwSat.EOF
waitforsat = False
debug.print " Curr Sat: " & fwSat!Date & " Curr Sun: " & fwSun!Date
If WeekdayName(Weekday(fwSat!Date)) = "saturday" Then
If ((DateAdd("d", 1, fwSat!Date) = fwSun!Date) And (fwSun!ID = fwSat!ID)) Then
fwSun.Edit
fwSun!multiplier = 2
fwSun.Update
End If
End If
If Not fwSun.EOF Then
fwSun.MoveNext
End If
fwSat.MoveNext
Loop
只要星期六之后是星期日,我的代码就可以正常工作。一旦一个星期六后面没有跟着一个星期天,那么光标就会处于不同的水平,有时一个是。我不介意在 SQL 更新或其他任何情况下执行此操作,只要它在访问中有效即可。
注意:下面的样本不是真实样本。评论部分用于显示星期几。
样本table tblA
Workid | Date | ID | Multiplier | comments
12 10-11-2012 2 1 sunday
13 15-12-2012 4 1 Monday
14 10-10-2012 3 1 Saturday
25 11-10-2012 3 1 Sunday
17 8-10-2012 2 1 sunday
35 15-10-2012 4 1 Monday
45 8-10-2012 3 1 Saturday
50 9-10-2012 3 1 Sunday
tblA 运行 代码后的最终输出:
Workid | Date | ID | Multiplier | comments
12 10-11-2012 2 1 Sunday
13 15-12-2012 4 1 Monday
14 10-10-2012 3 1 Saturday
25 11-10-2012 3 2 Sunday
17 8-10-2012 2 1 sunday
35 15-10-2012 4 1 Monday
45 8-10-2012 3 1 Saturday
50 9-10-2012 3 2 Sunday
正如您从 table 中看到的那样,前面的星期日。
根据您要访问的记录数量,我认为这应该适合您:
第一个函数只是循环遍历 fwsat
RecordSet
中的所有星期日。对于每个星期天,它都会调用 PrecedingSaturday
函数,并检查该 ID 是否有一个星期六,该星期六是否在该星期日的一天之内。
Public Function CheckSunday()
sqlFindSat = "Select WorkID, Date, Task, ID, Multiplier from tblA where (weekday([date]) = 7) order by date, id, workId"
sqlFindSun = "select WorkID, Date, Task, ID, Multiplier from tblA where ( weekday([date]) = 1 ) order by date, id, workId"
Set fwSun = db.OpenRecordset(sqlFindSun)
Set fwsat = db.OpenRecordset(sqlFindSat)
'For all Sundays
Do While Not fwSun.EOF
'If this Sunday has a Preceding Saturday.
If PrecedingSaturday(fwsat, fwSun!id, fwSun!Date) Then
'Update multiplier to 2 for this Sunday
fwSun.Edit
fwSun!multiplier = 2
fwSun.Update
End If
fwSun.MoveNext
Loop
End Function
此函数只接受包含所有星期六的 RecordSet
,并搜索它们以查看是否有任何一个在所讨论的星期日之前。如果是,则 returns 为真。
Public Function PrecedingSaturday(fwsat As Recordset, intID As Integer, dte As Date) As Boolean
Dim blnPrecedingSaturday As Boolean
blnPrecedingSaturday = False
'For all Saturdays while a preceding Saturday hasn't already been found
Do While Not fwsat.EOF And blnPrecedingSaturday = False
'If Saturday's ID and Sunday's id match
If fwsat!id = intID Then
'If the Saturday and Sunday happened within 1 day
If DateDiff("d", fwsat!Date, dte) = 1 Then
'This is a preceding Saturday
blnPrecedingSaturday = True
End If
End If
fwsat.MoveNext
Loop
PrecedingSaturday= blnPrecedingSaturday
End Function
这是粗略的代码,因为我没有 table 结构来正确测试它。虽然我认为它应该适用于你正在寻找的东西。
VBA不需要这样做;您还可以 运行 使用自联接的 SQL 查询并直接进行更新。
对于具有相同 ID 的前一个星期六的记录的所有星期日行,此查询会将乘数更改为 2。
语法应该是:
UPDATE tblA t1
INNER JOIN tblA t2 ON t1.ID = t2.ID AND t2.Date = DATEADD('d', -1, t1.date)
SET t1.Multiplier = 2
WHERE WEEKDAY(t1.date) = 1 -- assuming 1 is Sunday, might depend on regional setting
如果您想在执行更新之前查看会发生什么,只需将更新更改为 select * 并删除 set 语句。
或者在 运行 之前备份 table :)
问题
我构建了一个跟踪系统,其中包含来自其他 table 的独特 workID
和 Id
。我有一个名为 multiplier 的列,如果满足某些条件,我想更改它。我想更改每条记录的乘数列,其中:日期是星期日并且在星期六之前(意味着星期六的日期需要在 table 中)并且具有与星期六相同的 ID。
基本上这是一个奖金系统,如果跑步者在周六和周日工作,那么在那个周日他将获得 2 的乘数。我在 table 中打开每个周日和周六的记录集并尝试匹配它们。但它会跳过一些东西,因为星期六后面并不总是星期天。
代码
sqlFindSat = "Select WorkID, Date, Task, ID, Multiplier from tblA where (weekday([date]) = 7) order by date, id, workId"
sqlFindSun = "select WorkID, Date, Task, ID, Multiplier from tblA where ( weekday([date]) = 1 ) order by date, id, workId"
Set fwSun = db.OpenRecordset(sqlFindSun)
Set fwSat = db.OpenRecordset(sqlFindSat)
Do While Not fwSat.EOF
waitforsat = False
debug.print " Curr Sat: " & fwSat!Date & " Curr Sun: " & fwSun!Date
If WeekdayName(Weekday(fwSat!Date)) = "saturday" Then
If ((DateAdd("d", 1, fwSat!Date) = fwSun!Date) And (fwSun!ID = fwSat!ID)) Then
fwSun.Edit
fwSun!multiplier = 2
fwSun.Update
End If
End If
If Not fwSun.EOF Then
fwSun.MoveNext
End If
fwSat.MoveNext
Loop
只要星期六之后是星期日,我的代码就可以正常工作。一旦一个星期六后面没有跟着一个星期天,那么光标就会处于不同的水平,有时一个是。我不介意在 SQL 更新或其他任何情况下执行此操作,只要它在访问中有效即可。
注意:下面的样本不是真实样本。评论部分用于显示星期几。
样本table tblA
Workid | Date | ID | Multiplier | comments
12 10-11-2012 2 1 sunday
13 15-12-2012 4 1 Monday
14 10-10-2012 3 1 Saturday
25 11-10-2012 3 1 Sunday
17 8-10-2012 2 1 sunday
35 15-10-2012 4 1 Monday
45 8-10-2012 3 1 Saturday
50 9-10-2012 3 1 Sunday
tblA 运行 代码后的最终输出:
Workid | Date | ID | Multiplier | comments
12 10-11-2012 2 1 Sunday
13 15-12-2012 4 1 Monday
14 10-10-2012 3 1 Saturday
25 11-10-2012 3 2 Sunday
17 8-10-2012 2 1 sunday
35 15-10-2012 4 1 Monday
45 8-10-2012 3 1 Saturday
50 9-10-2012 3 2 Sunday
正如您从 table 中看到的那样,前面的星期日。
根据您要访问的记录数量,我认为这应该适合您:
第一个函数只是循环遍历 fwsat
RecordSet
中的所有星期日。对于每个星期天,它都会调用 PrecedingSaturday
函数,并检查该 ID 是否有一个星期六,该星期六是否在该星期日的一天之内。
Public Function CheckSunday()
sqlFindSat = "Select WorkID, Date, Task, ID, Multiplier from tblA where (weekday([date]) = 7) order by date, id, workId"
sqlFindSun = "select WorkID, Date, Task, ID, Multiplier from tblA where ( weekday([date]) = 1 ) order by date, id, workId"
Set fwSun = db.OpenRecordset(sqlFindSun)
Set fwsat = db.OpenRecordset(sqlFindSat)
'For all Sundays
Do While Not fwSun.EOF
'If this Sunday has a Preceding Saturday.
If PrecedingSaturday(fwsat, fwSun!id, fwSun!Date) Then
'Update multiplier to 2 for this Sunday
fwSun.Edit
fwSun!multiplier = 2
fwSun.Update
End If
fwSun.MoveNext
Loop
End Function
此函数只接受包含所有星期六的 RecordSet
,并搜索它们以查看是否有任何一个在所讨论的星期日之前。如果是,则 returns 为真。
Public Function PrecedingSaturday(fwsat As Recordset, intID As Integer, dte As Date) As Boolean
Dim blnPrecedingSaturday As Boolean
blnPrecedingSaturday = False
'For all Saturdays while a preceding Saturday hasn't already been found
Do While Not fwsat.EOF And blnPrecedingSaturday = False
'If Saturday's ID and Sunday's id match
If fwsat!id = intID Then
'If the Saturday and Sunday happened within 1 day
If DateDiff("d", fwsat!Date, dte) = 1 Then
'This is a preceding Saturday
blnPrecedingSaturday = True
End If
End If
fwsat.MoveNext
Loop
PrecedingSaturday= blnPrecedingSaturday
End Function
这是粗略的代码,因为我没有 table 结构来正确测试它。虽然我认为它应该适用于你正在寻找的东西。
VBA不需要这样做;您还可以 运行 使用自联接的 SQL 查询并直接进行更新。
对于具有相同 ID 的前一个星期六的记录的所有星期日行,此查询会将乘数更改为 2。
语法应该是:
UPDATE tblA t1
INNER JOIN tblA t2 ON t1.ID = t2.ID AND t2.Date = DATEADD('d', -1, t1.date)
SET t1.Multiplier = 2
WHERE WEEKDAY(t1.date) = 1 -- assuming 1 is Sunday, might depend on regional setting
如果您想在执行更新之前查看会发生什么,只需将更新更改为 select * 并删除 set 语句。
或者在 运行 之前备份 table :)