使用SQL在Excel中操作数据

Joe*_*sky -2 sql excel integration vba excel-vba

我有一个我正在使用的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
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*don 5

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

=SUM(A1:A3)
Run Code Online (Sandbox Code Playgroud)

输入[A4]并输入您的金额,而不是以最有效的方式编写任何代码,并且不会让任何看到您所做的事情的人感到惊讶.


还是不相信?好的.坐下来,抓一些爆米花,享受骑行乐趣.

使用VBA将单元格A1-> A3读入表对象(称为x)

Excel不是数据库,它没有 - 不是你的意思"表"这个词.但这并不是什么好事.

假设您的工作簿有3张代码Sheet1,Sheet2并且Sheet3(无论如何都是默认值).所以你已经Sheet1!A1:A3填充了一些你想要SUM使用,因为......无关紧要,因为.

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

所以我们将复制Sheet1!A1:A3Sheet2:

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

接下来,我们需要一些可以Sheet2视为"表"的东西,并对它执行SQL查询.因此,我们将设置ADODB/OLEDB连接Sheet2,执行SQL查询,获取Recordset带有结果的对象,然后将值转储到Sheet1!A4.

执行此操作的邋late后期代码看起来像这样:

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
Run Code Online (Sandbox Code Playgroud)

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

在上面和=SUM(A1:A3)单元之间A4,设计决策应该是明智之举.

  • 后期绑定调用在运行时得到解决.这是开销,可以通过引用ADODB类型库并使用ADODB.ConnectionADODB.Recordset类型而不是使用Object接口来避免.
  • 与工作簿的连接也是无关的运行时开销.
  • 通过OLEDB查询工作表对于计算3个值的总和是绝对不合理的.
  • 您需要记住清理连接和记录集!
  • 不要那样做.
  • 只是不要.
  • Sheet1.Range("A4").Value = Application.WorksheetFunction.Sum(Sheet1.Range("A1:A3")) 是本机Excel工作表函数解决方案的单行代码 - 这仍然是过度的,但至少它仍然在Excel的领域,并不涉及飞向月球和返回.
  • 我说不要那样做吗?

这种类型的解决方案有用的用于其他目的,例如,当你已经制定了一个表,工作簿包含应该生活在一个数据库中的信息,但不知何故生活在一个Excel工作表中,与通过打开它这么多的数据Workbooks.Open和计算复杂聚合(可能涉及WHEREGROUP BY子句)使用SUMIFS其他非SQL方法效率低下.