Vba+access+Excel编程

学习目的是建立简易的管理系统

当前学习路线:excel的宏的简单了解→access数据库的了解→两者的结合

excel的宏的简单了解:

关于宏的使用,大部分文章都提到说Vba很难写,但是可以通过一段现成的代码,修改关键部分来为自己所用,现成代码的获得方式就是录制宏,在其自动生成的代码上添加循环等修改,达到自己想要的效果。

关于宏的录制与代码的修改运行如下:

1.首先要在excel中找到开发工具(WPS也有,但当前使用的是office的)

在excel的“文件”→“选项”→“自定义功能区”的“主选项卡”部分,把“开发工具”一项勾选上,点击右下角的确定,这样excel的操作栏就会显示开发工具选项卡了

 接下来举例实现功能:录制宏操作,对A1:A10单元格添加批注,批注内容是“你好”

首先,在开发工具中点击录制宏

接下来做正常的批注操作,批注好之后点击停止录制

然后点击Visual Basic 会弹窗出来如图所示的界面

 首先要在左侧的工程界面找到我们需要操作的对象,是example.xlsx的模块,打开后才会显示右侧的代码部分,宏2是录制下来的“本体”生成的代码,把它修改为宏1的形式就完成了从A列的1到10都批注“你好”的功能

这里有一个小知识点:

Cstr()函数可以将数字转换成字符,如 2 → “2”

Val()函数可以将字符(数字字符)转换成数字, 如 “2” → 2

代码写好之后,运行即可(注意!!!如果录制的宏是对A1批注,代码中的循环操作又包括了对A1的操作的话,会报错的,需要先把原A1的批注删除掉,即不能对已经存在的操作重复操作)

access数据库的建立

首先可以在目标文件夹新建一个.accdb格式的数据库文档

数据库的数据来源可以手动添加,也可以根据excel导入(推荐),即可建立一个数据库可供使用

如下图所示

两者的结合

首先明确一下目标:是为了通过对宏的编写和调用,实现excel和access连接,通过一些sql语句,将目标数据从数据库中提取到excel中

在Visual Basic新建一个新的模块,即新建了一个宏,然后要现尝试着把excel和access连接起来,在Visual Basic for Applications的窗口中找到 “工具” → “引用”

如图所示

在可使用的引用中找到“Microsoft ActiveX Data Objects”(简称ADO)可能有很多版本,选择最高的版本即可,勾选然后点击确定

接下来就是代码的实现了,代码部分如下

 1 Sub ConnectDBtest()
 2 '第一步,告诉电脑需要使用ADO工具,在工具→引用中找到ADO确认引用
 3 
 4 '第二步,创建连接对象
 5 '2-1,给连接对象取名字
 6 Dim con As ADODB.Connection    '声明对象变量
 7 '2-2,创建对象变量并赋值
 8 Set con = New ADODB.Connection   '创建对象变量
 9 
10 '第三步,建立数据库的连接
11 con.Open "provider=microsoft.ace.oledb.12.0;data source=" & ThisWorkbook.Path & "example.accdb"
12 
13 
14 MsgBox "连接成功"
15 
16 
17 End Sub

第一行是给这部分代码命名

第六行是声明对象变量的类型 Dim ...As ...

第八行是正式创建这个变量

第十一行是建立对象与数据库的连接,其中要注意两点,第一是数据驱动引擎即provider的版本,第二是所连接的数据库的位置

   1.版本: 可以根据数据库文件的后缀名进行简单的判断,03版的后缀名是.mdb,07版以上用的是accdb,对应使用的provider就是12.0的

   2.数据库的位置:本地的数据库可以照上方第十一行的写法,ThisWorkbook.Path,如果是其他位置的数据库,可以按照如下所示的方法,把数据库位置设置为变量

1 '第三步,建立数据库的连接
2 Dim mydblocation As String
3 mydblocation = "数据库位置"
4 con.Open "provider=microsoft.ace.oledb.12.0;data source=" & mydblocation & "example.accdb"
5 MsgBox "连接成功"

以上是确保了数据库与excel的连接,连接成功后会出现弹窗提示 “连接成功”【判断连接成功还有一个方法是通过查看本地是否出现了example.laccdb这样的一个文件,出现则表明数据库已经被打开了】

接下来要实现把数据库的内容通过SQL语言来帅选出来,放入excel指定的位置,代码如下

 1 Sub ConnectDBtest()
 2 '第一步,告诉电脑需要使用ADO工具,在工具→引用中找到ADO确认引用
 3 
 4 '第二部,创建连接对象
 5 '2-1,给连接对象取名字
 6 Dim con As ADODB.Connection    '声明对象变量
 7 '2-2,创建对象变量并赋值
 8 Set con = New ADODB.Connection   '创建对象变量
 9 
