【问题标题】:What is correct way to set up VBA ADO connection from Excel to Access for multiple users and files?为多个用户和文件设置从 Excel 到 Access 的 VBA ADO 连接的正确方法是什么?
【发布时间】:2017-01-10 11:35:33
【问题描述】:

我有几个用于输入数据的 excel 文件。文件在功能上是相同的,我们每个服务中心都有一个。在表单中有一个按钮可以启动一个宏,该宏将数据转换为另一张表上的表格格式,然后上传到 Access db。

在我自己的电脑上一切正常。添加新行、更新现有行和删除现有角色。我使用了早期绑定,当我将文件移动到我们的网络驱动器时会导致问题。我设法将文件转换为后期绑定,但随后出现了其他问题。

大多数情况下,无法上传到 Access,尤其是当多个用户尝试同时做某事时。最常见的错误代码是我没有使用可更新查询或者此方法不支持向后滚动。很抱歉没有报告实际的错误代码,但我目前无法复制它们。

我的连接代码如下,它是来自不同示例的复制粘贴代码的混合。

打开连接和其他prestuff

Sub excel2access()

Const adUseClient = 3  
Const adUseServer = 2
Const adLockOptimistic = 3
Const adOpenKeyset = 1
Const adOpenDynamic = 2

Dim oConn As Object
Dim cmd As Object
Dim rs As Object
Dim r As Long
Dim criteria As String
Dim Rng As Range

Set oConn = CreateObject("ADODB.Connection")
Set cmd = CreateObject("ADODB.Command")

oConn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "Data Source= '" & Range("dbpath").Value & "\" & Range("dbfile").Value & "' ;"

Set rs = CreateObject("ADODB.Recordset")
rs.CursorLocation = adUseClient
rs.CursorType = adOpenStatic
rs.LockType = adLockOptimistic
rs.Open "Select * from need_rows WHERE service_center = '" & Range("scenter_name").Value & "'", oConn

r = 2 ' the start row in the worksheet

Sheets("data").Select

以下位查看 Excel 工作表中的数据,并尝试从为该服务中心找到的记录集中找到匹配项。如果未找到匹配,则创建新记录,如果找到匹配,则更新旧记录。

Do While Len(Range("A" & r).Formula) > 0
    With rs
        criteria = Range("D" & r).Value
        .Find "identifier='" & criteria & "'"
        If (.EOF = True) Or (.BOF = True) Then
            .AddNew ' create a new record
            .Fields("service_center") = Range("scenter_name").Value
            .Fields("product_id") = Range("A" & r).Value
            .Fields("quantity") = Range("B" & r).Value
            .Fields("use_date") = Range("C" & r).Value
            .Fields("identifier") = Range("D" & r).Value
            .Fields("file_type") = Range("file_type").Value
            .Fields("use_type") = Range("E" & r).Value
            .Fields("updated_at") = Now
            .Update             
        Else
            If .Fields("quantity") <> Range("B" & r).Value Then
                .Fields("quantity") = Range("B" & r).Value
                .Fields("updated_at") = Now
                .Update ' stores the new record
            End If                      
        End If
        .MoveFirst 
    End With
    r = r + 1 
Loop

rs.Close
Set rs = Nothing
Set oConn = Nothing

MsgBox "Confirmation message"
End Sub

编辑:基于 barrowc 的链接,我将光标类型更改为 adOpenStatic。我对几个尝试同时上传数据的用户进行了测试,一切正常。直到一位用户留在文件中并在那里编辑数据并尝试将数据上传到数据库并收到以下错误消息: https://dl.dropbox.com/u/3815482/vba_error.jpg

我又回到了我的起点。

此外,我也愿意就我的代码提供总体反馈。

我正在使用 Office 2010。

我做错了吗?感谢所有帮助。

【问题讨论】:

  • “如果 CursorLocation 属性设置为 adUseClient,则仅支持 adOpenStatic 设置” - 请参阅 msdn.microsoft.com/en-us/library/windows/desktop/…
  • 这不是解决这个问题的方法,如果我没看错,所有用户都可以连接到访问文件的位置。您最好为他们开发一个前端访问应用程序,以安装哪些链接到主后端。 Access 可以创建比 Excel 更动态/更丰富的条目格式。
  • 这些用于规划一年中每周的消耗品采购。我还没有找到一种方法可以在 Access 中以一种可以很好地直观了解总体情况的方式来执行此操作。
  • 巴罗克,谢谢。似乎现在可以工作了。
  • 添加了错误信息和更多解释。此外,删除了最后一段代码,因为这不是这里的主要问题。

