在Excel VBA中使用SQL到底优势在哪儿
小爬在之前的博文中多次提到,可以在VBA中写SQL来操作Excel文件,实现各类数据处理和分析需求。那么,你可能有这样的疑问:Excel原生的VBA,数据透视表,数据分析功能不够吗,为啥一定要用SQL来实现呢?在Excel VBA中使用SQL到底优势在哪儿?今天小爬就来带大家好好捋一捋这些问题。
首先,在VBA中写SQL,这基本算VBA的高阶功能,不是所有人都掌握,因此,上述的场景除了SQL,确实都有其它技术方案。其次,如果我们对别的技术运用的更熟练,我们完全可以用自己最擅长的技术栈来解决问题。以结果论来说,只要能解决实际问题的方案,都是好方案。
不过,小爬这里想讨论的是,假如我们对VBA原生方法,数据透视表,SQL等知识都很熟悉的前提下,我们该如何选择技术栈来解决实际问题呢,这个时候,SQL的优势在于什么?我认为有以下几点:
一、执行效率最高
跟VBA原生方法和Excel公式比较起来,SQL执行时速度要快很多。当表格数量超过一万行时,这种优势越发明显。数据量越大,越适合用SQL来解决问题,越发高效;
二、代码极为简洁
①、数据匹配场景:我们如果有多个字段要匹配时,原则上需要多个Vlookup或者VBA中建立多个字典,但是,如果我们用SQL的外连接,可能一行代码足够了;
②、数据分组聚合场景:如果我们在VBA中录制宏生成数据透视表代码,来分组聚合求最大值,EXCEL后台会自动生成大量代码,这些代码可读性极差,可如果我们使用SQL Group By,结合max,min,average等聚合函数,我们也只用一行SQL语句即可。
三、实现较为简单
有一些特殊场景,使用原生VBA方法将极为复杂,但是使用SQL可能就一行代码。以我之前一篇博文VBA如何实现筛选条件之“排除某些值”举例,这个场景,那篇文章用到了很大篇幅来使用纯VBA技巧实现这样一个看似很简单的需求,单的一个“筛选——不包含某些值”的VBA场景,我们需要用到录制宏功能,一维数组、二维数组功能、数组的转置方法、字典的remove方法、字典键快速存入数组方法等。但是其实,如果我们使用SQL,需要用到的知识点就少多了。
我们重新回顾下这个场景,【源数据】表含有【姓名】【通讯地址】【邮政编码】三列,【例外清单】表中存储着待排除在外的姓名,【结果】表要求返回【源数据】表中不包含【例外清单】姓名的所有数据。我们使用Python faker库生成20000行数据,方便比对大样本时使用不同方法效率上的差异。
如果用SQL,本质上我们需要将【源数据】表左外连接(Left Join)【例外清单】表,基于【姓名】列,再加上where条件即可。
具体代码如下:
1 Sub myQuery()
2 Dim conn As Object, rs As Object, sht1 As Worksheet, sht2 As Worksheet, sht3 As Worksheet, sql As String, startTime As Date, endTime As Date
3 startTime = Timer
4 Set conn = CreateObject("ADODB.Connection")
5 Set rs = CreateObject("ADODB.recordset")
6 Set sht1 = ThisWorkbook.Sheets("源数据")
7 Set sht2 = ThisWorkbook.Sheets("例外清单")
8 Set sht3 = ThisWorkbook.Sheets("结果")
9 conn.Open "provider=Microsoft.ACE.OLEDB.12.0;extended properties=excel 12.0;data source=" & ThisWorkbook.FullName
10 sql = "SELECT a.* FROM [源数据$]a LEFT JOIN [例外清单$]b ON a.姓名=b.姓名 WHERE b.姓名 IS NULL"
11 Set rs = conn.Execute(sql)
12 For i = 0 To rs.Fields.Count - 1 '输出recordset字段名到【结果】表
13 sht3.Cells(1, i + 1) = rs.Fields(i).Name
14 Next
15 sht3.Cells(2, 1).CopyFromRecordset rs '输出recordset结果到【结果】表
16 conn.Close
17 Set conn = Nothing
18 endTime = Timer
19 sht3.Activate
20 MsgBox "累计运行" & (endTime - startTime) & "秒"
21
22 End Sub
运行结果如下所示,耗时约0.63秒:
我们再回顾下使用VBA字典来实现这一需求的方法,代码如下:
1 Sub dictWay()
2 Dim conn As Object, rs As Object, sht1 As Worksheet, sht2 As Worksheet, sht3 As Worksheet, sql As String, startTime As Date, endTime As Date, maxRow1 As Integer, myDic As Object, maxRow2 As Integer
3 startTime = Timer
4 Application.ScreenUpdating = False
5 Set sht1 = ThisWorkbook.Sheets("源数据")
6 Set sht2 = ThisWorkbook.Sheets("例外清单")
7 Set sht3 = ThisWorkbook.Sheets("结果")
8 Set myDic = CreateObject("scripting.dictionary")
9 maxRow1 = sht1.Cells(Rows.Count, 1).End(xlUp).Row
10 maxRow2 = sht2.Cells(Rows.Count, 1).End(xlUp).Row
11 Dim i As Integer, j As Integer, k As Integer
12 For i = 2 To maxRow2
13 myDic.Add sht2.Cells(i, 1).Value, ""
14 Next
15
16 k = 1
17 For i = 1 To maxRow1
18 If myDic.exists(sht1.Cells(i, 1).Value) = False Then
19 For j = 1 To 3
20 sht3.Cells(k, j).Value = sht1.Cells(i, j).Value
21 Next
22 k = k + 1
23 End If
24
25 Next
26
27 endTime = Timer
28 sht3.Activate
29 Application.ScreenUpdating = True
30 MsgBox "累计运行" & (endTime - startTime) & "秒"
31
32 End Sub
为了让该方法尽可能提速,我们使用了字典,同时关掉了Excel的屏幕刷新。最终20000行数据时,耗时约4秒:
可以看到,与之前VBA的方法比起来,只需要一行SQL语句,逻辑清晰易懂,代码简洁明了,程序运行耗时是传统方法的1/6不到,这就是小爬力推在VBA中使用SQL的主要原因~~
欢迎扫码关注我的公众号 获取更多爬虫、数据分析的知识!
在Excel VBA中使用SQL到底优势在哪儿的更多相关文章
- Excel VBA中写SQL,这些问题的方法你一定要牢记
小爬之前的文章 [Excel VBA中写SQL,这些问题你一定为此头痛过]中详细讲诉了一些常见的VBA 中使用SQL遇到的问题,这里再补充两个常见的问题场景及对应的解决方案,希望你们看了后能够思路开阔 ...
- 在Excel VBA中写SQL,是一种什么体验
每每提到Excel办公自动化,我们脑海里能想到的就是公式.数据透视表.宏.VBA,这也是我们大部分人数据分析的进阶之路.当我们对于常用VBA技巧已经相当熟练后,往往会有一种"我的VBA知识够 ...
- Excel vba中访问ASP.NET MVC项目,记录访问时间,文件名称
每30秒连接一次服务器,连接成功单元格变绿色,连接失败变红色,状态单元格为17行,2列 1,打开excel文件,进入vba编辑器,新建一个modules模块,在里面先写一个每30秒执行一次ConnSe ...
- excel VBA中正则模块vbscript.regexp的用法
一.是一个对象,用于执行 正则表达式! 二.有三个属性: 1. Global属性: True or False, 指明模式是匹配整个字符串中所有与之相符的地方还是只匹配第一次出现的地方.默认 ...
- excel VBA中Xldown和xlup用法
1.Worksheets("Sheet1").Range("A1").End(xlDown).Select '意思为自A1起,返回从上往下的最后一个非空 ...
- Excel 2003 中如何用VBA 代码访问单元格里的值及操作单元格 - 唐诗宋词的专栏 - 博客频道 - CSDN.NET
在Excel 中编写VBA 代码,最常做的事可能就是操作表单中单元格里的数据. 我这里总结一下如何从VBA 代码中操作单元格的数据. 在VBA 代码中操作单元格需要用到Range 对象,Range 是 ...
- Excel VBA 连接各种数据库(三) VBA连接SQL Server数据库
本文主要涉及: VBA中的SQL Server环境配置 VBA连接SQL Server数据库 VBA读写SQL Server数据 如何安装SQL Client 系统环境: Windows 7 64bi ...
- Excel VBA 连接各种数据库(一) VBA连接MySQL数据库
本文参考[东围居士]的cnblog博文 Excel.VBA与MySQL交互 在自己机器上调试成功,把调试中遇到的问题一并写出了. 本文主要涉及: VBA中的MySQL环境配置 VBA连接MySQL ...
- 嫌Excel VBA执行速度慢,这些建议你一定要看
Excel是办公利器,这无需多言.尤其在办公室,Excel用的熟练与否,会的Excel知识点多不多,很大程度上决定了你工作是否高效,能否按时打卡下班.可我们也时常听到这样的吐槽:Excel好是好,可就 ...
随机推荐
- Ubuntu18.04升级内核后修改grub文件启动顺序
采坑:之前线上的服务器内核是4.15.0,后面有的服务跑不起来,说是要升级内核,于是就升级了,然后改了/etc/default/grub的启动顺序,改错了就启动不起来了,哈哈.后面多次尝试还是改成功了 ...
- UI自动化,通过Xpath结合父类、同级元素,查找到唯一的元素定位
UI自动化,通过Xpath定位的总结 当页面展示的内容的html布局格式一样,只能第几个控件的绝对定位来区分时,如果后面有变更控件的顺序,就会导致找不到这个元素,维护成本较高,可以尝试用其他的方式,比 ...
- Typescript Record的用法
Record<Keys,Type> 构造一个对象类型,其属性key是Keys,属性value是Tpye.被用于映射一个类型的属性到另一个类型 interface CatInfo { age ...
- 基于CentOS7.x gitlab环境搭建,卸载,汉化 --汉化篇
gitlab环境搭建,卸载,汉化--汉化篇 注意gitlab的版本需和汉化版本一致 安装git yum install -y git 下载最新的汉化包 cd git clone https://git ...
- 51 Nod 1133 不重叠的线段 (贪心算法)
原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1133 题目分析:感觉这到第不应该被分到二级算法题,比 109 ...
- C#获取http图片
public Image GetHttpImage(string url) { var client = new HttpClient(); var uri = new Uri(Uri.EscapeU ...
- IDEA包名分层问题
解决办法: 将默认的"Hide empty Middle Packages"或者"compact middle packages"勾选项去掉,这样就不会把中间空 ...
- 为什么 Redis 的查询很快, Redis 如何保证查询的高效
Redis 如何保证高效的查询效率 为什么 Redis 比较快 Redis 中的数据结构 1.简单动态字符串 SDS 对比 c 字符串的优势 SDS可以常数级别获取字符串的长度 杜绝缓冲区溢出 减少修 ...
- How to check in Windows if you are using UEFI
You might be wondering if Windows is using UEFI or the legacy BIOS, it's easy to check. Just fire up ...
- python24day
内容回顾 命名空间 组合 一个类的对象是另一个类对象的属性 两个类之间有 什么有什么二点关系:例:班级有学生 学生和课程.圆形和圆环.班级和课程 计算器 from functools import r ...