VBA访问中的While循环

时间:2018-10-29 12:51:59

标签: sql vba ms-access

我具有删除和附加函数,这些函数根据用户的输入来构建Table1。因此,表1为每个用户附加了不同数量的记录。

我的SQL代码可以查找日期,但只能执行一次,因此我需要针对表的长度循环SQL代码。我不太擅长编码,我尝试了一个while语句,不确定是否可以在标准中使用变量Z,但是我希望它运行直到填充ID值最小的记录中的due_date。 / p>

这是我尝试过的:

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

说明:

  • 运行SQL之前

    Before Running SQL

  • 运行一次SQL之后

    After running SQL once

  • 单击几次后

    After clicking several times

目标是单击一次即可填充整个表格

2 个答案:

答案 0 :(得分:1)

您的变量Z包含DLookup函数返回的结果,该结果在子Command7_Click定义的第四行进行评估;除非重新定义该变量,否则该变量的值不会更改。

使用BuildCriteria函数会模糊代码的意图,因此很难建议最好的编写代码的方式...

编辑BuildCriteria对我来说是新的-感谢@Andre指出了这一点。

由于您的SQL语句的内容是静态的,因此不需要循环,因为循环内没有任何变化-SQL语句将更新所有符合您条件的记录,并且在以后的每次迭代中均不执行任何操作(除非您将记录更新到的值也满足选择条件)。


编辑

根据您的其他说明和屏幕截图,您可以通过迭代按ID字段排序的记录集并为每个记录依次计算适当的Due_date来完成任务-

>
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

尽管根据您的屏幕截图,您似乎正在尝试像Excel电子表格一样使用Access。

答案 1 :(得分:0)

请考虑实际上没有For循环,没有BuildCriteria甚至没有VBA SQL。将更新查询另存为单击按钮时运行的MS Access操作查询对象。

具体来说,您将需要几个域函数-DLookUpDSumDMax,在其中您可以计算持续时间的连续天数(即相关的聚合计算)然后将DateAdd的结果返回到相应的最大值ID DueDate ,而不会丢失 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

要演示样本数据:

更新前 (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

更新后 (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