【问题标题】:How do I update multiple subform records in a linear fashion from a main form?如何从主表单以线性方式更新多个子表单记录?
【发布时间】:2018-08-30 15:52:01
【问题描述】:

我在主窗体中有一个日期文本框,它在子窗体中输出 6 个连续日期(2 周间隔)。作为主表单的AfterInsert() 事件的一部分,子表单将填充这些日期。

Private Sub Form_AfterInsert()
    Dim strSQL As String
    Dim i As Integer
    For i = 2 To 12 Step 2
        strSQL = "INSERT INTO tbl_Date (DateDescriptionID, TestDate) "
        strSQL = strSQL & "SELECT " & Me.tbDescriptionID & ", (DateAdd('ww', " & i & ", #" & Me.tbStartDate & "#));"
        CurrentDb.Execute strSQL, dbFailOnError
    Next i
End Sub

如果用户更改主表单中的日期文本框,我希望子表单日期能够反映该更改。我尝试了UPDATE 查询以用新日期替换现有日期,但在尝试对齐主外键时遇到了麻烦。我只能用空值(null)替换现有日期,但不确定如何用新日期相应地更新现有日期。

Private Sub tbStartDate_AfterUpdate()
    Dim strSQL As String
    strSQL = "UPDATE tbl_Date "
    strSQL = strSQL & "SET [TestDate] = NULL "
    strSQL = strSQL & "WHERE [DateDescriptionID] = " & Me.DescriptionID & ";"
    CurrentDb.Execute strSQL, dbFailOnError
End Sub

用户输入 05/01/2018

Date           Data
05/15/2018     Apple
05/29/2018     Banana
06/12/2018     Orange
06/26/2018     Strawberry
07/10/2018     Pineapple
07/24/2018     Peach

用户更改条目至 06/30/2018

Date           Data
07/14/2018     Apple
07/28/2018     Banana
08/11/2018     Orange
08/25/2018     Strawberry
09/08/2018     Pineapple
09/22/2018     Peach

【问题讨论】:

  • 您不能将日期更新为与原始日期相同的 DateDiff 期间。航空代码 - NewDateValue = CurrentDateValue + DateDiff("D" ,OldStartDate,NewStartDate)
  • 好建议!我将如何通过旧的开始日期?我应该在BeforeUpdate() 事件期间使用全局变量吗?
  • 为什么不存储间隔,而不是日期,或者如果恒定 2 周,只需存储订单序列并计算日期= DateAdd("ww",2 * countOfFormerElements,StartDate)
  • @Minty 我可以通过Me.tbStartDate.OldValue访问控件的旧值
  • @ComputerVersteher 间隔将始终保持在 2 周。如何将订单序列存储在UPDATE SQL 中?

标签: sql ms-access vba


【解决方案1】:

跳过所有 SQL 内容并使用 DAO 和 recordsetclone - 更清洁、更快速且具有自动更新功能:

Private Sub Form_AfterInsert()

    Dim rs As DAO.Recordset
    Dim i As Integer

    Set rs = Me!NameOfYourSubformCONTROL.Form.RecordsetClone
    For i = 2 To 12 Step 2
        rs.AddNew
            rs!DateDescriptionID.Value = Me!tbDescriptionID.Value
            rs!TestDate.Value = DateAdd("ww", i, Me!tbStartDate.Value)
        rs.Update
    Next i
    rs.Close

End Sub

和:

Private Sub tbStartDate_AfterUpdate()

    Dim rs As DAO.Recordset
    Dim i As Integer

    Set rs = Me!NameOfYourSubformCONTROL.Form.RecordsetClone

    rs.MoveFirst
    While Not rs.EOF
        i = i + 2
        rs.Edit
           rs!TestDate.Value = DateAdd("ww", i, Me!tbStartDate.Value)
        rs.Update
        rs.MoveNext
    Wend        
    rs.Close

End Sub

【讨论】:

  • 你说得对,它更干净、更快捷。我将在我的数据库中使用 DAO 进行更多探索。
【解决方案2】:

考虑使用相关子查询,但由于 MS Access 仅允许对 UPDATE 语句的可更新查询,请使用 DCount 域聚合。此外,请考虑使用parameterization 将 SQL 代码与 VBA 数据值完全分开。

具体来说,DCount 生成 TestDate 列的排名顺序,然后将每个列乘以 14,即所需的天数间隔长度(例如,1*14、2*14、3*14 )。此解决方案不需要循环。

SQL (另存为存储的 Access 查询)

PARAMETERS [DescIDParam] Long;
UPDATE tbl_Date t
SET t.[TestDate] = DCount("*", "tbl_Date", "TestDate <= #" & t.[TestDate] & "#") * 14, t.[TestDate])
WHERE t.[DateDescriptionID] = [DescIDParam]

VBA

Private Sub tbStartDate_AfterUpdate()
    Dim qdef As QueryDef

    Set qdef = CurrentDb.QueryDefs("mySavedUpdateQuery")

    ' BIND VALUE TO PARAMETER
    qdef![DescIDParam] = Me.tbDescriptionID

    ' EXECUTE ACTION
    qdef.Execute dbFailOnError

    Set qdef = Nothing
End Sub

【讨论】:

    【解决方案3】:

    我选择 SQL:

    我假设有一个名为 tblData 的表,其中包含字段 ID(PK, Autoincrement) 、Data (Text) 和 Sort(Long)

    ID     Data        Sort
    1     Apple          3
    2     Banana         5
    3     Orange         2
    4     Strawberry     1
    5     Pineapple      4
    6     Peach          6
    

    查询:

    SELECT Data, DateAdd("ww", 2 * Sort, Forms!ParentForm!txtDate) as ComputedDate FROM tblData Order By Sort;
    

    将其用作子表单的记录源。如果txtDate 存储在表中,您可以加入或查找。 只存储一个日期,始终保持最新。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多