10 '第三步,建立数据库的连接
11 Dim mydblocation As String
12 mydblocation = "数据库远程的位置"
13 con.Open "provider=microsoft.ace.oledb.12.0;data source=" & mydblocation & "example.accdb"
14 MsgBox "连接成功"
15 
16 '第四步,查询表中满足条件的字段,这里是列出工作表 “Summary of frame-parallel test” decoder一列下为google的行的内容
17 Sql = "select * from [Summary of frame-parallel test] where [decoder] = 'google'"
18 Dim rs As New ADODB.Recordset    '创建记录集对象
19 
20 '第五步,执行sql查询语句
21 Set rs = con.Execute(Sql)
22 
23 '获取字段名即col的title
24 Dim i As Integer
25 For i = 0 To rs.Fields.Count - 1
26     Cells(1, i + 1) = rs.Fields(i).Name
27 Next
28 
29 
30 Sheets("sheet1").Range("A2").CopyFromRecordset rs    '将记录集rs中的数据返回到工作表中
31 
32 
33 '清空缓存区
34 rs.Close: Set rs = Nothing
35 con.Close: Set con = Nothing
36 
37 
38 End Sub

第十七行是定义了数据库查询的内容

第十八行和21行是定义了装载查询后结果的容器为rs,即记录集,21行是执行,执行后结果都放在rs中

第24~27行是遍历获取数据库的列的title并写进excel的第一行

第30行是复制了数据集rs中的内容到excel工作薄中,名为“sheet1”的工作表,且从A2开始写

第34~35行是清空rs记录集和对象的缓存

其中第21行生成记录集的方法:

1.第21行的方法可以称之为“使用connection对象的Execute方法产生记录集”,这种方法产生的记录集特点:一.rs是只读的,不能修改记录,通常用于做一些不需要返回的操作。二.不能获取记录的条数

2.还有一种方法较叫“使用recordset对象的open方法”产生记录集,这种方法获得的记录集是可读可写的,可以修改记录,语句是

$  rs.Open sql,con,adOpenKeyset,adLockOptimistic

其中Open后面跟的四个参数,第一个sql表示所执行的命令字符串(因为此例中第17行已经定义了查询语句为sql),第二个参数写的是当前连接的哪一个数据库,这里是连接了con数据库,第三个参数选游标的运动方式,选动态的(其实这里选固定的adOpenKeyset即可包括后面第四个参数也是一样)

这种方式可以获取到符合条件的记录的条数,便于做判断,使表格使用更方便(如果无记录,使用if语句判断一下,弹窗提示即可,无需再生成一个空表格)

如下代码所示,实现的是如果没有查找到记录,会弹窗提示无记录而不是报错

 1 Sub ConnectDBtest()
 2 '第一步,告诉电脑需要使用ADO工具,在工具→引用中找到ADO确认引用
 3 
 4 '第二部,创建连接对象
 5 '2-1,给连接对象取名字
 6 Dim con As ADODB.Connection    '声明对象变量
 7 '2-2,创建对象变量并赋值
 8 Set con = New ADODB.Connection   '创建对象变量
 9 
10 '第三步,建立数据库的连接
11 Dim mydblocation As String
12 mydblocation = "数据库位置"
13 con.Open "provider=microsoft.ace.oledb.12.0;data source=" & mydblocation & "example.accdb"
14 MsgBox "连接成功"
15 
16 '第四步,查询表中满足条件的字段
17 Sql = "select * from [Summary of frame-parallel test] where [decoder] = 'ci'"
18 
19 Dim rs As New ADODB.Recordset    '创建记录集对象方式1
20 
21 '第五步,执行sql查询语句
22 rs.Open Sql, con, adOpenKeyset, adLockOptimistic
23 
24 If rs.RecordCount <= 0 Then      '表示没有满足条件的记录
25     MsgBox "没有满足条件的记录"
26 Else
27     '获取字段名即col的title
28     Dim i As Integer
29     For i = 0 To rs.Fields.Count - 1
30         Cells(1, i + 1) = rs.Fields(i).Name
31     Next
32     
33     
34     Sheets("sheet1").Range("A2").CopyFromRecordset rs    '将记录集rs中的数据返回到工作表中
35 End If
36 
37 '清空缓存区
38 rs.Close: Set rs = Nothing
39 con.Close: Set con = Nothing
40 
41 
42 End Sub

如果用connection对象的Execute方法产生记录集,也可以实现判空的功能,代码如下

 1 Sub ConnectDBtest()
 2 '第一步,告诉电脑需要使用ADO工具,在工具→引用中找到ADO确认引用
 3 
 4 '第二部,创建连接对象
 5 '2-1,给连接对象取名字
 6 Dim con As ADODB.Connection    '声明对象变量
 7 '2-2,创建对象变量并赋值
 8 Set con = New ADODB.Connection   '创建对象变量
 9 
