每每提到Excel办公自动化,我们脑海里能想到的就是公式、数据透视表、宏、VBA,这也是我们大部分人数据分析的进阶之路。当我们对于常用VBA技巧已经相当熟练后,往往会有一种“我的VBA知识够用啦”的错觉,其实那只是因为我们收到的实际需求还不够复杂和多样化。

  一旦哪天碰到略显复杂的业务需求时,我们才知道VBA变量、循环、条件判断、数组、字典、窗体,这些还只是VBA的基础知识罢了,会了这些,远达不到【蒂花之秀】的水准。我们今天的主角,SQL(结构化查询语言),通过嵌入VBA代码中,就可以解决很多复杂的实际问题。

  考虑到写VBA的大军主要还是办公人员,如财务岗、行政岗,并非科班程序员出身,他们往往觉得SQL是后端程序员才使用的语言,并不那么容易掌握,其实这不过是另一种认知的偏差。我们今天就通过一个简单例子,看看在VBA中如何写SQL,是一种什么体验。

  想要在VBA中使用SQL,我们就不得不先认识下ADO。

ADO,其实是ActiveX Data Objects的简称,说人话,它其实是几个ActiveX对象(类),用于提供数据(Data)之间的访问。

Connection:ADO Connection 对象用于创建一个访问某个数据源的开放连接。基于此开发连接,我们可以对一个数据库进行访问和相关操作;

Recrodset:ADO Recordset 对象用于存储一个来自数据库表的记录集。一个 Recordset 对象由记录和列(字段)组成。它也是我们最常用的操作数据库的对象。

  我们数据库的数据源(dataSource)可以是Access、SQL Server、Oracle 等数据库,也可以是简单的text文件,甚至可以是一个excel文件。考虑到办公人员的主要数据来源都是通过excel本身。我们先来看看如何连接excel文件作为我们的数据源。

03版本Excel(.xls)

Provider=Microsoft.jet.OLEDB.4.0;Extended Properties=’Excel 8.0;HDR=yes;IMEX=0’;Data Source=带路径的Excel工作簿完整名称;

07~19版本Excel(.xlsx 或.xlsm)

Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=’Excel 12.0; HDR=yes;IMEX=0’;Data Source=带路径的Excel工作簿完整名称。

如何理解【Data Source=带路径的Excel工作簿完整名称】这句话?

  翻译成程序语言,就是要这个文件的完整路径,如果我们要控制的数据源就是我们当前的xlsm宏文件,那么就是Data Source=thisworkbook.FullName,如果是同目录下某个'test.xlsx'文件,我们则可以写作:Data Source=thisworkbook.path &"\test.xlsx".

  有了这些基础知识,我们还需要知道SQL的一些基础语法,此处推荐SQL 教程 (w3school.com.cn) 进行入门。

现在我们就可以使用SQL Select语句做一个最基础的查询了。

场景一:利用SQL将【表一】数据拷贝到【表二】

代码如下:

 1 Sub myFirstQuery()
2 '将表一的数据查询到后,返回到表二中,包含字段名
3 Dim CONN As Object, sht As Worksheet, RS As Object, i As Integer
4 Set CONN = CreateObject("ADODB.Connection")
5 Set sht = ThisWorkbook.Sheets("表二")
6 CONN.Open "provider=Microsoft.Ace.oledb.12.0;Extended Properties=Excel 12.0;data source=" & ThisWorkbook.FullName
7 Sql = "SELECT * FROM [表一$]" '查找表一的所有数据,*默认指查找所有字段内容
8 Set RS = CONN.Execute(Sql)
9
10 For i = 0 To RS.Fields.Count - 1 '输出字段名,也就是excel列名,索引从0开始,而Excel行列索引号均从1开始计数
11 sht.Cells(1, i + 1).Value = RS.Fields(i).Name
12 Next
13 sht.Cells(2, 1).CopyFromRecordset RS '将查询到的recordset数据集粘贴到表二的A2单元格
14 CONN.Close
15 End Sub

场景二:筛选【表一】中 姓名为‘温宁’的数据到【表二】中

其实,有了sql基础,我们只需要对上面的代码加上Where条件判断子句即可。

代码如下:

 1 Sub myFirstQuery()
2 '将表一的数据查询到后,返回到表二中,包含字段名
3 Dim CONN As Object, sht As Worksheet, RS As Object, i As Integer
4 Set CONN = CreateObject("ADODB.Connection")
5 Set sht = ThisWorkbook.Sheets("表二")
6 CONN.Open "provider=Microsoft.Ace.oledb.12.0;Extended Properties=Excel 12.0;data source=" & ThisWorkbook.FullName
7 Sql = "SELECT * FROM [表一$] WHERE 姓名='温宁'" '查找表一中姓名='温宁'的所有数据
8 Set RS = CONN.Execute(Sql)
9
10 For i = 0 To RS.Fields.Count - 1 '输出字段名,索引从0开始,而Excel行列索引号均从1开始计数
11 sht.Cells(1, i + 1).Value = RS.Fields(i).Name
12 Next
13 sht.Cells(2, 1).CopyFromRecordset RS '将查询到的recordset数据集粘贴到表二的A2单元格
14 CONN.Close
15 End Sub

  通过以上两个场景不难看出,核心的逻辑只需要一句SQL就足以,SQL并不是什么程序员才能掌握的东西,我们完全不用担心无法掌握它。不过我们每次使用前都要提前定义CONNECTION、RECORDSET等对象,包括输出字段名等必要操作。因此,当如果我们的业务足够简单时,使用VBA中的基础功能反而写起来更快,当业务逻辑复杂时,我们才会重点考虑SQL,永远不用为了用SQL而刻意写SQL。用对了地方,SQL就是六脉神剑;用错了地方,就真成了花里胡哨的炫技,Duck不必。

