从0学Excel VBA编程 · 番外篇9:连接外部数据库——打通 Excel 与 Access / CSV / SQL Server
学习目标
明白 ADO 是什么,以及它怎么把 Excel 变成"万能查库器" 学会写三种常见数据库的连接串(Access / CSV / SQL Server) 用一个公共函数,把任意 SQL 查询结果一键写回工作表
知识点精讲
前面两篇(番外篇7、8)我们都是把 Excel 当数据库来查。但办公里更多情况是:数据本来就躺在别处——Access 里的业务库、一堆每天导出的 CSV、公司服务器上的 SQL Server。难道要把它们先复制到 Excel 再查?太笨了。
这一篇教你怎么直接连上去查,结果写回 Excel 就行。
核心工具叫 ADO(ActiveX Data Objects)。你就把它理解成 Excel 和外部数据库之间的"通用数据线"。我们只需要两个对象:
Connection(连接):负责"拨号",把 Excel 和数据库连起来。 Recordset(记录集):连上之后,SQL 查出来的结果就装在它里面,我们用 CopyFromRecordset一次性倒进工作表。
连不同的库,区别只在连接串怎么写(就像不同的地址和钥匙):
Provider=Microsoft.ACE.OLEDB.12.0; Data Source=完整路径 | |
Provider=Microsoft.ACE.OLEDB.12.0; Data Source=文件夹路径; Extended Properties="text;HDR=Yes;FMT=Delimited" | |
Provider=SQLOLEDB; Server=IP或机器名; Database=库名; UID=账号; PWD=密码 |
连接串铁律:CSV 的 Data Source 必须写到"文件夹",且带末尾反斜杠;表名就是 文件名.csv。其他两种 Data Source 写到具体文件或库名。
3 个实战案例
三个案例共用一个公共函数
运行外部SQL,它负责"连库 → 执行 SQL → 写字段名+数据 → 关连接"。案例本身只关心"连什么、查什么"。
案例1(简单):连本地 Access,把订单查出来
功能说明:公司有个 销售.accdb,里面一张 订单 表。一键把金额大于 1000 的订单按金额从高到低查到 Excel。
代码:
' 公共函数:连任意库、执行 SQL、结果写回指定表(含字段名)Sub 运行外部SQL(连接串 As String, SQL As String, 目标表名 As String) Dim conn As Object, rs As Object Dim ws As Worksheet Dim i As Integer Set conn = CreateObject("ADODB.Connection") Set rs = CreateObject("ADODB.Recordset") conn.Open 连接串 ' ① 拨号连库 rs.Open SQL, conn ' ② 执行 SQL,结果进 Recordset ' 目标表不存在就新建 On Error Resume Next Set ws = ThisWorkbook.Sheets(目标表名) If ws Is Nothing Then Set ws = ThisWorkbook.Sheets.Add ws.Name = 目标表名 End If On Error GoTo 0 ws.Cells.Clear ' ③ 先写字段名(表头) For i = 0 To rs.Fields.Count - 1 ws.Cells(1, i + 1).Value = rs.Fields(i).Name Next i ' ④ 再写数据(从第2行开始) ws.Range("A2").CopyFromRecordset rs ws.Rows(1).Font.Bold = True rs.Close conn.Close Set rs = Nothing Set conn = Nothing MsgBox "查询完成,结果已写入【" & 目标表名 & "】", vbInformationEnd Sub' 案例1:连 AccessSub 案例1_查询Access() Dim 连接串 As String, SQL As String 连接串 = "Provider=Microsoft.ACE.OLEDB.12.0;" & _ "Data Source=C:\数据\销售.accdb;" SQL = "SELECT * FROM 订单 WHERE 金额 > 1000 ORDER BY 金额 DESC" Call 运行外部SQL(连接串, SQL, "Access结果")End Sub操作步骤:
把 C:\数据\销售.accdb换成你真实的 Access 文件路径(含扩展名)。确认表名是 订单、字段名是金额;不是就改 SQL。把 案例1_查询Access整段粘进模块,运行它,结果自动写到新表"Access结果"。
案例2(中等):连一文件夹 CSV,按地区筛选
功能说明:每天导出的 CSV 都丢在 C:\数据\csv\ 里。把这个文件夹当作"数据库",只挑"华东"地区的记录查出来。
代码:
' 案例2:连 CSV 文件夹Sub 案例2_查询CSV() Dim 文件夹 As String Dim 连接串 As String, SQL As String 文件夹 = "C:\数据\csv\" ' 注意:必须带末尾反斜杠 连接串 = "Provider=Microsoft.ACE.OLEDB.12.0;" & _ "Data Source=" & 文件夹 & ";" & _ "Extended Properties=""text;HDR=Yes;FMT=Delimited;""" ' CSV 文件名就是表名,要带 .csv SQL = "SELECT * FROM 销售2026.csv WHERE 地区 = '华东'" Call 运行外部SQL(连接串, SQL, "CSV结果")End Sub操作步骤:
把 文件夹改成你放 CSV 的真实路径,末尾一定要加\。把 销售2026.csv改成你要查的 CSV 文件名(带扩展名)。把 地区、'华东'换成你 CSV 里真实存在的列名和值。运行,结果写进"CSV结果"表。
小提示:CSV 当数据库时,每一列的类型由前 8 行"猜"出来。若数字被当文本,可在文件夹里放一个
Schema.ini指定列类型,新手先用默认即可。
案例3(实用):连 SQL Server,按日期汇总
功能说明:公司服务器上的 销售库 有一张 订单 表。一键查"2026 年以来各产品的总销量",结果写回 Excel,比在数据库客户端里导省事多了。
代码:
' 案例3:连 SQL ServerSub 案例3_查询SQLServer() Dim 连接串 As String, SQL As String 连接串 = "Provider=SQLOLEDB;" & _ "Server=192.168.1.10;" & _ "Database=销售库;" & _ "UID=sa;" & _ "PWD=你的密码;" SQL = "SELECT 产品, SUM(数量) AS 总数量 " & _ "FROM 订单 " & _ "WHERE 日期 >= '2026-01-01' " & _ "GROUP BY 产品 " & _ "ORDER BY 总数量 DESC" Call 运行外部SQL(连接串, SQL, "SQL结果")End Sub操作步骤:
把 Server改成数据库服务器 IP 或机器名,Database改成真实库名。把 UID、PWD换成你有权限的账号密码(注意:真实环境别把密码写死在代码里,可改为运行时用InputBox输入)。确认 订单表有产品、数量、日期字段;否则改 SQL。运行,结果写进"SQL结果"表。
安全提醒:SQL Server 密码写在代码里只是演示。正式用建议从配置文件读取(参考番外篇2 的
config.txt),或直接弹窗输入,避免泄露。
本篇小结
ADO = 万能数据线: Connection拨号连库,Recordset装结果,CopyFromRecordset倒进工作表。三种库只差连接串:Access 写文件、CSV 写文件夹(带反斜杠)、SQL Server 写 IP+库+账号。 一套公共函数走天下: 运行外部SQL封装了连/查/写/关,换库只改连接串和 SQL,业务逻辑不用动。两道铁律:本机要装 Access 数据库引擎(ACE.OLEDB.12.0);路径、表名、中文列名 [ ]必须写对。
下一篇预告
番外篇10(可选):用 Command 参数化查询——把 SQL 里的条件做成参数,既防注入又好看;或就此收尾,把 1~9 番外 + 收尾篇整理成《VBA 自动化工具箱》总目录。你点哪个方向,我就写哪个。
夜雨聆风