10 '第三步,建立数据库的连接
11 Dim mydblocation As String
12 mydblocation = "数据库位置"
13 con.Open "provider=microsoft.ace.oledb.12.0;data source=" & mydblocation & "example.accdb"
14 MsgBox "连接成功"
15 
16 '第四步,查询表中满足条件的字段
17 Sql = "select * from [Summary of frame-parallel test] where [decoder] = 'ci'"
18 
19 Dim rs As New ADODB.Recordset    '创建记录集对象方式1
20 Set rs = con.Execute(Sql)
21 
22 'EOF表示记录的结尾,BOF表示记录的开头
23 If rs.EOF And rs.BOF Then       '指针既指向开头又指向末尾,说明没有记录
24 
25 '第五步,执行sql查询语句
26 'rs.Open Sql, con, adOpenKeyset, adLockOptimistic
27 'If rs.RecordCount <= 0 Then      '表示没有满足条件的记录
28     MsgBox "没有满足条件的记录"
29 Else
30     '获取字段名即col的title
31     Dim i As Integer
32     For i = 0 To rs.Fields.Count - 1
33         Cells(1, i + 1) = rs.Fields(i).Name
34     Next
35     
36     
37     Sheets("sheet1").Range("A2").CopyFromRecordset rs    '将记录集rs中的数据返回到工作表中
38 End If
39 
40 '清空缓存区
41 rs.Close: Set rs = Nothing
42 con.Close: Set con = Nothing
43 
44 
45 End Sub

 窗体的设置

excel要结合窗体才能实现更便捷的功能,设置方法如下:

首先在excel的Visual Basic中找到对应工程,点击菜单栏中的插入→用户窗体

 接下来会出现如图所示的界面

 窗体调出来之后,是需要有个模块来专门编辑窗体信息的,在此再点击插入→模块,创建一个新的模块

1 '定义一个函数名为OpenMenuWindow来打来窗体
2 Sub OpenMenuWindow()
3 
4 '窗体名称.show可以调出目标窗体
5 UserForm1.Show
6 
7 End Sub

运行这个函数就可以打开窗体了

窗体的外形和内容设计的方法是:在窗体的编辑页面下,右键点击窗体,再点击查看代码会出现如图所示的界面

 意思是当前的窗体UserForm是单击事件,我们需要把它改掉,进行初始化的设置

可以先点进去UserForm1的界面,在工具箱的控件中选择“框架”,画出一个框架如图所示

 然后点击“列表框”,在框架中画出一个列表框

 在UserForm1的空白处点击一下,可以预览到大致的效果如图

 我们要对这个框架和列表框的名称进行修改,便于后续的调用操作,于是可以先选中列表框,在左侧的属性栏中,修改“名称”为“Listphone”,再选中框架,修改名称为“selectphone”,再把“caption”修改为“选择手机型号”,这样完成的效果为

 右键点击这个userform1,查看代码,可以把里面的东西都清除干净,然后,选择这个userform1的类型为initialize,补充函数如下

 1 Option Explicit
 2 Dim con As ADODB.Connection
 3 Dim rs As Recordset
 4 
 5 '当窗体加载时显示Android Phone这个列表框的内容
 6 Private Sub UserForm_initialize()
 7 
 8 Set con = New ADODB.Connection
 9 Set rs = New ADODB.Recordset
10 '建立数据库的连接
11 Dim mydblocation As String
12 mydblocation = "数据库地址"
13 con.Open "provider=microsoft.ace.oledb.12.0;data source=" & mydblocation & "example.accdb"
14 MsgBox "连接成功"
15 
16 '提取不重复的手机类型
17 Dim sql1 As String           '定义命令字符串变量
18 sql1 = "select distinct [Android Phone] from [Summary of frame-parallel test]"
19 rs.Open sql1, con, adOpenKeyset, adLockOptimistic
20 
21 Dim i As Integer
22 With Listphone
23     .Clear
24     For i = 1 To rs.RecordCount
25         .AddItem rs("Android Phone")
26         rs.MoveNext
27         
28     Next i
29 
30 End With
31 End Sub

函数说明:

2,3行分别是声明连接对象变量、声明记录集对象变量

第6行往下就是这函数的正式内容了

8,9行分别是创建连接对象变量,创建记录集对象变量

11~14行是建立数据库的连接

17~19行是用open方法去提取不重复的手机类型,把结果放入记录集rs中

22是用with + 模块名称,表示操作对象(23行是清除此次之前的列表框中的记录)

24行是表示开始遍历记录集中数据

25行说明了要取的rs中的数据

26行是将记录集中的指针指向下一条记录

28行是指针+1

30行,31行是结束with部分和结束函数部分

样例分析

此样例是实现了:对任意access数据库的数据表,任选三个字段名为条件进行筛选查询(目前存在的缺陷是数据中如果某字段名的列单元格为空,那么选这个字段为条件就会报错“类型不匹配”)

原文地址:https://www.cnblogs.com/RuiRuia/p/14658420.html