欢迎扫码关注我的公众号 获取更多爬虫、数据分析的知识!



在Excel VBA中写SQL,是一种什么体验的更多相关文章

  1. Excel VBA中写SQL,这些问题的方法你一定要牢记

    小爬之前的文章 [Excel VBA中写SQL,这些问题你一定为此头痛过]中详细讲诉了一些常见的VBA 中使用SQL遇到的问题,这里再补充两个常见的问题场景及对应的解决方案,希望你们看了后能够思路开阔 ...

  2. 在Excel VBA中使用SQL到底优势在哪儿

    小爬在之前的博文中多次提到,可以在VBA中写SQL来操作Excel文件,实现各类数据处理和分析需求.那么,你可能有这样的疑问:Excel原生的VBA,数据透视表,数据分析功能不够吗,为啥一定要用SQL ...

  3. 转 mysql mysql命令行中执行sql的几种方式总结

    https://www.jb51.net/article/96394.htm 1.直接输入sql执行 MySQL> select now(); +---------------------+ | ...

  4. 在mybatis中写sql语句的一些体会

    本文会使用一个案例,就mybatis的一些基础语法进行讲解.案例中使用到的数据库表和对象如下: article表:这个表存放的是文章的基础信息 -- ------------------------- ...

  5. Excel vba中访问ASP.NET MVC项目,记录访问时间,文件名称

    每30秒连接一次服务器,连接成功单元格变绿色,连接失败变红色,状态单元格为17行,2列 1,打开excel文件,进入vba编辑器,新建一个modules模块,在里面先写一个每30秒执行一次ConnSe ...

  6. 关于在Java代码中写Sql语句需要注意的问题

    最近做程序,时不时需要自己去手动将sql语句直接写入到Java代码中,写入sql语句时,需要注意几个小问题. 先看我之前写的几句简单的sql语句,自以为没有问题,但是编译直接报错. String st ...

  7. SSM框架中写sql在xml文件中

    第一种(用Mapper.xml映射文件中定义了操作数据库sql) 注意点: 1.#{}与${} #{}表示一个占位符,使用占位符可以防止sql注入, ${}通过${}可以将parameterType传 ...

  8. SSM框架中写sql在dao文件中以注解的方式

    1以注解方式 //两个参数其中一个是对象需写,对象.属性 @Update("update delivery_address set consignee = #{address.consign ...

  9. 在myeclipse中写sql语句的细节问题

    注意类型,varchar 和int  在java中表示为sql语句中的细微区别!! 下面的REGISEAT_NUM为int 类型       custid为varchar类型 String sql1= ...

随机推荐

  1. 【LeetCode】283. Move Zeroes 解题报告(Java & Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:首尾指针 方法二:头部双指针+双循环 方法三 ...

  2. Java线程安全MAP ,LIST ,SET

    ConcurrentHashMap是线程安全的HashMap, CopyOnWriteArrayList是线程安全的ArrayList CopyOnWriteArraySet是线程安全的Set.

  3. Redis的各种实现(Jedis、Redisson、Lettuce)

    1.1.Jedis 是Redis的Java实现的客户端.支持基本的数据类型如:String.Hash.List.Set.Sorted Set. 特点:使用阻塞的I/O,方法调用同步,程序流需要等到so ...

  4. C++函数参数的传递顺序

    C++编译器默认使用的是 __cdecl 模式,参数是通过栈传递的,因此是从右到左的传参顺序. int f(int a, int b, int c) { return 0; } int main(){ ...

  5. [Kaiming]Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification

    目录 概 主要内容 PReLU Kaiming 初始化 Forward case Backward case He K, Zhang X, Ren S, et al. Delving Deep int ...

  6. js处理复杂数据格式数组嵌套对象,对象嵌套数组,reduce处理数据格式

    let list=[ {id:1,name:'a'}, {id:1,name:'b'}, {id:1,name:'c'}, {id:2,name:'A'}, {id:2,name:'B'}, {id: ...

  7. Linux设置主机名与hosts映射

    目的 方便操作,便于建立Linux集群. 设置主机名 查看主机名:hostname 设置主机名,修改/etc/hosts:vim /etc/hostname 通过主机名ping通 原理 通过hosts ...

  8. Java初学者作业——判断该年份是否为闰年,并输出判断结果

    返回本章节 返回作业目录 需求说明: 从控制台输入年份,判断该年份是否为闰年,并输出判断结果. 实现思路: 可通过运算符实现闰年判断的条件: (1)能被4整除且不能被100整除的年份 实现:(年份 % ...

  9. 在CentOS7系统安装与配置RabbitMQ

    在CentOS7系统安装与配置RabbitMQ 远程访问需要开放端口 https://www.cnblogs.com/heqiuyong/p/10460150.html

  10. Solr单机安装Version5.5.2

    Solr安装单机模式,基于Solr的安装版本为5.5.2. 安装规划 IP/机器名 安装软件 运行进程 zdh-9 solr jar 安装用户 solr/zdh1234 hadoop useradd ...