0

我有几个用于输入数据的 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。

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

4

3 回答 3

1

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

于 2012-10-29T15:13:11.087 回答
1

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

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

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

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

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

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

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

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

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

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

于 2017-01-10T03:35:33.980 回答
0

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

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
于 2015-09-11T15:48:17.637 回答