"交易中不支持操作"在Access中复制/粘贴记录时

时间:2013-10-31 17:06:25

标签: ms-access ms-access-2010

将Excel中的单元格复制/粘贴到Access子窗体中时,如果没有创建父记录,则会导致错误 - 正如预期的那样。

问题在于,在发生此错误后,访问将被锁定在这样一种状态:输入的所有后续数据都会导致 操作不支持 错误。当您打开表格时,您可以看到新添加的数据尚未出现在表格中 - 因此看起来好像Access实际上正在进行某种交易。

我试过点击'保存' ..'刷新' ..甚至添加一个AfterInsert事件来强制commitTrans()但没有运气 - 并且Access声称没有正在进行的事务

如果手动输入记录,则没有错误。粘贴记录时似乎只会出现问题。我猜测Access正在创建一个事务来处理多个记录操作,并且没有正确地从错误中恢复。

我可以删除“必需”'标志,它会工作 - 但你有孤儿记录。我想也许可以使用After Insert Data Macro添加一个带有默认批处理名称的新批处理,并将新的BatchID自动填充到Items表中。我不确定如何做到这一点。

我确实尝试删除了“必需”'使用更改前数据宏来标记和捕获错误 - 虽然它减少了错误 - 它仍然产生相同的事务中不支持的操作错误。

我查找了Microsoft知识库中的错误,但没有找到任何特定于我的情况。我在stackoverflow中搜索了错误消息但没有找到任何内容。

我创建了一个新数据库,并且能够复制该问题。

复制步骤

设置数据库

  1. 在Access 2010中创建新的ACCDB数据库
  2. 创建一个名为' Batches'的表,其中包含以下字段:
    • BatchID(自动编号)(主键)
    • BatchName(文字)
  3. 使用以下字段创建名为' Items'的表格:
    • RecordID(自动编号)(主键)
    • BatchID(长整数)
      • 必需属性设置为True
    • 数据 - 文字
  4. 创建关系,将Batches.BatchID链接到Items.BatchID
    • 包括批次中的所有记录,以及匹配来自项目的记录
    • 实施参照完整性
    • 级联更新/删除
  5. 创建一个名为' Form'
    • 将Recordsource设置为批次
    • 添加BatchID和Batch名称Textboxes
    • 添加SubForm / SubReport控件
      • 将源对象设置为" Table.Items"
      • 将链接主字段设置为" BatchID"
      • 将链接子字段设置为" BatchID"
      • Set" Filter On Empty Master" =是
  6. 创建样本数据(使用表单)
    • 批量创建新记录。
      • 设置BatchName ="测试"
    • 在项目中创建新记录
      • 参考批记录。
      • 设置数据="测试"
  7. 正如您所看到的,手动工作正常。

    从Excel复制和粘贴数据

    1. 在Excel中
      • 从A1-A10开始,每个单元格输入一个字母:A,B,C,D,E,F,G,H,I,J
      • 突出显示单元格A1-A10
      • 复制(Control + C)
    2. 在Access中,使用表格:
      • 添加新的批记录。它应该说"(新)"在BatchID TextBox
      • 请勿输入批名称
      • 在子窗体中,单击新记录的记录选择器(*)以选择整个行。输入Control + V进行粘贴。
      • 点击&#34确定;您必须在' Data.BatchID'中输入一个值。字段。错误
        • 此错误可能会重复。保持单击确定
        • 如果它要求"您是否要抑制更多错误消息..."回答是
      • 单击确定" Microsoft Access无法粘贴的记录已插入名为'粘贴错误的新表中。' 通知
      • 使用" TestName"
      • 填写批名称文本框
      • 尝试优雅地恢复。击中逃生。更改记录。
    3. 此时 - 您应该看到输入的BatchID,批次名称和新数据。所有出现都按预期工作。如果您尝试刷新或导航到另一个批记录 - 您将收到错误 交易中不支持的操作 。 Access将继续显示此错误消息,直到我们关闭并重新打开表单。您粘贴的数据不会进入数据库。

      通常情况下,具有一点技术知识的人会意识到某些事情并不顺利并且从数据库中关闭并重新打开...但不幸的是,我有玩耍的用户"打击鼹鼠& #34;使用任何弹出框然后尝试继续 - 所以我想尽可能地防范。

      所需解决方案

      我想解决问题的方法,最终导致其他带有访问权限,重复值等的怪癖。

      根据我自己的经验,使用VBA来修复&#39;钥匙不可靠。数据宏似乎更可靠 - 但它们设置起来可能很棘手 - 它们还不是主流(我说应该有一个 ms-access-data-macros < / em>标签在stackoverflow上,但还没有)

