【问题标题】:Excel VBA Late Bind to Access and SQL InsertExcel VBA 后期绑定到 Access 和 SQL 插入
【发布时间】:2015-02-27 12:10:50
【问题描述】:

我遇到了一个令人沮丧的问题,即从 Excel VBA 后期绑定到 MS Access 以执行插入或更新等 DML 语句。我在 vba 中使用的所有数据都来自用户定义的类。我可以很好地查询,但是每次我尝试不同的方式来做同样的事情时,写入数据库都会得到不同的错误。下面是一些指向相同/类似问题的链接,但是每个链接都略微脱离上下文,因此我无法通过我的问题。

我的最终目标是简单地执行 DML 字符串语句,并且它必须使用后期绑定。主要是当我将 ReadOnly=0 添加到连接字符串时,我收到 3251 错误说我的连接是“只读”或缺少 ISAM。仅供参考,getProjectFile 只是返回从我的项目的父文件夹开始的文件的路径。我很确定我可以只使用 connDB.Execute 所以我只需要 SQL 插入,我不想先查询,因为查询会很快变胖。我还认为枚举参数可能有问题,因为 ExecuteOptions 需要位掩码而不是 Long,我真的不知道该怎么做。在我的大部分研究中,我不断被提及 LockType 和/或光标不正确。对于我的环境; Windows 8.1 64 位,MS Office 2010 32 位(必需)。有人看到这里有什么问题吗?

Sub ADO_Tester()

Dim strSQL, strFile, strConnection As String
Dim connDB As Object

'late bind to the ADODB library and get a connection object
Set connDB = CreateObject("ADODB.Connection")

'Connect to the DB
strFile = Application.ActiveWorkbook.Path & "\" & "PortfolioDB.accdb"
strConnection = "Provider = Microsoft.ACE.OLEDB.12.0; data source=" & strFile & ";"
connDB.Open strConnection

'insert statement for a test record
strSQL = "INSERT INTO underlying_symbol (symbol) VALUES ('xyz')"

'execute the 
connDB.Execute strSQL, , 2, 1 + 128

'clear the object
connDB.Close
Set connDB = Nothing

End Sub

编辑:

早期绑定:

connDB.Execute strSQL, , adCmdText + adExecuteNoRecords

后期绑定:如何输入 adExecuteNoRecords 的值?在 msdn 上它是 0x80,另一个帖子说 &H0001,无论哪种方式它都会给出语法错误。它说为此枚举值输入一个位掩码。

connDB.Execute strSQL, , 1 + 0x80

编辑:现在正确的方法 - adExecuteNoRecords(ADO 枚举值)= 0x80(二进制值)= 128(十进制值)

connDB.Execute strSQL, , 1 + 128

编辑:现在问题变得更深了。当我将测试电子表格中的代码执行到测试数据库中时,它可以工作。当我复制并粘贴到实际项目电子表格并指向实际项目数据库时,我收到错误:操作必须使用可更新查询。 . .再次。相同的数据库名称,相同的 dml,相同的表名。唯一的区别是实际的 DB 是拆分的产物,以将其与 Access 中的表单和代码分开。这是否可以更改某些设置以使其只读?

编辑:它只会越来越深。导致它在项目数据库中不起作用的问题是因为我有一些 Excel 表查询数据库。我通过 Excel UI、功能区 -> 外部数据 -> 访问 -> 等制作了这些。 .现在很明显,这些导致我无法插入 DML,因为它们可能设置为只读。如何更改表连接权限?有没有另一种方法可以制作这些表格以便我可以提供连接?如何让表格对 VBA 中的 DML 友好?

