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, ...
随机推荐
- JQuery-属性
// attr能访问到的都是html里面的样式,诸如内联样式.外部样式和外联样式该方法访问不到 $('#div1').width('400px') // 这个用来改样式css $("#div ...
- 在block中使用self
__weak typeof(self) weakSelf = self; [self doABlockOperation:^{ __strong typeof(weakSelf) strong ...
- 在Ubuntu Trusty 14.04 (LTS) (64-bit)安装Docker
Ubuntu Trusty带来的是3.13.0 Linux kernel ,需要准备所有ubuntu库的某些条件,docker安装包被称之为docker.io.(注:Ubuntu (和Debian)包 ...
- distribution数据库过大问题
从事件探查器中监控到如下语句执行时间查过 1分钟: EXEC dbo .sp_MSdistribution_cleanup @min_distretention = 0, @max_distreten ...
- fiddler note
一晚上终于找到对的东西,作者很专业,这里作为笔记,想学习好东西还是到作者那里^_^ ---------------------------------------------------------- ...
- haproxy log config
Step 4: Configuring logging Edit /etc/sysconfig/syslog SYSLOGD_OPTIONS=”-m 0 -r” ————————————————— ...
- C#扩展特性
今天跟同事讨论技术,无意发现的C#3.0的一个新特性,高手可以直接忽略. 这个特性叫扩展,我觉得非常的方便所以就记录下来了.以下是我的测试代码: public static class test { ...
- 非空二叉树的一个有趣的性质:n0 = n2 + 1
对任何非空二叉树T,若n0 表示叶结点的个数.n2 表示度为2 的非叶结点的个数,那么两者满足关系n0 = n2 + 1. 这个性质很有意思,下面我们来证明它. 证明:首先,假设该二叉树有N 个节点, ...
- box-flex不均分问题
解决box-flex不均等分的问题 我想当你上手css3的时候后一定为他的强大而感到震惊,但是震惊之后带来的一定是苦恼,因为他太TM变态了! 我之所以这么说是因为我今天写box-flex的时候遇到了一 ...
- C#使用二叉树算法设计一个无限分级的树表
效果图: 数据库: 操作树的示意图: 控制器代码: using Dw.Business; using Dw.Entity; using Dw.Utilities; using System; usin ...