2011-04-20 46 views
0

我可能是这个得太多,但我看到各种各样的潜在问题....取消单场的更新对MS Access 2007的结合形式

我有我会打电话给法师的表。除其他项目外,它还包含一个名为Serial的字段。我想认为这将是一个静态的项目 - 即,它永远不会改变(一旦初始分配),为主任何给定的行。我现在发现它可以改变,不仅如此,我需要存储那些改变的历史。

我可以将串行分成一个单独的表,其中每一行将有一个MasterId,EffectiveDate和Termination Date(主行的当前串行将是一个(并且只有一个代码强制的)行,一个空终止日期)。到目前为止,这么好....

现在我问的问题是:我有一个绑定窗体构建在Select从主包含Serial上。

什么我认为我想要做的,使这种可变性对用户透明,是短路任何对串行文本框,可能在文本框BeforeUpdate事件进行的更改。然后,我会使用代码来终止串行表中的当前行&插入一个新行,它变为当前行并显示在文本框中。我会(我认为)需要取消窗体的记录集中的更新,没有失去了用户对其他字段所做的任何更改....

在这一点上,我的大脑出去吃午餐,我仍然可以更加舒适地使用未绑定的表格&保存按钮。我能按照建议做到吗?我需要了解哪些陷阱&?如果需要的话,我可以将表单中的Serial字段设置为只读,并且需要弹出窗口才能对其进行编辑,但是如果可以的话,我宁愿避免。

* *编辑

希望这有助于:

以前

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

当前frmMaster记录来源:

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记录来源:

表单上
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. 选择行串行得到TermDt填充(NOW()) 。对此行的Serial.Serial的值不做任何更改。
  2. 在串行一个新行被创建,用新的串口,相同MasterId和EffDt = NOW()显示在形式
  3. 新串行,优选使得它看起来给用户,如果他们想在适当位置刚刚编辑。
  4. 对表单上其他字段所做的任何更改都会被保存。

编辑,再次

好了,所以HansUp给了,看起来像它涵盖了大多数的什么,我需要一个答案。我剩下的绊脚石甚至可能不是问题(但如果是这样的话,有人可以解释为什么吗?)。

添加主的用例是非常简单的,但是在改变,我仍然困惑串行更新的使用情况:如果txtSerial势必Serial.Serial,和用户改变txtSerial内容,深得访问尝试更新Serial.Serial的内容以匹配?如何在变更时添加一个串行(这看起来应该是一种享受),防止更新现有的串行?

+0

这是一个难以想象的IMO。向我们展示包含Master和SerialHistory表格相关字段的示例。 – HansUp 2011-04-20 19:09:23

+0

在你的例子中,串行字段是否成为主表和串行表的一部分? – 2011-04-20 19:19:00

+0

有关更多信息,请参阅编辑。 – RolandTumble 2011-04-20 19:40:03

回答

1

您没有向我们展示串行表的示例数据。我很好奇它是否能像这样:

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表示串行行,你可以使用相关子查询。

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; 

我明白你的问题是更广泛的。就目前而言,这件作品是我可以包裹头部的一件。但它符合你的要求吗?

更新:我用我的版本的序列表。我创建了一个主表,其中包含自动编号Id,文本串行以及另外两个文本字段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字段......这正是我原以为你提出的。这种方法现在有什么问题?

+0

这确实告诉我如何只使用一个日期。它不回答我的主要问题 - 我将不得不对另一个编辑进行一些思考,看看我能否做得更清楚。 – RolandTumble 2011-04-21 20:58:18

+0

再读一次,它确实满足了我需要的东西。看到我最近的编辑为我仍然坚持的一件事.... – RolandTumble 2011-04-22 17:53:56

+0

好。对Serial的空值不确定;认为如果需要,你可以将其排除。现在有什么棘手的问题?我从昨天开始阅读您的修改内容,但是我没有看到您希望我看到的内容。 – HansUp 2011-04-22 17:58:50

0

其实我看不出为什么要防止改变文本框?如果我正在阅读此内容,那么您所说的是如果文本框发生变化,那么您需要保存之前的当前数据并在更改之前记录下来?

如果上面的话,那么只需在串行文本框的更新事件后,运行追加查询采用当前记录从表及复印件(追加别的地方)。

当你有一个绑定表,在表格上的变化,以控制尚未提交到实际的基础表。如果您的代码或进程或某个附加查询或VBA代码从该表中查看或复制了该行,则所有旧值都将保持不变。

所以绑定的形式并不意味着文本框中的每个更改都写入表中,但实际上整个记录仅在保存记录时才写入表中,这就是更新事件之前的表单有一个取消,可以防止记录写入发生,直到您的规则等得到满足。

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

+0

我不确定我是否理解你的意思 - 但如果我这样做,我认为它不会按照我想要的方式工作。请参阅编辑。 – RolandTumble 2011-04-20 19:43:46

+0

嗯......我想了一下,也许我*可以*插入一个(复制的)串行并更新*那行*的TermDt,然后只要保存前进,然后更新已更改的串行的EffDt ....但这似乎很复杂和容易出错。也许。 – RolandTumble 2011-04-20 19:49:19

+0

你不清楚你是否只是想要一个审计。在更新事件之前的表单序列文本框中,您可以使用textbox.old值,并设置表单级别变量,从而获得新值和旧值。 在这个时间点,用户可能会想要取消并且不保存整个记录。因此,您不应该更新该序列(审核)表。 如果要保存的记录,然后更新后,如果旧串行<>当前然后简单用新的值+日期+时间等写出新的记录等。如果不是新的串行值,你仍然能够更新现有的串行行时间/日期更新值。 – 2011-04-21 12:03:34

0

如果保存时法师不会经常改变,不是太大的话,用一个whoChanged记录追加整个主记录添加和timefield。然后,当您想要查看Serial中的更改时,只需在Serial上执行GroupBy,就可以看到时间以及谁更改了它。

这是矫枉过正一个领域,但在一般提供了记录变化的好办法。