DoCmd.DeleteObject acTable - “无法锁定表,因为它已经在使用”

时间:2015-09-03 16:17:28

标签: ms-access access-vba ms-access-2007 ms-access-2010 ms-access-2013

尝试删除表时出现以下错误:

  

运行时错误'3211'

     

数据库引擎无法锁定表'RuleViolations1516',因为   它已被其他人或进程使用。

这是违规程序,注释显示抛出错误的行:

Public Sub ImportRuleViolations()

    DoCmd.Close acForm, "frmImportRuleViolations"

    If _
        TableExists("RuleViolations1516") = True _
    Then

        Debug.Print "Table RuleViolations1516 already exists"

        DoCmd.DeleteObject acTable, "RuleViolations1516" ' <-- EXECUTION STOPS HERE
        Debug.Print "...old table deleted..."

        DoCmd.TransferSpreadsheet acTable, _
                  10, _
                  "RuleViolations1516", _
                  Forms!frmImportRuleViolations.txtRuleViolationsPath & Forms!frmImportRuleViolations.txtRuleViolationFile, _
                  -1
        Debug.Print "...new data imported."

    ElseIf _
        TableExists("RuleViolations1516") = False _
    Then

        Debug.Print "Table RuleViolations1516 does not already exist"

        DoCmd.TransferSpreadsheet acTable, _
                          10, _
                          "RuleViolations1516", _
                          Forms!frmImportRuleViolations.txtRuleViolationsPath & Forms!frmImportRuleViolations.txtRuleViolationFile, _
                          -1
        Debug.Print "...new data imported."

    End If

    Dim db As DAO.Database
    Dim tDef As TableDef, fld As DAO.Field

    Set db = CurrentDb

    db.TableDefs.Refresh

    ' LRN

        Set tDef = db.TableDefs("RuleViolations1516")
        Set fld = tDef.CreateField("newLRN", dbText, 20)
        fld.OrdinalPosition = 2
        tDef.Fields.Append fld

        db.Execute _
            "UPDATE RuleViolations1516 Set newLRN=[Learner Ref]", dbFailOnError

        ' delete old field
        tDef.Fields.Delete "Learner Ref"
        tDef.Fields.Refresh

        ' rename new field
        tDef.Fields("newLRN").name = "LRN"
        tDef.Fields.Refresh

        Set fld = Nothing
        Set tDef = Nothing

    ' AimRef

        Set tDef = db.TableDefs("RuleViolations1516")
        Set fld = tDef.CreateField("newAimRef", dbText, 20)
        fld.OrdinalPosition = 7
        tDef.Fields.Append fld

        db.Execute _
            "UPDATE RuleViolations1516 Set newAimRef=[Aim Reference Number]", dbFailOnError

        ' delete old field
        tDef.Fields.Delete "Aim Reference Number"
        tDef.Fields.Refresh

        ' rename new field
        tDef.Fields("newAimRef").name = "AimRef"
        tDef.Fields.Refresh

        Set fld = Nothing
        Set tDef = Nothing

    Set db = Nothing

    DoCmd.OpenForm "frmImportRuleViolations"

End Sub

违规子也引用了另一个功能:

Public Function TableExists(name As String) As Boolean

    TableExists = DCount("*", "MSysObjects", "Name = '" & name & "' AND Type = 1")

End Function

上面的子和函数在他们自己独立的模块上运行(没有绑定到表单模块)。

运行sub时,表 RuleViolations1516 未打开。表单frmImportRuleViolations在一些子表单后面的一些查询中使用RuleViolations1516表,但正如您从sub中看到的那样,我在第一行关闭了此表单。

任何指针都会受到赞赏。

更新

frmImportRuleViolations上有2个子表单...删除它们(暂时)可以解决问题。我需要表单上的子表单..我怎么能解决这个问题呢?

1 个答案:

答案 0 :(得分:1)

据我了解您的更新问题,您有一个名为frmImportRuleViolations的表单,其中包含一个子表单,我将调用frmImportRuleViolationsSubform1

frmImportRuleViolationsSubform1在其上的某处引用了RuleViolations1516表。

我假设您还在frmImportRuleViolations上的按钮或其他控件上触发此重新加载。如果是这样,那么这是错误的原因。在到达关闭事件时,访问可能没有放弃对RuleViolations1516的每次引用。

那个关闭和重新开放的形式可能会变得多毛。

一个相当容易的事情是在打开frmImportRuleViolationsSubform1之前删除并加载表。作为我期望的用户(和开发者) - 我打开表单并且它是最新的。关闭表格并重新打开表格的最坏情况让我更新。

失败(表单关闭后必须重新加载);然后我会做任何关闭它打开frmImportRuleViolations作为模态窗口,然后在调用frmImportRuleViolations之后重新加载表代码,因为它将等到控制返回到调用窗口。< / p>

您也可以将数据加载到临时登台表中,然后删除RuleViolations1516的内容并从登台表重新填充它。这可能是我将采取的路线,因为它将消除frmImportRuleViolations形式的关闭和打开。您只需告诉子表单上的表格进行刷新(我将为读者留下一个练习。)

除此之外,还有几种风格的笔记:

'' this 
If _
    TableExists("RuleViolations1516") = True _
Then

'' could be equally written as
If TableExists("RuleViolations1516") Then
'' the "= True" is implied and not required

'' this
ElseIf _
    TableExists("RuleViolations1516") = False _
Then

'' is redundant to the previous if. A simple else would do, since we
'' know if the last time it ran, it wasn't true, it must be false

并且DoCmd块在if和else中看起来都是一样的,所以我倾向于像这样提取它:

If TableExists("RuleViolations1516") then
    Debug.Print "Table RuleViolations1516 already exists"
    DoCmd.DeleteObject acTable, "RuleViolations1516" 
    Debug.Print "...old table deleted..."
else
    Debug.Print "Table RuleViolations1516 does not already exist"
end if

DoCmd.TransferSpreadsheet acTable, _
    10, _
    "RuleViolations1516", _
    Forms!frmImportRuleViolations.txtRuleViolationsPath & _
        Forms!frmImportRuleViolations.txtRuleViolationFile, _
    -1
Debug.Print "...new data imported."

当你回来更改文件的名称(或其他)时,你只会在一个地方更改它等等,并遵循DRY原则 - &#34; DRY - 不要重复你的自我&#34;。

I like the use of underscores so that what you have coded does not run off the edge of the screen like some extract from war and peace. It makes it much more readable.

您所做的是错误。这不是大多数开发人员会做的事情。尽管我们为计算机编写代码以便按照我们想要的方式运行,但我们也希望下一个开发人员能够在5年后触摸您的代码,以便轻松了解您正在做什么。代码总是比你想象的要长:^)

祝你好运!