使用 SQL 在 excel 内处理数据

Manipulating data WITHIN excel using SQL

我正在处理一份 excel 报告,该报告使用 VBA 来处理数据。

虽然我没有理由不能使用 VBA 来达到我的目的,但我宁愿使用 SQL,因为我更精通那种语言。为了做到这一点,我面临着一些挑战,并将我的问题简化为一个更容易解决的问题。

假设我有一个 Excel 电子表格,单元格 A1 中的数字为 1,单元格 A2 中的数字为 2,单元格 A3 中的数字为 3。在单元格 A4 中,我试图对这些求和,得到数字 6。

SUM() 函数会得到我想要的答案,但不是我想要的方式。

相反,这就是我想要做的...

1) read cells A1->A3 into a table object (call this x) using VBA
2) declare a string variable and set it to 'SELECT SUM(column1) FROM x'
3) execute that sql string
4) store the results in cell A4

这是一种可行的处理方式吗?如果是这样,可以发布一个例子吗?

是的,可以做到。不,不应该。如果您需要 3 个单元格的总和,计算 3 个单元格的总和 - Excel 具有内置函数 专门为此制作 .

=SUM(A1:A3)

[A4] 中输入,您将得到总和 ,无需编写任何代码,以 最有效的方式 , 毫不奇怪,看到你所做的一切的人都该死。


还不服气?好的。坐下,拿些爆米花,享受旅程。

read cells A1->A3 into a table object (call this x) using VBA

Excel 不是数据库,它没有 tables - 不是你所说的 "table".但这并不是什么大事。

假设您的工作簿有 3 个工作表,代号分别为 Sheet1Sheet2Sheet3(这是默认设置)。所以你已经 Sheet1!A1:A3 填充了一些你想 SUM 使用 的数字,因为...为什么不重要,只是 因为 .

由于我们希望将总和写入 Sheet1!A4,因此我们不会使用 Sheet1 作为我们的 "table" - 而是将其视为我们的输出。

所以我们将 Sheet1!A1:A3 复制到 Sheet2:

Sheet2.Range("A1").Value = "Values" 'our column header
Sheet1.Range("A1:A3").Copy Sheet2.Range("A2") 'our values

接下来,我们需要一些可以将 Sheet2 视为 "table" 并对其执行 SQL 查询的东西。所以我们将建立一个到 Sheet2 的 ADODB/OLEDB 连接,执行 SQL 查询,得到一个包含结果的 Recordset 对象,然后将值转储到 Sheet1!A4.

执行此操作的马虎后期绑定代码如下所示:

Public Sub OverkillSum()

    Dim connection As Object
    Set connection = CreateObject("ADODB.Connection")
    connection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                    "Data Source=" & ThisWorkbook.FullName & ";" & _
                    "Extended Properties=""Excel 8.0;HDR=Yes;"";"

    Dim recordset As Object
    Set recordset = connection.Execute("SELECT SUM(Values) As Total FROM [Sheet2$]")

    Sheet1.Range("A4").Value = recordset.Fields("Total").Value
    recordset.Close
    connection.Close

End Sub

请注意,连接字符串需要 ThisWorkbook.FullName,因此它在您尚未保存的一次性工作簿中不起作用。

在上面的内容和单元格 A4 中的 =SUM(A1:A3) 之间,设计决策 应该 是显而易见的。

  • 延迟绑定调用在 运行 时得到解决。这是可以通过引用 ADODB 类型库并使用 ADODB.ConnectionADODB.Recordset 类型而不是使用 Object 接口来避免的开销。
  • 与工作簿的连接也是无关紧要的 运行 时间开销。
  • 通过 OLEDB 查询工作表绝对不适合计算 3 个值的总和。
  • 您需要记得清理您的连接和记录集!
  • 不要那样做。
  • 只是不要。
  • Sheet1.Range("A4").Value = Application.WorksheetFunction.Sum(Sheet1.Range("A1:A3")) 是本机 Excel 工作表函数解决方案的单行等价物 - 这仍然是矫枉过正,但至少它仍然在 Excel 的范围内并且不会涉及往返月球的飞行。
  • 我说过不要那样做吗

此类解决方案有用用于其他目的,例如当你有一个布局为 table 的工作簿时,它包含的信息应该存在于数据库中但不知何故存在于 Excel 工作表中,其中包含如此多的数据以至于通过 Workbooks.Open 和计算复杂的聚合(可能涉及 WHEREGROUP BY 子句)使用 SUMIFS 或其他非 SQL 方法效率低下。