【问题标题】:Update Excel with ADODB with Workbook Open使用 ADODB 更新 Excel 并打开工作簿
【发布时间】:2017-05-26 18:05:24
【问题描述】:

在 Excel 2010 中。我正在尝试根据一些过滤器在执行宏的同一个工作簿上编写/更新一些单元格;为简单起见,我将 de query 缩减为您可以看到的内容。 此代码有效,但仅当工作簿关闭时(从另一个工作簿测试)。

Dim libro As Workbook
Set libro = ActiveWorkbook
esteLibro = libro.Name

Dim cnCaja As ADODB.Connection
Dim rsCaja As ADODB.Recordset
Set cnCaja = New ADODB.Connection
Set rsCaja = New ADODB.Recordset
cnCaja.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
    "Data Source='" & esteLibro & "';" & _
        "Extended Properties='Excel 12.0;HDR=Yes;ReadOnly=False';"

Dim consCaja As String
consCaja = "Update [Base$A3:T100000] Set INVERSIONES = 1000 "
rsCaja.Open consCaja, cnCaja, adOpenStatic, adLockOptimistic

从另一个工作簿执行时,“INVERSIONES”列的空白单元格将更改为 10000;但从同一个工作簿我得到了错误:

'-2147217865 (8004e37)' Microsoft Access 数据库引擎无法 找到对象“[Base$A3:T100000]”。确保对象存在并且您拼写它 名称和路径名正确。如果 '' 不是本地对象,请检查 您的网络连接或联系服务器管理员。

这是整个连接字符串:

Debug.Print cnCaja.ConnectionString

提供者=Microsoft.ACE.OLEDB.12.0;用户 ID=管理员;数据 Source=Danny_Diario.xlsm;Mode=Share Deny None; Jet OLEDB:系统 数据库="";Jet OLEDB:注册表路径=""; Jet OLEDB:数据库 Password="";Jet OLEDB:Engine Type=35; Jet OLEDB:数据库锁定 Mode=0;Jet OLEDB:Global Partial Bulk Ops=2; Jet OLEDB:全球散装 Transactions=1;Jet OLEDB:新数据库密码=""; Jet OLEDB:创建 系统数据库=假;Jet OLEDB:加密数据库=假;喷射 OLEDB:不要在 Compact=False 上复制区域设置; Jet OLEDB:紧凑型 副本修复=False;Jet OLEDB:SFP=False; Jet OLEDB:支持复合体 数据=假; Jet OLEDB:绕过 UserInfo 验证=False;

而且,即使工作簿处于打开状态,对同一个表的查询也将起作用。

consCaja = "Select * from [Base$A3:T100000] Where Fecha = #" & fechaBase & "# and Empresa = ""Empresa"" and Banco = ""Banco"""
rsCaja.Open consCaja, cnCaja, adOpenForwardOnly, adLockReadOnly

Do While Not rsCaja.EOF
    MsgBox (rsCaja("Empresa").Value & vbNewLine & rsCaja("Banco").Value & vbNewLine & rsCaja("INVERSIONES").Value)
    rsCaja.MoveNext
Loop

最后,是否可以在工作簿打开的情况下使用 ADODB 更新 Excel? 如果是,我做错了什么,或者我该如何解决?

【问题讨论】:

  • 连接字符串需要完整路径。将顶行更改为:esteLibro = libro.FullName。尽管如此,我怀疑您是否可以使用打开的工作簿进行更新。
  • 我可以阅读,所以不需要完整路径。但即使有完整路径,我仍然有同样的错误。而且我一直无法找到一些消息来源告诉我这是无法做到的。

标签: vba excel adodb


【解决方案1】:

考虑对已打开工作簿的现有数据运行只读SELECT。由于文件写入访问的各种原因,Excel 作为一个平面文件缓存内存应用程序,可能没有像数据库这样的设施来同步打开应用程序和更新当前数据。

下面为您设置SELECT 查询以镜像当前结构,其中一个更改是传递一个常量 1000,并将其分配给当前列位置的 INVERSIONES 列别名。条件逻辑IIF 语句也可以轻松放置在这里。或者,在新工作表中运行查询和转储结果。然后删除/归档当前工作表并保存工作簿。

Dim cnCaja As New ADODB.Connection
Dim rsCaja As New ADODB.Recordset
Dim consCaja As String

esteLibro = ActiveWorkbook.FullName
cnCaja.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
            "Data Source='" & esteLibro & "';" & _
            "Extended Properties='Excel 12.0;HDR=Yes;';"

consCaja = "SELECT Col1, Col2, Col3, '1000' AS INVERSIONES, Col4, Col5, Col6" & _
           " FROM [Base$A3:T100000]"
rsCaja.Open consCaja, cnCaja

Worksheets("Base").Range("A3").CopyFromRecordset rsCaja

rsCaja.Close: cnCaja.Close
Set rsCaja As Nothing: Set cnCaja As Nothing

【讨论】:

  • 这是一个简化的查询。真正的查询类似于:'consUpdate = "Update [Base$A3:T100000] Set INVERSIONES = prMonto " & _ ' "Where Empresa = prEmpresa and BANCO = prBanco and Fecha = prFecha " 我想对 SQL 中的过滤器使用参数化查询,这就是我需要 ADODB 的原因。我要更新的数据之间可能存在差距,因此我不能使用 range.copy ... 目前,另一个选择是遍历行以查看数据是否与我的参数匹配,但我认为它随着时间和数据的增加,速度会慢很多。
  • 如前所述,您可以使用IIF() 设置逻辑并传递所需的参数:SELECT Col1, Col2, Col3, IIF(Empresa = ? AND BANCO = ? AND Fecha =?, ?, INVERSIONES) AS NewInversiones, Col4, Col5, Col6 FROM [Base$A3:T100000]。而且我不太明白为什么CopyFromRecordset 不起作用,因为它将是FROM 子句中非常表范围的精确副本,从Base$A3 开始。
  • 现在我明白了。但是我仍然对重写所有内容感到不舒服。谢谢你。我想我想做的事情是不可能的,所以我就用旧的For each r in ws.Range().Rows
  • 我在 Excel 工作表中添加了一个带有行号的字段并将值拉入查询中,然后只更新了我想要的行 ws.range("A" & rsCaja("rowNumber") )=1000
猜你喜欢
  • 2015-06-02
  • 2014-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多