Excel VBA中写SQL,这些问题的方法你一定要牢记
小爬之前的文章 【Excel VBA中写SQL,这些问题你一定为此头痛过】中详细讲诉了一些常见的VBA 中使用SQL遇到的问题,这里再补充两个常见的问题场景及对应的解决方案,希望你们看了后能够思路开阔些,少走些弯路。
一、数据源Excel文件的工作表有些列的列名相同
我们知道,在商业数据库中创建表时,同一个表名下是不允许创建相同的字段的,且字段名要遵从一定规范。但在Excel文件中则无此限制,同一个工作表下,支持多列的列名相同。那么当我们用SQL来操作这类头疼的Excel文件时,该如何区分不同字段呢?
假设小爬有这样一个Excel表(数据样本通过python的第三方库faker来生成),【源数据】表中,A列和C列的列名都为【公司】,但其实一个指代【公司名称】,另一个指代【公司代码】,这样不规范的excel模板例子在现实工作中很常见。我们该如何区分它俩呢?

小爬试着先输出recordSet中所有字段名,看VBA的sql引擎是如何贴心处理这个问题的,示例代码如下:
1 Sub myQuery()
2 Dim conn As Object, rs As Object, rs1 As Object, sht1 As Worksheet, sht2 As Worksheet, sql As String
3 Set conn = CreateObject("ADODB.Connection")
4 Set rs = CreateObject("ADODB.recordset")
5 Set sht1 = ThisWorkbook.Sheets("源数据")
6 Set sht2 = ThisWorkbook.Sheets("结果")
7 conn.Open "provider=Microsoft.ACE.OLEDB.12.0;extended properties=excel 12.0;data source=" & ThisWorkbook.FullName
8 sql = "SELECT * FROM [源数据$]"
9 Set rs = conn.Execute(sql)
10 For i = 0 To rs.Fields.Count - 1 '输出recordset字段名到【结果】表
11 sht2.Cells(1, i + 1) = rs.Fields(i).Name
12 Next
13 sht2.Cells(2, 1).CopyFromRecordset rs '输出recordset结果到【结果】表
14 conn.Close
15 Set conn = Nothing
16
17 End Sub
输出的结果如下图所示:

可以看到,重名后的列名被sql解析成字段名后,默认跟上阿拉伯数字1,2,3……知道了sql 引擎的解析规则,我们就可以直接根据解析后的列名 如【公司】【公司1】来操作不同的字段了,没输出所有字段名前就可以做到心中有数。
二、Excel“表格”不是真正的表格文件格式
有的时候,我们从ERP系统导出的报表Excel文件,虽然是xls(xlsx)后缀,可出于种种原因,他们并非真正的Excel表格格式,可能底层依然是txt文件,小爬在工作中就没少遇到过这种奇葩问题。
解决思路如下:先利用sql的方法获取当前数据库的所有表名,如果表名是乱码,如("?????"),则该Excel文件可能底层是txt文件,至少不是规范格式的Excel文件。此时,我们可以用VBA原生的workbooks.open方法来显式打开该工作簿,自动保存,然后用SQL引擎来重新连接该工作簿即可。示例代码如下:
Const adSchemaTables = 20 '这句很重要,一定要提前定义adSchemaTables常量的值
Sub myQuery()
Dim conn As Object, rs As Object, rs1 As Object, sht1 As Worksheet, sht2 As Worksheet, sql As String, sourceFileName As String Set conn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.recordset")
sourceFileName = ThisWorkbook.Path & "\数据源\" & "测试.xls"
conn.Open "provider=Microsoft.ACE.OLEDB.12.0;extended properties=excel 12.0;data source=" & sourceFileName
Set rs = conn.openschema(adSchemaTables)
TableName = rs.Fields(2).Value
If TableName <> "源数据" Then '假定当工作簿格式规范时,工作表名为【源数据】
conn.Close
Set wb = Workbooks.Open(sourceFileName)
wb.Save
wb.Close
conn.Open "provider=Microsoft.Ace.oledb.12.0;Extended Properties=Excel 12.0;data source=" & sourceFileName
Set rs = conn.openschema(adSchemaTables)
TableName = rs.Fields(2).Value
End If
End Sub
这里面包含两个技巧:
1、当小爬用wb.save时,Excel会自动将不规范的xls文件(本质是txt)保存为规范的xls文件;
2、利用conn.openschema(adSchemaTables)输出该数据库下所有的表名,代码如下:
CONN.Open "provider=Microsoft.Ace.oledb.12.0;Extended Properties=Excel 12.0;data source=" & sourceFullName
Set rs = CONN.openschema(adSchemaTables)
Do While Not rs.EOF
tableName = rs.Fields(2).Value Debug.Print rs.Fields(2).Value '表名,对于Excel中的表或(工作表名)后面会自动加一个$
rs.MoveNext
Loop
至于上面的例子中,为啥不每次默认用VBA语法打开某个工作簿,再保存为xls文件,再用CONN来连接,自然是为了改善脚本的性能,毕竟workbooks.open相比较于CONN来连接表格,速度太慢了。
欢迎扫码关注我的公众号 获取更多爬虫、数据分析的知识!