5 个答案:

答案 0 :(得分:1)

建议的解决方法:

在[批次]表格中,将[BatchName]字段的Required属性设置为Yes

将[BatchID]文本框的Tab Stop属性更改为“否”。这将在表单打开时为[BatchName]文本框提供默认焦点。

让表单的On Current事件为[BatchName]文本框指定新记录的焦点(IsNull(Me.BatchID) = True)。

当[BatchName]文本框失去焦点时,使表单变脏。

Option Compare Database
Option Explicit

Dim DeletePending As Boolean

Private Sub Form_Load()
    DeletePending = False
    Me.ItemSubForm.Enabled = False  ' Disable Subform by default
End Sub

Private Sub Form_Current()
    If IsNull(Me.BatchID) Then
        Me.BatchName.SetFocus
        ' Disable Subform if BatchID is NULL
        Me.ItemSubForm.Enabled = False
    Else
        ' Enable SubForm Otherwise
        Me.ItemSubForm.Enabled = False 
    End If
End Sub

Private Sub Form_BeforeDelConfirm(Cancel As Integer, Response As Integer)
    DeletePending = True
End Sub

Private Sub Form_AfterDelConfirm(Status As Integer)
    DeletePending = False
End Sub

Private Sub BatchName_LostFocus()
    If IsNull(Me.BatchID) And Not DeletePending Then
        Me.Dirty = True
    End If
End Sub

当用户单击子窗体(并关闭[BatchName]文本框)时,它们会使窗体变脏并且BatchID获取值。然后他们可以粘贴,并且他们没有收到[BatchID]的“你必须输入值...”消息。如果他们没有输入[BatchName]值,他们现在会被提示输入 it (因为它现在是Required),但至少他们可以从中优雅地恢复。

更新时间2013-11-09 18:40 UTC:

在玩这个时,我发现了两个怪癖:

  1. 如果您删除了最后一个父记录,Access会执行此操作,然后立即在其位置创建另一个新记录。

  2. 如果您导航到“新”父记录然后立即退出(例如,通过 PageDown PageUp 键)Access将创建一个新的记录,然后将表格弄脏,留在该记录上。点击 Esc ,然后移开“新”记录就可以了,它没有造成任何错误,但它肯定会让用户感到困惑。

  3. 我已经更新了答案,试图解决这些问题。我添加了一些VBA代码来跟踪“DeletePending”状态。我还添加了[BatchName]在[Batches]表中设置为Required = Yes的要求。如果用户进入“新”记录然后立即再次退出,后者会使其更直观(虽然稍微有些烦人)。

答案 1 :(得分:1)

我知道这是一个古老的故事,我也对此感到不安。 我的解决方案是重新设置该过程,以便用户关闭接收数据的表单以保存插入的记录。既不优雅又高效,使我无法猜测可能发生的每一件事。

答案 2 :(得分:0)

避免不受欢迎的内部交易就足够了 使用以下代码编写子表单错误事件:

Private Sub Form_Error(DataErr As Integer, Response As Integer)

    Response = acDataErrContinue

End Sub

拦截子表格事件的一般方法是

' parent form code
' ---------------------------------------------------
Private WithEvents subFormObj As [Form_Sottomaschera items]

Private Sub Form_Open(Cancel As Integer)

    Set subFormObj = Me.Sottomaschera_items.Form

End Subcode here

' asynchronous way
Private Sub subFormObj_isInserting()

    Me.batchName = vbNullString         ' this resolves the new ID issue

