VBA中练习ADO:ActiveX Data Object
前期绑定,要先添加引用---"Microsoft ActiveX Data Objects 6.1"
ADO学习的权威参考可点击:w3school
ADO简单理解:是几个ActiveX对象(类),用于数据(Data)访问。
Connection:ADO Connection 对象用于创建一个到达某个数据源的开放连接。通过此连接,可以对一个数据库进行访问和操作。
Command:ADO Command 对象用于执行面向数据库的一次简单查询。此查询可执行诸如增删查改等动作。
Command 对象的主要特性是有能力使用存储查询和带有参数的存储过程。
Recrodset:ADO Recordset 对象用于容纳一个来自数据库表的记录集。一个 Recordset 对象由记录和列(字段)组成。
在 ADO 中,此对象是最重要且最常用于对数据库的数据进行操作的对象。
(三个对象的使用场景可先跳到本文末尾看一下留个印象)
案例:ado.xlsm的[Sheet1]工作表中有一些数据,文件的保存路径:C:\Users\stone\Desktop\ado.xlsm
ado方式访问excle数据,无论表格是否打开状态,都可读取、修改数据,还是很有用的。
一、执行非查询语句。(增、删、改)
执行非查询,一般目的是直接对数据库操作,不返回结果。不需要使用Recordset对象。
1、Connection:使用connection执行一个非查询
Sub AdoCnn()
Dim cnn As New ADODB.Connection
'定义cnn属性
cnn.Provider = "Microsoft.ACE.OLEDB.12.0"
'定义连接字符串
cnn.ConnectionString = "Data Source=C:\Users\stone\Desktop\ado.xlsm;Extended Properties=""Excel 12.0"";"
cnn.Mode = adModeReadWrite
'打开连接
cnn.Open
Dim sql As String
'sql脚本
'sql = "update [Sheet1$] set 年龄=年龄-10 where 姓名=""张三""" '改
sql = "insert into [Sheet1$] values(""王七"",50)" '增
'执行语句
Dim count As Integer
cnn.Execute sql, count, adCmdText
17
Debug.Print "共影响了" & count & "行"
19 cnn.Close
End Sub
Function Execute(CommandText As String, [RecordsAffected], [Options As Long = -1]) As Recordset
Connection对象的Execute方法有三个参数:
1、CommandText:要执行的 SQL 语句、表名称、存储过程、URL 或提供者特有的文本。
2、RecordsAffected:返回受影响的行数(像一个输出参数)。
3、Options:指示如何设置计算 commandtext 参数。可以是一个或多个 CommandTypeEnum 或 ExecuteOptionEnum 值。
默认adCmdUnspecified(不指定命令类型的参数)。
adCmdText:指示CommandText是sql命令
adCmdStoreProc:指示CommandText是存储过程名
4、它的返回值是Recordset对象,始终是只读的、仅向前的游标。(见下文“执行查询语句”部分)
(本例中执行的是“非查询语句”,没有使用返回值。)
2、Command:使用command对象执行一个带有"参数"的sql非查询语句(sql语句的参数化)
注:参数化,是防止SQL注入的有效方法。
Sub AdoCmd()
Dim str As String
str = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\stone\Desktop\ado.xlsm;Extended Properties=""Excel 12.0"";"
Dim cnn As New ADODB.Connection
'在open方法中,给连接字符串赋值
cnn.Open str
Dim sql As String
'sql脚本,在T-SQL语法中,用"@变量名"表示变量,这种在Sql语句中使用变量的方法叫做:参数化
sql = "update [Sheet1$] set 年龄=年龄-10 where 姓名=@name"
Dim cmd As New ADODB.Command
cmd.CommandText = sql
cmd.ActiveConnection = cnn
'给sql语句中使用到的参数赋值
cmd.Parameters("@name").Value = "张三"
cmd.Execute
16
' '另一种参数化的方法,替换掉上面13-15行
'Dim p As New ADODB.Parameter
' p.Name = "@name"
' p.Value = "张三"
'Dim count As Integer
'cmd.Execute count, p, adCmdText
' '输出受影响的行数
'Debug.Print count
25 cnn.Close
End Sub
Function Execute([RecordsAffected], [Parameters], [Options As Long = -1]) As Recordset
1、第一参数返回受影响的行数(输出参数)
2、第二参数传入需要使用的Parameter。(代码第22行)本例中参数只有一个@name,直接使用了Parameter。
3、第二参数如果有多个可以使用Array(p1,p2...):cmd.Execute count, Array(p1, p2),adCmdText
二、执行查询语句:
执行查询语句,一般都要对查询结果进行处理,比如在查询得到的记录集的基础中修改数据,以至达到更新修改源数据的目的。先转载一个抄来的一段对RecordSet的描述:原文参考请点
Recordset对象的作用是由数据库返回记录集。根据查询结果返回一个包含所查询数据的记录集。
因为删除、更新、添加操作不需要返回记录集,因此可以直接使用连接对象或是命令对象的Exexut方法,但是利用记录集对象有时会更简单
此外,通过记录集对象能够实现比较复杂的数据库管理任务。
Recordset对象可以用来代表表中的记录,可以把记录集看成是一张虚拟的表格,包含一条或多条记录(行),每条记录包含一个或多个字段
但任何时候只有一条记录为当前记录。
1、使用Connection对象或Command对象的Execte方法取得Recordset,得到的是仅向前的、只读的记录集,无法修改更新。
通过下面的测试可以说明,重点看CursorType和LockType两个属性:
'测试Connection的Execute方法得到记录集
Sub AdoCnn2()
Dim cnn As New ADODB.Connection
cnn.Provider = "Microsoft.ACE.OLEDB.12.0"
cnn.ConnectionString = "Data Source=C:\Users\stone\Desktop\ado.xlsm;Extended Properties=""Excel 12.0"";"
cnn.Open
Dim sql As String
sql = "select * from [Sheet1$]"
'定义记录集对象,接收查询结果
Dim rst As New ADODB.Recordset
Set rst = cnn.Execute(sql)
Debug.Print rst.State
'输出游标类型
Debug.Print rst.CursorType
'输出锁定类型
Debug.Print rst.LockType
rst.Close
cnn.Close
End Sub '测试Command的Execute方法得到记录集
Sub AdoCmd2()
Dim str As String
str = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\stone\Desktop\ado.xlsm;Extended Properties=""Excel 12.0"";"
Dim cnn As New ADODB.Connection
cnn.ConnectionString = str
cnn.Open
Dim sql As String
sql = "select * from [Sheet1$]"
Dim cmd As New ADODB.Command
cmd.CommandText = sql
cmd.ActiveConnection = cnn
Dim rst As New ADODB.Recordset
Set rst = cmd.Execute Debug.Print rst.State
Debug.Print rst.CursorType
Debug.Print rst.LockType
rst.Close
cnn.Close
End Sub
上面分别测试了Connect和Command对象的Execute方法得到Recordset,其中的CursorType和LockType属性的值见下表(抱歉再次抄袭了大师的表):
CursorType参数值
|
||
参数
|
值
|
说明
|
AdOpenForwardOnly | 0 | 向前指针,默认值。只能用MoveNext方法或GetRows方法向前单向移动指针,所耗系统资源最少,执行速度也最快,但很多属性和方法将不能用 |
AdOpenKeyset | 1 | 键集指针,记录集中可以前后移动。某一用户修改数据后,其他用户可以立即显示,但禁止查看其他用户添加和删除的记录 |
AdOpenDynamic | 2 | 动态指针,记录集中可以前后移动。所有修改会立即在其他客户端显示,功能强大,但所耗系统资源也多 |
AdOpenStatic | 3 | 静态指针,记录集中可以前后移动。所有修改不会在其他客户端显示 |
表6-18 LockType参数值
|
||
参数
|
值
|
说明
|
AdLockReadOnly | 1 | 只读,默认值,适用于仅浏览数据 |
AdLockPessimistic | 2 | 只能同时被一个用户所修改,修改时锁定,完毕解锁 |
AdLockOptimistic | 3 | 可以同时被多个用户所修改,直到用update方法更新记录才锁定 |
AdLockBatchOptimistic | 4 | 数据可以被修改,且不锁定其他用户,指定数据成批更新 |
测试结论:Connect和Command对象的Execute方法,得到的RecordSet记录集的属性是AdOpenForwardOnly(仅向前)、AdLockReadOnly(只读)。
2、Recordset对象:如果有在记录集的基础上修改数据的需求时,就要使用RecordSet对象的方法来实现:
Sub AdoRst()
Dim cnn As New ADODB.Connection
cnn.Provider = "Microsoft.ACE.OLEDB.12.0"
cnn.ConnectionString = "Data Source=C:\Users\stone\Desktop\ado.xlsm;Extended Properties=""Excel 12.0"";"
cnn.Open
Dim sql As String
sql = "select * from [Sheet1$]"
Dim rst As New ADODB.Recordset
'使用rst的Open方法取得记录
rst.Open sql, cnn, adOpenStatic, adLockPessimistic
'输出记录集的内容
PrintRecordset rst
'游标移动到第一条记录
rst.MoveFirst
'执行记录集的修改方法,修改当前游标位置的记录(现在是修改第一条记录)
rst.Update "姓名", "王麻子"
rst.Update "年龄", ""
' '上面的Update方法也可以使用下面的方式来替代
' rst(0).Value = "张三"
' rst(1).Value = 66
' rst.Update
Debug.Print "华丽的分割线-----------------"
'重新输出修改后的记录
PrintRecordset rst
rst.Close
cnn.Close
End Sub '输出记录集的内容
Function PrintRecordset(rst As ADODB.Recordset)
'定义记录集字段类型
Dim fd As ADODB.Field
Dim s As String
'输出记录集的字段名,本例中只有两个字段分别是:姓名、年龄
Debug.Print rst.Fields().Name & " " & rst.Fields().Name
Do
s = ""
For Each fd In rst.Fields
'当前游标位置,对应的字段的值
s = s & fd.Value & " "
Next
Debug.Print s
'游标向前移动一次
rst.MoveNext
'当游标已经到了记录集的末尾时停止
Loop Until rst.EOF
End Function Function PrintRecordset2(rst As ADODB.Recordset)
Dim fd As ADODB.Field
Dim s As String
Debug.Print rst().Name & " " & rst().Name
s = ""
Do
s = rst() & " " & rst()
Debug.Print s
rst.MoveNext
Loop Until rst.EOF
End Function
输出结果的内容:(可以看到第一条记录已经修改,并且update方法的作用会使修改结果立即更新到数据库中)
姓名 年龄
张三 32
李四 20
华丽的分割线-----------------
姓名 年龄
王麻子 88
李四 20
RecordSet对象非常强大,提供了对记录集操作的许多方法,比如添加AddNew、删除Delete、更新Update等:
注释:并非所有的提供者(providers)支持 Recordset 对象的所有方法和属性。
表6-23 Recordset记录集对象的方法
|
|
方法
|
说明
|
Open | 打开记录集 |
Close | 关闭记录集 |
Requery | 重新打开记录集 |
Move | 指针移至指定记录 |
MoveFirst | 指针移至第一条记录 |
MoveLast | 指针移至最后一条记录 |
MovePrevious | 指针移至上一条记录 |
MoveNext | 指针移至下一条记录 |
Find | 搜索一个 Recordset 中满足指定某个条件的一条记录 |
AddNew | 添加记录 |
Delete | 删除记录 |
Update | 更新记录 |
CancelUpdate | 取消更新 |
UpdateBatch | 把所有 Recordset 中的更改存入数据库。请在批更新模式中使用 |
GetRows | 从记录集得到多行记录 |
GetString | 将 Recordset 作为字符串返回 |
Resync | 与数据库服务器同步更新 |
Save | 把 Recordset 对象保存到 file 或 Stream 对象中 |
GetRows方法:Function GetRows([Rows As Long = -1], [Start], [Fields])
第一参数用于设置要返回多少条记录,默认为-1,也就是全部记录。把多条记录从一个 Recordset 对象中拷贝到一个二维数组中,第一维表示列,第二维表示行。该方法得到的数据是行列倒置的。
rst.MoveFirst
Dim arr
arr = rst.GetRows
AddNew方法:总是在记录集的最后面添加一条记录
'第一种方式
'添加新记录到记录集,并直接更新到数据源
rst.AddNew Array("姓名", "年龄"), Array("王二", ) '第二种方式
'添加记录
rst.AddNew
rst("姓名") = "张飞"
rst("年龄") =
'将添加的新记录,更新到数据库
rst.Update
Delete方法:Excel表中数据似乎不能使用ADO方式删除数据
Save方法:
rst.MoveFirst
rst.Save "C:\Users\stone\Desktop\ado.xml", adPersistXML
如果把记录集一次性写入单元格,可使用单元格Range对象的CopyFromRecordset方法,例如:
rst.MoveFirst
ActiveCell.CopyFromRecordset rst
最后总结一下Connection、Command、RecordSet三个重要对象的使用情景:
0、三个对象是结合在一起使用的
1、对数据源做一次性的简单更新操作(update、delete、insert)时,可选择使用[Connection||Command].Execute,不需要Recordset
2、读取(Select)但不更新原数据,使用 Set RecordsetObj = [Connection||Command].Execute,此时记录集是仅向前的、只读的。
3、在第1-2的情景中,如果在Sql命令中加入参数化形式(避免sql注入漏洞),要使用“Command+参数化的SQL”。Connection单干不行。
4、对数据源做复杂的更新操作时,“[Connection&command]+SQL脚本”不能胜任,把数据取出来放到Recordset里,借用记录集对象的一套丰富的方法,先更改记录集再把更新同步至数据源显然非常的灵活方便。
关于连接自符串:
连接字符串是很难去记住的一项内容,但如果字符串写不对,就好像有豪车没有钥匙,白瞎了。可以使用Excel程序自带的功能来助记。
1、使用“数据选项卡”-->“现有连接”(Alt+A+X)-->“浏览更多”-->找到要连接的文件类型,比如*.xlsm
注:如果选择连接的文件是access文件,也可以得到与之对应的连接字符串。
2、在打开要连接文件的“连接属性中”,可以找到需要的连接信息(不用愁Provider、Extended Properties的拼写了):
3、想要ADO连接excel文件,复制上面的文本,改一下:Extended Properties="Excel 8.0"(Excel2003)或"Excel 12.0"(Excel2007以后) ,8.0、12.0两个数字而已,就比较好记了。
VBA中练习ADO:ActiveX Data Object的更多相关文章
- VC++中使用ADO方式操作ACCESS数据库
ADO(ActiveX Data Object)是Microsoft数据库应用程序开发的新接口,是建立在OLE DB之上的高层数据库访问技术,即使你对OLE DB,COM不了解也能轻松对付ADO,因为 ...
- Using ADO.NET Data Service
ADO.NET Data Service是随同Visual Studio 2008 SP1提供的用于构建在数据对象模型 (如EF-DEMX, LINQ-DBML) 之时来快速提供企业网内外的轻量级数据 ...
- Java中对不变的 data和object reference 使用 final
Java中对不变的 data和object reference 使用 final 许多语言都提供常量数据的概念,用来表示那些既不会改变也不能改变的数据,java关键词final用来表示常量数据.例如: ...
- 在Excel VBA中写SQL,是一种什么体验
每每提到Excel办公自动化,我们脑海里能想到的就是公式.数据透视表.宏.VBA,这也是我们大部分人数据分析的进阶之路.当我们对于常用VBA技巧已经相当熟练后,往往会有一种"我的VBA知识够 ...
- Visual C++中的ADO编程
摘 要:本文介绍了微软推出的以ActiveX技术为基础的ADO数据存取技术,分析了ADO的工作原理,并用Visual C++说明了ADO数据访问技术的实现方法. 关键字:ADO:连接对象:OLE D ...
- 使用Spring.net中对Ado.net的抽象封装来访问数据库
使用Spring.net中对Ado.net的抽象封装来访问数据库 Spring.NET是一个应用程序框架,其目的是协助开发人员创建企业级的.NET应用程序.它提供了很多方面的功能,比如依赖注入 ...
- Spring.NET 中的 ADO.NET 数据访问的示例
Spring.NET 1.3.1 中提供了一个使用 AdoTemplate 的完整示例,包括使用泛型和使用非泛型技术进行数据访问,这个示例位于下载的压缩包中\Spring.NET-1.3.1\Spri ...
- ADO.NET Data Service
关于ADO.NET Entity Framework部分的内容见ADO.NET Entity Framework(1-4) http://www.cnblogs.com/foundation/arch ...
- 一步一步学Silverlight 2系列(17):数据与通信之ADO.NET Data Services
概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...
随机推荐
- 使用putty组件向服务器上传或下载文件
基于SSH的连接 上传文件: pscp -P 28661(portNum) -pw password sourceFilePath user@serverIP:destinationFilePath ...
- LaTex 基础
一.文档 \documentclass{article} %book, report, letter 二.宏包 \usepackage{amsmath} 三.正文 \begin{document} \ ...
- yii1 render方法解析(记录下)
先判断主题(themes)中是否有相对应的文件,如果没有变换file为protected/views路径下的文件,如果有文件则变换为themes路径下的文件.然后,如果加载了viewrender模块( ...
- Maven应用
Maven进行项目管理很方便,下面介绍一下学习maven中的笔记.我是在Windows上运行的 有些知识点没有试,只是收集转载,很可能存在错误 1.安装 解压缩之后,配置环境变量MA ...
- PowerDesigner连接mysql逆向生成pdm
常用的建模工具有:PowerDesigner和ERWin,后者已快被淘汰,但前者依然活跃.相信大家都遇到过项目组已经运营很很久,但是竟然连一个ER图都没有,今天就讲解一下PowerDesigner连接 ...
- HttpServlet 详解(注!仿)
Servlet的框架是由两个Java包组成:javax.servlet和javax.servlet.http. 在javax.servlet包中定义了所有的Servlet类都必须实现或扩展的的通用接口 ...
- 用soapUI生成客户端代码
一.用soapUI生成客户端代码 方法一: 1.第一步,打开soapUI,菜单栏里的tools,选择apache CXF,如图, 2.第二步,WSDL:写上你连接服务端的地址,OutputDirect ...
- Android应用程序窗口(Activity)与WindowManagerService服务的连接过程分析
在前两文中,我们分析了Activity组件的窗口对象和视图对象的创建过程.Activity组件在其窗口对象和视图对象创建完成之后,就会请求与WindowManagerService建立一个连接,即请求 ...
- Knockout.js是什么?
从本节开始介绍关于KnockoutJs相关的内容,本节主要介绍knockoutjs一些重要特性与优点,以及它与Jquery等框架库之间的区别. 1.Knockout.js是什么? Knockout是一 ...
- 关于IPv6被拒
关于IPv6被拒 App在本地IPv6的测试环境下运行一切正常,结果又是被拒,悲剧原因还是IPv6的问题;求解决方法被拒原因We discovered one or more bugs i ...