使用 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 个工作表,代号分别为 Sheet1
、Sheet2
和 Sheet3
(这是默认设置)。所以你已经 Sheet1!A1:A3
填充了一些你想 SUM
使用 sql 的数字,因为...为什么不重要,只是 因为 .
由于我们希望将总和写入 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.Connection
和 ADODB.Recordset
类型而不是使用 Object
接口来避免的开销。
- 与工作簿的连接也是无关紧要的 运行 时间开销。
- 通过 OLEDB 查询工作表绝对不适合计算 3 个值的总和。
- 您需要记得清理您的连接和记录集!
- 不要那样做。
- 只是不要。
Sheet1.Range("A4").Value = Application.WorksheetFunction.Sum(Sheet1.Range("A1:A3"))
是本机 Excel 工作表函数解决方案的单行等价物 - 这仍然是矫枉过正,但至少它仍然在 Excel 的范围内并且不会涉及往返月球的飞行。
- 我说过不要那样做吗?
此类解决方案有用用于其他目的,例如当你有一个布局为 table 的工作簿时,它包含的信息应该存在于数据库中但不知何故存在于 Excel 工作表中,其中包含如此多的数据以至于通过 Workbooks.Open
和计算复杂的聚合(可能涉及 WHERE
和 GROUP BY
子句)使用 SUMIFS
或其他非 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 个工作表,代号分别为 Sheet1
、Sheet2
和 Sheet3
(这是默认设置)。所以你已经 Sheet1!A1:A3
填充了一些你想 SUM
使用 sql 的数字,因为...为什么不重要,只是 因为 .
由于我们希望将总和写入 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.Connection
和ADODB.Recordset
类型而不是使用Object
接口来避免的开销。 - 与工作簿的连接也是无关紧要的 运行 时间开销。
- 通过 OLEDB 查询工作表绝对不适合计算 3 个值的总和。
- 您需要记得清理您的连接和记录集!
- 不要那样做。
- 只是不要。
Sheet1.Range("A4").Value = Application.WorksheetFunction.Sum(Sheet1.Range("A1:A3"))
是本机 Excel 工作表函数解决方案的单行等价物 - 这仍然是矫枉过正,但至少它仍然在 Excel 的范围内并且不会涉及往返月球的飞行。- 我说过不要那样做吗?
此类解决方案有用用于其他目的,例如当你有一个布局为 table 的工作簿时,它包含的信息应该存在于数据库中但不知何故存在于 Excel 工作表中,其中包含如此多的数据以至于通过 Workbooks.Open
和计算复杂的聚合(可能涉及 WHERE
和 GROUP BY
子句)使用 SUMIFS
或其他非 SQL 方法效率低下。