标签: vba ms-access excel ado


【解决方案1】:

您将遇到很多数据库被其他用户锁定的问题。这有几个原因:

  • 据我所知,您没有处理错误。因此,如果您的脚本在连接中途出错,连接将保持打开状态,从而导致锁定问题。
  • 从表面上看,宏可能会在相当长的时间内保持连接打开(假设没有错误)。

我已经创建了很多连接到 MS Access 数据库的宏,我可以直截了当地告诉你。您将遇到很多连接问题,其中数据库被电子表格锁定,由于诸如未处理意外错误(连接永远不会关闭)等原因,有人整天/夜间保持打开状态。

即使您解决了问题,您所需要的只是一个人将电子表格与旧代码一起使用,他们将继续锁定数据库。

一个大问题是,如果有人在数据库已经被其他人打开的情况下连接到数据库,我相信他们会继承已经打开的数据库的连接类型,从而导致写锁的菊花链。然后,您需要确保所有连接都被切断才能重置连接。

您还没有首先向我们展示数据是如何放入电子表格的。也许您没有正确关闭连接,这可能是有时数据库被锁定的原因。

您可以尝试许多不同的方法来解决这个问题:

  • 最简单的方法是使用 MS Access 前端 + MS Access 后端。
  • 无需按下此按钮并通过连接字符串上传数据,您可以将文件保存在文件夹中,然后由坐在那里观察文件夹的 ms 访问数据库处理该文件夹。这意味着您上传的脚本将在 MS Access 中编写,并且只是在处理文件。不会像您当前的方法那样即时,但在这种情况下,所有写入连接都来自同一台机器/用户。
  • 坚持使用当前方法:最终您可能会使其进入稳定状态,但这会带来很多挫折和努力,因为确定锁定的原因可能并不总是那么容易。您至少可以查看当时谁锁定了文件并从那里开始工作,但如前所述,他们可能不是锁定的原因。他们可能刚刚继承了锁类型。

我个人喜欢使用 MS Excel 为用户显示 MS Access 数据,但避免像瘟疫一样让它更新 MS Access。但是,如果我要这样做,我会通过使用 oConn.Execute 命令而不打开记录集、比较和减慢推送来实现,因为这会使连接保持打开太久。

对不起,文字墙。希望这些信息对您有所帮助。

【讨论】:

  • 已经很久了,我已经不记得我是如何真正做到这一点的了。但它已经工作了好几年了。
【解决方案2】:

在我看来,Jet 对于您的环境来说不够可靠。我经常使用 SQL Server / Access Data Projects 将来自多个电子表格的信息整合到一个数据库后端,当您添加六个用户时,它不会出错。

【讨论】:

  • 对如何进行有什么建议吗?我能够将 db 移动到 sql server。无论如何,那是我的长期计划。
  • 我在 SQL Server 中使用了“升迁向导”,然后选择了客户端/服务器选项 (ADP)。这只需要你大约 1/2 的路程,然后你需要编写一些 ADO / SQL 存储过程来填补一些漏洞。
【解决方案3】:

您也可以尝试使用操作查询。 首先我会尝试使用更新(您可能需要格式化现在的值)

dim count as long
oConn.Execute "UPDATE need_rows SET quantity = " & Range("B" & r).Value & ", updated_at = #" & Now & "# WHERE service_center = '" & Range("scenter_name").Value & "' AND identifier='" & Range("D" & r).Value & "' AND quantity <> " & Range("B" & r).Value", count

如果计数为零,则没有更新任何行,因此要么没有要更新的行,要么数量没有改变。无论哪种方式,我们都可以尝试插入,在后一种情况下会失败,但不会导致问题。

if count = 0 then
    count = oConn.Execute "INSERT ...", count
    if count = 0 then
        ' quantity has not changed, so nothing to do
    else
        ' new record inserted
    end if
else
    ' record updated
end if

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-29
    • 1970-01-01
    • 2011-06-08
    相关资源
    最近更新 更多