在 VBA 中使用 SQL 连接两个 Excel 工作簿中的数据(只读错误)

Posted

技术标签:

【中文标题】在 VBA 中使用 SQL 连接两个 Excel 工作簿中的数据(只读错误)【英文标题】:Using SQL in VBA to Join Data from two Excel Workbooks (Read-Only error) 【发布时间】:2019-08-21 17:30:15 【问题描述】:

我正在寻求加入两个非常大的 Excel 工作簿中的特定数据,然后将其保存到另一个工作簿。为了做到这一点,我使用 ADODB 对象来使用 SQL 命令,这使得执行连接比执行数十万个 VLookup 更容​​易。我的设置会提示一个状态的名称,并且数据源被格式化为依赖于这个状态。假设您输入了“内华达州”。它将连接到一个名为“Nevada - bio metadata multiple cont”的文件,并将其连接到另一个名为“Nevada - Site data only multiple cont”的文件,并从中选择某些字段。

当我调试时,我可以看到连接工作正常,并且我将字符串变量 'sql' 更改为等于“SELECT * FROM [biologicalresult$]”,它会正常工作。该问题似乎与我通过 ADODB 查询将其加入另一个工作簿这一事实有关,并且我收到错误消息:“无法更新。数据库或对象是只读的”

Option Explicit

Sub RunSELECT()

    On Error GoTo ErrorHandling

    Dim cn As Object, rs As Object, output As String, sql As String, state As String
    state = InputBox("Please insert the state name with the first letter being capital")

    Set cn = CreateObject("ADODB.Connection")

    '---Connecting to the Data Source---
    With cn
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .connectionstring = "Data Source=T:\Marketing\Data Analytics\GIS Data\Water Quality Portal Data\State Data\" & state & _
                            " - biological metadata multiple cont;Extended Properties=""Excel 12.0 Xml;HDR=YES;Readonly = false;IMEX = 0"";"
        .Open
    End With

    '---Run the SQL SELECT Query---
    sql = "SELECT b.OrganizationIdentifier, b.OrganizationFormalName, b.MonitoringLocationIdentifier, s.LatitudeMeasure, s.LongitudeMeasure, " & _
        "b.ActivityIdentifier , b.ActivityTypeCode, b.ActivityMediaName, b.ActivityMediaSubdivisionName, " & _
        "b.ActivityStartDate, b.ProjectIdentifier, b.CharacteristicName, b.ResultSampleFractionText, b.ResultMeasureValue, b.[ResultMeasure/MeasureUnitCode] " & _
        "FROM [biologicalresult$] b INNER JOIN (SELECT * FROM [Excel 12.0 Xml; IMEX = 0; HDR = Yes; Database = T:\Marketing\Data Analytics\GIS Data\Water Quality Portal Data\" & _
        "State Data\" & state & " - Site data only multiple cont;Readonly = False].[station$]) s " & _
        "ON b.MonitoringLocationIdentifier = s.MonitoringLocationIdentifier;"

    Set rs = cn.Execute(sql)

    '---Clean up---
    rs.Close
    cn.Close
    Set cn = Nothing
    Set rs = Nothing

Exit Sub

ErrorHandling:
    MsgBox ("Source: " & Err.Source & vbNewLine & "Number: " & Err.Number & vbNewLine & "Description: " & Err.Description & vbNewLine & "Help Context: " & Err.HelpContext)
done:
    End Sub

感谢您的帮助!

【问题讨论】:

【参考方案1】:

诚然,该错误信息量不大,因为问题可能是由文件路径问题引起的。然而,这个简单的印刷修复可能对犯同样微妙错误的未来读者有所帮助。顺便说一句,对于长名称,请考虑单独的变量并连接成连接和 SQL 字符串。

    在源文件中包含完整路径,包括扩展名、.xlsx.xlsm

    meta_file = "T:\Marketing\Data Analytics\GIS Data\Water Quality Portal Data\State Data\" _
                 & state & " - biological metadata multiple cont.xlsx"
    
    With cn
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .connectionstring = "Data Source=" & meta_file & ";Extended Properties=""Excel 12.0 Xml;HDR=YES;Readonly=false;IMEX=0"";"
        .Open
    End With
    

    删除括号命名空间内 Database 参数前后的空格:...Database=T:\Marketing\...。否则,引擎会将空格解释为名称的一部分。甚至考虑删除所有参数 IMEXHDRReadonly 等之间的空格。

    site_file = "T:\Marketing\Data Analytics\GIS Data\Water Quality Portal Data\State Data\" _
                 & state & " - Site data only multiple cont.xlsx"
    
    '---Run the SQL SELECT Query---
    sql = "SELECT b.OrganizationIdentifier, b.OrganizationFormalName, " & _
          "       b.MonitoringLocationIdentifier, s.LatitudeMeasure, " & _ 
          "       s.LongitudeMeasure, b.ActivityIdentifier, b.ActivityTypeCode, " & _ 
          "       b.ActivityMediaName, b.ActivityMediaSubdivisionName, " & _
          "       b.ActivityStartDate, b.ProjectIdentifier, b.CharacteristicName, " &  _
          "       b.ResultSampleFractionText, b.ResultMeasureValue, " & _
          "       b.[ResultMeasure/MeasureUnitCode] " & _
          "FROM [biologicalresult$] b " & _
          "INNER JOIN (SELECT * FROM [Excel 12.0 Xml;IMEX=0;HDR=Yes;" & _
          "                           Database=" & site_file & ";Readonly=False].[station$]) s " & _
          "ON b.MonitoringLocationIdentifier = s.MonitoringLocationIdentifier;"
    

【讨论】:

以上是关于在 VBA 中使用 SQL 连接两个 Excel 工作簿中的数据(只读错误)的主要内容,如果未能解决你的问题,请参考以下文章

Excel VBA - 搜索范围和连接的 SQL ADODB 记录集以在列中匹配写入结果集

Excel VBA 连接各种数据库 VBA连接SQL Server数据库

在excel中用vba实现与sql数据库的数据比较

有没有办法在没有 VBA 的情况下在 Excel 中连接两个数组? [复制]

使用 VBA 将 Excel 表连接到 SQL Server

Excel VBA 连接SQL数据库后的操作。