Excel VBA中写SQL,这些问题的方法你一定要牢记的更多相关文章
- 在Excel VBA中写SQL,是一种什么体验
每每提到Excel办公自动化,我们脑海里能想到的就是公式.数据透视表.宏.VBA,这也是我们大部分人数据分析的进阶之路.当我们对于常用VBA技巧已经相当熟练后,往往会有一种"我的VBA知识够 ...
- 在Excel VBA中使用SQL到底优势在哪儿
小爬在之前的博文中多次提到,可以在VBA中写SQL来操作Excel文件,实现各类数据处理和分析需求.那么,你可能有这样的疑问:Excel原生的VBA,数据透视表,数据分析功能不够吗,为啥一定要用SQL ...
- 在mybatis中写sql语句的一些体会
本文会使用一个案例,就mybatis的一些基础语法进行讲解.案例中使用到的数据库表和对象如下: article表:这个表存放的是文章的基础信息 -- ------------------------- ...
- 浅谈Excel开发:九 Excel 开发中遇到的常见问题及解决方法
Excel开发过程中有时候会遇到各种奇怪的问题,下面就列出一些本人在开发中遇到的一些比较典型的问题,并给出了解决方法,希望对大家有所帮助. 一 插件调试不了以及错误导致崩溃的问题 在开发机器上,有时可 ...
- Excel 2013中单元格添加下拉列表的方法
使用Excel录入数据的时候我们通常使用下拉列表来限定输入的数据,这样录入数据就很少发生错误了.Excel 2013较以前的版本发生了很大的变化,那么在Excel 2013是如何添加下拉列表的呢? 下 ...
- Excel vba中访问ASP.NET MVC项目,记录访问时间,文件名称
每30秒连接一次服务器,连接成功单元格变绿色,连接失败变红色,状态单元格为17行,2列 1,打开excel文件,进入vba编辑器,新建一个modules模块,在里面先写一个每30秒执行一次ConnSe ...
- 关于在Java代码中写Sql语句需要注意的问题
最近做程序,时不时需要自己去手动将sql语句直接写入到Java代码中,写入sql语句时,需要注意几个小问题. 先看我之前写的几句简单的sql语句,自以为没有问题,但是编译直接报错. String st ...
- SSM框架中写sql在xml文件中
第一种(用Mapper.xml映射文件中定义了操作数据库sql) 注意点: 1.#{}与${} #{}表示一个占位符,使用占位符可以防止sql注入, ${}通过${}可以将parameterType传 ...
- SSM框架中写sql在dao文件中以注解的方式
1以注解方式 //两个参数其中一个是对象需写,对象.属性 @Update("update delivery_address set consignee = #{address.consign ...
随机推荐
- Arduino+ESP32 之 驱动GC9A01圆形LCD(二),移植LVGL,跑示例程序,显示自制图片
在前文Arduino+ESP32 之 驱动GC9A01圆形LCD(一), 我们已经移植好了arduino GFX库, 该库的示例程序内,还有LVGL的示例程序哦. arduino环境下移植lvgl是很 ...
- 解决github.com无法访问
解决 绕过DNS解析,直接使用本地DNS记录进行直接跳转. DNS查询 在浏览器中打开DNS查询网站:http://tool.chinaz.com/dns?type=1&host=github ...
- 入门 - 复习Kubernetes核心概念 (八)
本文将会简单介绍Kubernetes的核心概念.因为这些定义可以在Kubernetes的文档中找到,所以文章也会避免用大段的枯燥的文字介绍.相反,我们会使用一些图表(其中一些是动画)和示例来解释这些概 ...
- ARP欺骗的原理
转载请注明来源:https://www.cnblogs.com/hookjc/ 从<ARP协议工作原理>一文我们已经了解到,主机在两种情况下会保存.更新本机的ARP缓存表, 1. 接 ...
- 【linux运维】Linux服务器玩转vsftpd安装与配置
Linux服务器搭建ftp详细教程. 前言 本文,主要以vsftp软件为主进行讲解,版本为3.0.2.以介绍设置虚拟用户.权限验证为主,linux权限知识默认大家都有所了解.vsftpd设置有两种模式 ...
- 根据经纬度坐标获得省市区县行政区划城市名称,自建数据库 java python php c# .net 均适用
目录 步骤一.下载省市区边界数据 步骤二.解析CSV文件导入数据库 步骤三.在程序中根据坐标解析获得城市 在LBS应用中,根据坐标来解析获得对应是哪个城市是一个很常见的功能,比如App里面通过手机定位 ...
- 关于git和SVN的介绍和区别
主要对git,svn进行一个简单的介绍. 顺带,我会在后面把我整理的一整套CSS3,PHP,MYSQL的开发的笔记打包放到百度云,有需要可以直接去百度云下载,这样以后你们开发就可以直接翻笔记不用百度搜 ...
- 用python的turtle作图(一)静态图
最近,花了点时间,用python画图. 主要包括三部分,简单的静态图形,复杂的组合图形,图形动画. (一)画静态图形 长方形, 圆, 三角形, 平行四边形, 五角星 (二)图形的组合 笑脸, 国旗, ...
- 利用shell脚本使用kubeadm部署kubenetes 1.18.6集群环境
# README # 此脚本需要在master节点上使用 # 注意root密码,请提前修改 # 个人实验环境,注意机器最低配置:master(2G内存,1cpu2核心,否则集群会创建失败),node( ...
- Zookeeper 提供的API
上篇介绍了Zookeeper命令行相关的知识,本小作文介绍从另一个维度操作Node相关的内容:Zookeer的API.同样借用Zookeeper应用之一的数据注册与订阅中的案例类比命令行操作,重点介绍 ...