【问题标题】:Excel function with ADODB connection string to Access database带有 ADODB 连接字符串到 Access 数据库的 Excel 函数
【发布时间】:2020-02-19 18:46:00
【问题描述】:

我在 Excel 函数下方创建了该函数,该函数使用 ADODB 连接到访问数据库(大约 10k 行)。 它通常有效,但有两个主要问题:

  1. 不可靠:经常返回 0 而结果应该不同
  2. 肯定很慢

有什么改进的建议吗?

Public Function TotaleSQL(Cat As String, SubCat As String, Anno As Integer) As Long
    On Error Resume Next

    Dim cn As Object, rs As Object, output As String, sql As String
    Dim src As String
    Dim Total As Long
    Dim CatLong As String

    src = "Z:\Report.accdb"

    '---Connecting to the Data Source---
    Set cn = CreateObject("ADODB.Connection")
    With cn
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .connectionstring = "Data Source=" & src & ";Persist Security Info=False"
        .Open
    End With


    '---Run the SQL SELECT Query---
    CatLong = "'" & Cat & ":" & SubCat & "'"
    sql = "SELECT Report.Withdrawal, Report.Deposit, Report.Category, Report.Date FROM Report WHERE (((Report.Category)=" & CatLong & ") AND ((Year([date]))=" & Anno & "));"

    'sql = "SELECT * FROM [Sheet1$]"
    Set rs = cn.Execute(sql)

    Total = 0

    Do
       Total = Total + Val(rs(1) & "") - Val(rs(0) & "")
       rs.Movenext
    Loop Until rs.EOF

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

    TotaleSQL = Total
End Function

【问题讨论】:

  • 很可能不可靠,因为有错误。请注意,您必须删除 On Error Resume Next,因为该行隐藏了 所有 错误消息,但错误仍然存​​在,您只是看不到它们的消息。因此,如果您没有看到错误,则无法修复它们,并且如果您不修复它们,则代码将无法按预期工作。删除该行并改正您的错误。 • 您可能会从VBA Error Handling – A Complete Guide 中受益。
  • 这可能很慢,因为您的 Do 循环遍历所有记录(如果有很多记录,它会大大减慢该过程)。显然,您只需减去两个值并将它们相加即可。尝试弄清楚如何在 SQL 中执行此操作,这样您就不需要循环了。应该可以使用一条 SQL 语句来获得该总数,而无需循环。

标签: excel vba ms-access connection-string adodb


【解决方案1】:

如果 Cat、SubCat 或 Anno 是用户输入,则在查询中使用参数会更安全。例如

Public Function TotaleSQL(Cat As String, SubCat As String, Anno As Integer)

    Const DATABASE = "Z:\Report.accdb"
    Const TABLE_NAME = "Report"

    Const SQL = " SELECT SUM(iif(Deposit is null,0,Deposit) " & _
                "        - iif(Withdrawal is null,0,Withdrawal)) " & _
                " FROM " & TABLE_NAME & _
                " WHERE Category   = ? " & _
                " AND   YEAR(ddate)= ? "

    Dim cn As Object, cmd As Object, rs As Object
    '---Connecting to the Data Source---
    Set cn = CreateObject("ADODB.Connection")
    With cn
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .connectionstring = "Data Source=" & DATABASE & ";Persist Security Info=False"
        .Open
    End With

    ' create command
    Set cmd = CreateObject("ADODB.Command")
    With cmd
        .ActiveConnection = cn
        .CommandText = SQL
        .CommandType = 1 'adCmdText
        .Parameters.Append .CreateParameter("P1", 200, 1, 50) ' 1=adParamInput 200=adVarChar
        .Parameters.Append .CreateParameter("P2", 3, 1) ' 3=adInteger
    End With

    ' execute with parameters
    With cmd
        .Parameters(0).Value = Cat & ":" & SubCat
        .Parameters(1).Value = Anno
        Set rs = .Execute
    End With

    TotaleSQL = rs(0)

    rs.Close
    cn.Close
    Set cn = Nothing
    Set rs = Nothing
    Set cmd = Nothing

End Function

Sub test()
    Debug.Print TotaleSQL("Cat", "SubCat", 2020)
End Sub

【讨论】:

  • 看起来棒极了!谢谢!只有我在“Set rs = .Execute”行出现以下错误:Microsoft Visual Basic 运行时错误“-2147467259 (80004005)”:文本文件规范“报告链接规范”不存在。您不能使用规范导入、导出或链接
  • 我有 Office 2016 Pro,在 Win 10 Pro 64 位上
  • 再次尝试,现在我得到这个错误,仍然在线“Set rs = .Execute”:运行时错误'-2147217904(80040e10)':参数太少。预计 3.
  • 当然我改变了 cat,subcat,2020。无论如何,现在我能够解决它! SQL 中的“ddate”而不是“date”出现输入错误。
  • @Andrew 创建测试数据库时,我使用 ddate 作为字段名称,因为 date 是保留字。忘记改了,呵呵!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-11
  • 2010-12-04
  • 1970-01-01
  • 2021-12-24
  • 2016-03-18
相关资源
最近更新 更多