DoCmd.DeleteObject acTable - "could not lock table because it is already in use"
DoCmd.DeleteObject acTable - "could not lock table because it is already in use"
我在尝试删除 table 时遇到以下错误:
Run-time error '3211'
The database engine could not lock table 'RuleViolations1516' because
it is already in use by another person or process.
这是有问题的程序,注释显示了引发错误的行:
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 和函数 运行 在它们自己的单独模块中(不绑定到表单模块)。
table RuleViolations1516 没开的时候我运行 子。表单 frmImportRuleViolations 在某些子表单后面的某些查询中使用 RuleViolations1516 table,但是正如您从子表单中看到的那样,我已经在第一行关闭了此表单。
任何指点将不胜感激。
更新:
frmImportRuleViolations 上有 2 个子表单...删除它们(暂时)可以解决问题。不过,我需要表单上的子表单。我该如何解决这个问题?
据我了解你更新后的问题,你有一个名为 frmImportRuleViolations
的表单,它有一个子表单,我称之为 frmImportRuleViolationsSubform1
.
frmImportRuleViolationsSubform1
引用了 RuleViolations1516
table 某处。
我假设您也在 frmImportRuleViolations
上通过按钮或其他控件触发此重新加载。如果是这样,那么这就是导致错误的原因。到关闭事件时,Access 可能还没有放弃对 RuleViolations1516
的所有引用。
那个和一个表单关闭和重新打开本身可能有点毛茸茸。
一件相当简单的事情是在打开 frmImportRuleViolationsSubform1 之前删除并加载 table。作为用户(和开发人员),这正是我所期望的——我打开表格,它是最新的。最坏的情况是关闭表单并重新打开它让我精神焕发。
否则(必须在关闭表单后重新加载);然后我会让关闭它的任何东西打开 frmImportRuleViolations
作为模态 window,然后在调用 frmImportRuleViolations
之后重新加载 table 代码,因为它将等到控制返回给调用 window.
您也可以将数据加载到临时暂存区 table,然后删除 RuleViolations1516
的内容并从暂存区 table 重新填充它。这可能是我要采取的路线,因为它会消除 frmImportRuleViolations
表格的关闭和打开。您只需告诉子表单上的 table 进行刷新(我将为 reader 留一个练习)。
除此之外,一些风格说明:
'' 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 原则 - "DRY - don't repeat your self".
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 年后接触您的代码,以便轻松理解您在做什么。而且代码总是比你想象的更持久 :^)
祝你好运!
我在尝试删除 table 时遇到以下错误:
Run-time error '3211'
The database engine could not lock table 'RuleViolations1516' because it is already in use by another person or process.
这是有问题的程序,注释显示了引发错误的行:
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 和函数 运行 在它们自己的单独模块中(不绑定到表单模块)。
table RuleViolations1516 没开的时候我运行 子。表单 frmImportRuleViolations 在某些子表单后面的某些查询中使用 RuleViolations1516 table,但是正如您从子表单中看到的那样,我已经在第一行关闭了此表单。
任何指点将不胜感激。
更新:
frmImportRuleViolations 上有 2 个子表单...删除它们(暂时)可以解决问题。不过,我需要表单上的子表单。我该如何解决这个问题?
据我了解你更新后的问题,你有一个名为 frmImportRuleViolations
的表单,它有一个子表单,我称之为 frmImportRuleViolationsSubform1
.
frmImportRuleViolationsSubform1
引用了 RuleViolations1516
table 某处。
我假设您也在 frmImportRuleViolations
上通过按钮或其他控件触发此重新加载。如果是这样,那么这就是导致错误的原因。到关闭事件时,Access 可能还没有放弃对 RuleViolations1516
的所有引用。
那个和一个表单关闭和重新打开本身可能有点毛茸茸。
一件相当简单的事情是在打开 frmImportRuleViolationsSubform1 之前删除并加载 table。作为用户(和开发人员),这正是我所期望的——我打开表格,它是最新的。最坏的情况是关闭表单并重新打开它让我精神焕发。
否则(必须在关闭表单后重新加载);然后我会让关闭它的任何东西打开 frmImportRuleViolations
作为模态 window,然后在调用 frmImportRuleViolations
之后重新加载 table 代码,因为它将等到控制返回给调用 window.
您也可以将数据加载到临时暂存区 table,然后删除 RuleViolations1516
的内容并从暂存区 table 重新填充它。这可能是我要采取的路线,因为它会消除 frmImportRuleViolations
表格的关闭和打开。您只需告诉子表单上的 table 进行刷新(我将为 reader 留一个练习)。
除此之外,一些风格说明:
'' 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 原则 - "DRY - don't repeat your self".
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 年后接触您的代码,以便轻松理解您在做什么。而且代码总是比你想象的更持久 :^)
祝你好运!