取消MS Access 2007绑定表单上的单个字段的更新

时间:2011-04-20 18:46:42

标签: ms-access ms-access-2007

我可能会过度思考这一点,但我看到各种各样的潜在问题......

我有一张桌子,我称之为师父。在其他项目中,它包含一个名为Serial的字段。我思想这将是一个静态项目 - 即,它永远不会改变(一旦最初分配),对于Master中的任何给定行。我现在发现可以更改,不仅如此,我还需要存储这些更改的历史记录。

我可以将Serial打破到一个单独的表中,其中每一行都有一个MasterId,EffectiveDate和Termination Date(Master行的当前Serial将是一行(并且只有一行代码) Null TerminationDate)。到目前为止,这太好了....

现在我问的问题是:我有一个基于Select from Master构建的绑定表单,包括Serial。

我想做的事情我想做的是,为了让这个可更改性对用户透明,可以将对Serial文本框所做的任何更改短路,可能在文本框BeforeUpdate事件中。然后我使用代码终止串行表中的当前行&插入一个新行,该行变为当前行并显示在文本框中。我(我认为)需要取消表单记录集中的更新,不用丢失用户对其他字段所做的任何更改....

正是在这一点上,我的大脑出去吃午饭,因为我对未绑定的表格更加舒服。保存按钮。我建议可以这样做吗?什么伎俩和陷阱我需要知道吗?如果需要,我可以将表单上的Serial字段设置为只读,并需要弹出窗口来编辑它,但如果可以,我宁愿避免使用。

*的 *修改

希望这会有所帮助:

之前

table Master
  Id             AutoNumber  PK
  Serial         Text(20)
  --other fields

目前的frmMaster RecordSource:

SELECT Id, Serial, yada, yada FROM Master WHERE blahBlah

table Master
  Id             AutoNumber  PK
  --other fields

table Serial
  Id             AutoNumber  PK
  MasterId       Long
  Serial         Text(20)
  EffDt          Date/Time
  TermDt         Date/Time

新的frmMaster RecordSource:

SELECT Master.Id, Serial.Serial, yada, yada 
FROM Master LEFT JOIN Serial ON Master.Id = Serial.MasterId 
WHERE Serial.TermDt is Null AND blahBlah

表单上的“编辑”应该导致:

  1. Serial中的选定行获取TermDt(Now())。对此行的Serial.Serial值不进行任何更改。
  2. 创建Serial中的新行,使用新的Serial,相同的MasterId和EffDt = Now()
  3. 新的序列号显示在表单上,​​最好是让用户看起来就好像他们刚刚编辑过一样。
  4. 对表单上其他字段所做的任何更改都会保存。
  5. 再次编辑

    好的,所以HansUp给出了一个答案,看起来它涵盖了我需要的大部分内容。我剩下的绊脚石可能不是一个问题(但如果是这样的话,有人可以解释原因吗?)。

    添加Master的用例非常简单,但是在更新Serial的用例中我仍然感到困惑:如果txtSerial绑定到Serial.Serial,那么用户更改txtSerial的内容,是否会尝试更新Serial.Serial的内容以进行匹配?如何在更改时添加串行(看起来应该可以处理),阻止更新现有的串行?

3 个答案:

答案 0 :(得分:1)

您尚未向我们展示Serial表的示例数据。我很好奇它是否会像这样:

Id MasterId Serial  date_added
 1        1 foo      4/21/2011 7:00:00 AM
 2        1 bar      4/21/2011 9:00:00 AM
 3        1 foo      4/21/2011 11:00:00 AM
 4        2 asldkjf  4/4/2011 1:00:00 PM

每当您需要使用EffDt和TermDt表示的Serial行时,您可以使用相关的子查询。

SELECT
    s.Id,
    s.MasterId,
    s.Serial,
    s.date_added AS EffDt,
    (SELECT TOP 1 sub.date_added
    FROM Serial As Sub
    WHERE
        sub.MasterId = s.MasterId
        And sub.date_added > s.date_added
    ORDER BY sub.date_added) AS TermDt
FROM Serial AS s
ORDER BY
    s.MasterId,
    s.date_added;

我意识到你的问题更广泛。就目前而言,这件作品是我可以包裹的。但它是否符合您的要求?

更新:我使用的是我的Serial表版本。我创建了一个主表,其中包含自动编号Id,文本序列,以及其他2个文本字段,Other_field1和Other_field2。然后创建一个简单的连续形式绑定到“SELECT Id,Serial,Other_field1,Other_field2 FROM Master Order By Id;”。

这是表单的代码:

Option Compare Database
Option Explicit
Dim varSerialOldvalue As Variant

Private Sub Form_AfterInsert()
    addSerialRow
End Sub

Private Sub Form_AfterUpdate()
    Dim strSql As String
    If Me.txtSerial.value <> varSerialOldvalue Then
        addSerialRow
    End If
End Sub

Private Sub Form_BeforeUpdate(Cancel As Integer)
    varSerialOldvalue = Me.txtSerial.OldValue
End Sub

Private Sub addSerialRow()
    Dim strSql As String
    Dim strMsg As String

On Error GoTo ErrorHandler

    strSql = "INSERT INTO Serial(MasterId, Serial, date_added)" & _
        vbNewLine & "VALUES(" & Me.txtid & ",'" & _
        Replace(Me.txtSerial, "'", "''") & "', #" & _
        Format(Now(), "yyyy/mm/dd hh:nn:ss") & "#);"

    CurrentDb.Execute strSql, dbFailOnError

ExitHere:
    On Error GoTo 0
    Exit Sub

ErrorHandler:
    strMsg = "Error " & Err.Number & " (" & Err.description _
        & ") in procedure addSerialRow" & vbNewLine & _
        "SQL: " & strSql
    MsgBox strMsg
    GoTo ExitHere
End Sub

这是你想要完成的事情的有用起点吗?

Update2 :您说 txtSerial绑定到Serial.Serial ;但是我的方法将txtSerial直接绑定到Master表中的Serial字段......这是我原先认为你提出的。这种方法现在有什么问题?

答案 1 :(得分:0)

实际上,我不明白为什么要阻止更改文本框?如果我读的是正确的,你所说的是如果文本框改变了,那么你需要保存以前的当前数据并在更改前记录吗?

如果是上述情况,那么只需在序列文本框的更新后事件中,运行一个追加查询,该查询从表中获取当前记录并复制(将其附加到其他地方)。

当您有绑定表单时,对表单上控件的更改不会提交给实际的基础表。如果您的代码或进程或某些追加查询或VBA代码查看或从表中复制该行,则所有旧值仍将保持不变。

因此绑定表单并不意味着文本框中的每个更改都写入表中,但实际上整个记录只在保存记录时写入表中,这就是为什么更新事件之前的表单有取消可以阻止记录写入发生,直到满足您的规则等。

因此,您只需要在更新事件后的串行框中需要一行或两行(除非对文本框进行更改,否则该事件不会触发)从表中复制当前记录,该记录将具有所有旧值,包括旧的序列号。

答案 2 :(得分:0)

如果Master不经常更改且不太大,则在保存时,添加添加了whoChanged记录和时间段的整个Master记录。然后,当您想要查看Serial中的更改时,只需在Serial上执行GroupBy,您就可以看到时间和更改者。

这对于一个字段来说是过度的,但通常提供记录更改的好方法。