【问题讨论】:

  • 我忘了提到我还查看了插入的“IN”语句; 'INSERT INTO IN () VALUES ()。但是我还没有尝试过。这会是一个好的解决方案吗?使用它有什么智慧之言吗?
  • 这是一种方法,但不是必须的。当我不想打开到每个访问数据库的单独连接时,我通常会使用这些语句。将connDB.Execute strSQL, , 2, &H1 更改为connDB.Execute strSQL 会出现什么错误?
  • 当我只使用 connDB.Execute strSQL 时,我收到一个错误,指出它是只读的,并且锁类型错误或提供程序无法执行此操作。在 msdn 上,它说 Execute 方法默认为 ForwardReadOnly。我的提供程序是 ACE.OLEDB,它与其他所有人在示例中使用的提供程序相同。我也尝试了其他一些 lockType,但它们返回了相同的错误。
  • 对不起,确切的错误是,操作必须使用可更新的查询。这就是我在执行时发现其他参数和默认 ForwardReadOnly 的方式。当我尝试更改锁定类型时,我得到了我提到的另一个错误。

标签: vba excel database-connection late-binding dml


【解决方案1】:

这对我有用:

Option Explicit

Private Const acCmdText As Integer = 1

Sub ADO_Tester()
On Error GoTo ErrorHandler

    Dim strSQL As String
    Dim strFile As String
    'Dim adoRecSet As Object
    Dim connDB As Object

    'late bind to the ADODB library and get a connection object
    Set connDB = CreateObject("ADODB.Connection")

    'Connect to the DB
    strFile = getProjectFile("core", "PortfolioDB.accdb")
    connDB.Open connectionString:="Provider = Microsoft.ACE.OLEDB.12.0; data source=" & strFile & ";"

    'If State = 1, db connection is okay.
    MsgBox "ADO Connection State is " & connDB.State & "."

    'SQL to get the whole [underlying_symbol] table
    'strSQL = "underlying_symbol" 'if options 2
    'strSQL = "SELECT * FROM underlying_symbol" 'if options 1
    strSQL = "INSERT INTO underlying_symbol (symbol) VALUES ('xyz')"

    'late bind to adodb and get recordset object
    'Set adoRecSet = CreateObject("ADODB.Recordset")

    '&H0001 = bitmask for aCmdText
    connDB.Execute strSQL, , acCmdText

    'With adoRecSet
     '   .Open Source:=strSQL, _
      '      ActiveConnection:=connDB, _
       '     CursorType:=1, _
        '    LockType:=3, _
         '   Options:=&H1
        '.AddNew
        '.fields("symbol") = "XYZ"
        '.Update
    'End With

    '------------------

    'close the objects
    'adoRecSet.Close
    connDB.Close

    'destroy the variables
    'Set adoRecSet = Nothing
    Set connDB = Nothing

ExitMe:
    Exit Sub
ErrorHandler:
    MsgBox Err.Number & ": " & Err.Description
    GoTo ExitMe

End Sub

添加了一些错误处理,一个定义 acCmdText 的常量(为什么不添加对 ADO 库的引用?不过,这取决于你。),以及一个用于检查与数据库的连接状态的消息框,因为我不能测试您的 getProjectFile 函数。后期绑定似乎不是这里的问题,我认为关键是:

connDB.Execute strSQL, , 2, &H1

真的可以说这里发生了什么,因为我从来没有这样做过(代码甚至无法编译),但将其更改为

connDB.Execute strSQL, , acCmdText

为我工作。

【讨论】:

  • 如果我只使用 adCmdText 我会得到一个错误。对我来说,这适用于早期绑定:connDB.Execute strSQL, , adCmdText + adExecuteNoRecords 虽然早期绑定在我的情况下根本不起作用,但我已经尝试编写一堆动态参考代码,这是一个非常糟糕的主意。仅当代码仅在您有权访问的计算机上运行时,早期绑定才有效。那么你知道如何输入 adExecuteNoRecords 作为位掩码吗? connDB.Execute strSQL, , 1 + ?
  • 哈哈没关系,我想通了。 connDB.Execute strSQL, , 1 + 128 其中 (adCmdText = 1) 和 (+) (adExecuteNoRecords = 0x80 = 128)。这一点都不明显。
  • 嗯,那种工作。现在事实证明,如果您有来自同一个数据库的查询的表(即 ListObjects),它们会干扰 DML。
猜你喜欢
  • 1970-01-01
  • 2019-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-02
  • 2021-04-10
相关资源
最近更新 更多