End Sub

' synchronous way
Public Sub subFormInserting()

    Me.batchName = vbNullString

End Sub

' sub-form code
' ---------------------------------------------------
Public Event isInserting()              ' for asynchronous way

Dim parentFormObj As Form_Maschera1     ' for synchronous way

Private Sub Form_BeforeInsert(Cancel As Integer)

    parentFormObj.subFormInserting
    RaiseEvent isInserting
'    Cancel = True

End Sub

Private Sub Form_Error(DataErr As Integer, Response As Integer)

    Response = acDataErrContinue

End Sub

Private Sub Form_Open(Cancel As Integer)

    Set parentFormObj = Me.Parent

End Sub

其中[Maschera1]是主要表单,[Sottomaschera items]是子表单。

不幸的是,它无法解决粘贴问题。

要明确解决问题,您需要保存父记录+ SetFocus技巧,无论是同步还是异步:

Private Sub subFormObj_isInserting()

    Me.batchName = vbNullString
    DoCmd.RunCommand acCmdSaveRecord
'    DoEvents
    Me.batchName.SetFocus

End Sub

Public Sub subFormInserting()

    Me.batchName = vbNullString
    DoCmd.RunCommand acCmdSaveRecord
'   DoEvents
    Me.batchName.SetFocus

End Sub

答案 3 :(得分:0)

我挣扎了这么久,直到我终于明白发生了什么导致这个错误。需要一篇相当长的文章才能详细介绍细节而不是博客回复来解释这一切。如果有人有兴趣,他们可以留下联系方式,我会联系他们并详细解释。 但是,对于那些想要解决这个问题的人,我可以通过向您提供问题背后的理念来节省大量时间: 在绑定子表单中执行数据事务时,不能引用其他对象。事务处理的内部代码不允许这样做。例如,如果Form_BeforeUpdate事件中的代码在子表单数据事务中尝试打开另一个表单,则会出现错误3246.您可以拥有创建变量,设置值,引用子代码的代码表单控件等,但你不能出去另一个对象。 如果你考虑一下,这是有道理的。谁知道用户或代码进入另一个表单或对象后可能会做什么。它可能永远不会回来或涉及其他让事务悬空的错误。这就是交易必须先完成的原因。 这意味着您必须捕获并解除当用户在事务中尝试单击子表单外部区域时导致的错误2115。这通常发生在大型复制和粘贴期间,其中用户变为住院病人或者在仍然处于子窗体事务中时开始前进到另一个记录。

答案 4 :(得分:0)

我不明白你到底想要什么,所以这个答案可能不够充分。 你可以

  • .Visible = False时设置您的子表单属性Me.NewRecord = True,以防止向其中输入数据
  • 通过在按Enter键触发的After Update事件中设置.Dirty = False,添加批名称后,将主表单强制保存到表中。它还允许避免在将一些记录添加到某些数据库中的主窗体之后不将子窗体的记录保存到表中,至少使用动态子窗体.Recordsource。
  • 设置子表单属性.Visible = True

下面的代码适用于表单视图,也许应该以某种方式扩展(开发)其他视图。

将子窗体Child和您要隐藏/显示的所有其他控件设置为。&#34; a&#34;。

Private Sub Form_Current()

If Me.CurrentView = 1 Then

    If Me.NewRecord = True Then
       ShowControls False
    ElseIf Me![Items subform Child].Visible = False Then
       ShowControls True
    End If

End If

End Sub

Private Sub BatchName_Text_AfterUpdate()

Dim NewRecordx As Boolean

If Me![Items subform Child].Visible = False And Me.CurrentView = 1 Then ShowControls True

NewRecordx = Me.NewRecord

If Me.Dirty Then Me.Dirty = False 'save the new record to the table

If Me.CurrentView = 1 And NewRecordx Then Me![Items subform Child].Form.Requery

End Sub

Private Sub ShowControls(bVisible As Boolean)

Dim ctl As Control

For Each ctl In Me.Controls
   If ctl.Tag = "a" Then ctl.Visible = bVisible
Next ctl

End Sub