Excel—数据驱动必备利器
注意:更多信息可以查询EXCEL的VBA或Visual Base For Aplication如何使用
如果遇到QTP读取DataTable不能满足基本需求,需要使用Excel来解决问题时
● 通过编写Excel Macros把数据表的格式转化为QTP中DataTable的格式。
● 直接抛弃DataTable功能,使用EOM来对数据表进行操控。
查看EOM[Excel ObjectModel]封装对象库的方法和属性
1、 使用VBSEdit创建Excel自动化模型对象
‘创建Excel自动化模型对象 Set excelApp = CreateObject("excel.application") |
就可以在VBSedit的Object Browser视图中自动添加相对应的Excel对象的方法和属性
2、 使用Excel自带的VB编辑器(宏编辑器)查看
在Excel表中按下快捷方式【Alt+F11】
注意:相关的对象库的使用可以参考MSDN的说明
进入VB宏编辑器后,选中需要进行宏定义的表,后输入快捷键F2,出现右图示
BOOK和Sheet的区别
l Book是Excel的一个最大的模块单元,具体点就是一个Excel的文件,也就是一个Xls文件
l Sheet是Book下的一个分类子模块,在每个Book下默认都会有3个Sheet,用户可以自动进行添加与删除。
l Excel Book和Word Book区别在于Excel打开后主窗口会自动绑定所有的BOOK子窗口,关闭的时候也是一起关闭
WordBook的操作
1、 新增WordBook
'创建Excel自动化模型对象 Set excelApp = CreateObject("excel.application") '设置为可见模式 excelApp.Visible = true ’上面基础步骤,下面示例只是为了方便略去却是必须的 '新增WorkBook excelapp.Workbooks.Add '保存 excelApp.Save "d:\1.xls" '关闭Excel excelApp.Quit '释放Excel对象 Set excelApp = nothing |
2、 打开WorkBook
'打开WorkBook excelapp.Workbooks.Open "d:\1.xls" |
提示:执行结果就是直接打开了D盘中的1.xls文件,前提是文件必须存在,如果文件不存在,则会出错。因此,可以在代码中利用fso进行事先的文件是否存在的判断。
3、 获取WorkBook的数量
'打开WorkBook excelapp.Workbooks.Open "d:\1.xls" '获取WorkBook的数量 MsgBox excelapp.Workbooks.Count |
WorkSheet操作
1、 新增Sheet
'创建Excel自动化模型对象 Set excelApp = CreateObject("excel.application") '设置为可见模式 excelApp.Visible = true '打开WorkBook excelapp.Workbooks.Open "d:\1.xls" '为1.xls新增一个Sheet Set oSheet = excelapp.Sheets.Add '重命名Sheet为"helloworld" oSheet.name = "helloworld" '释放Excel对象 Set excelApp = nothing |
提示:先打开Book或创建Book,然后才可以创建Sheet
2、 获取Sheet对象并操作单元格
'获取1.xls中一个Sheet对象 Set oSheet = excelapp.Sheets.Item(1) '重命名Sheet为"helloworld" oSheet.name = "helloworld" '为第一行第一列单元格赋值"QuickTest" oSheet.cells(1,1) = "QuickTest" '保存当前WorkBook excelApp.ActiveWorkbook.Save '释放Excel对象 Set excelApp = nothing |
提示:excelapp.Sheets.Item(1)是为了获取到Sheet1对象的引用
动态加载宏代码
静态加载:在Excel提供的VB编辑器进行编辑代码,然后通过QTP来进行调用
静态调用方法:
1、 假如已经在sheet1宏代码编辑器中编辑了函数tt
2、 调用方法如下所示:定位到
'创建EOM对象 Set eom = CreateObject("excel.application") '打开D盘中的1.xls eom.Workbooks.Open("d:\1.xls") '获取到Sheet1对象 Set sheet1 = eom.Sheets.Item(1)
'****执行Sheet1下的tt方法***** Sheet1.tt ‘****************************** '关闭当前工作簿 eom.ActiveWorkbook.Close '退出Excel应用 eom.Quit '释放 Set eom = Nothing |
调用流程:创建EOM对象,获取到Sheet1对象后,并调用Sheet1对象下的tt方法,关闭工作簿后退出应用
先修知识:VBProject常用代码操作
一、增加模块
1.增加一个模块,命名为“我的模块”
ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_StdModule).Name ="我的模块"
系统常量vbext_ct_StdModule=1
2.增加一个类模块,命名为“我的类”
ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_ClassModule).Name ="我的类"
vbext_ct_ClassModule=2
3.增加一个窗体,命名为“我的窗体”
ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm).Name = "我的窗体"
vbext_ct_MSForm=3
二、删除模块【Remove】 :类、模块、窗体同理
1.删除“模块1”
ThisWorkbook.VBProject.VBComponents.RemoveThisWorkbook.VBProject.VBComponents("模块1")
三、增加代码
1.在“模块1”中插入代码
如果需要在“Sheet1”、“Thisworkbook”、或“Userform1”中操作,用只需将下面的“模块1”换成相应的名称即可。
方法1:
在模块的开始增加代码,增加的代码放在公共声明option,全局变量等后面。
Sub AddCode1()
ThisWorkbook.VBProject.VBComponents("模块1").CodeModule.AddFromString _
"subaTest()" & Chr(10) & _
"msgbox""Hello""" & Chr(10) & _
"endsub"
End Sub
方法2:
在模块指定行处增加代码,原代码后移。增加代码不理会和判断插入处代码的内容。当指定行大于最后一行行号时,在最后一行的后面插入。
Sub AddCode2()
WithThisWorkbook.VBProject.VBComponents("模块1").CodeModule
.InsertLines 1, "sub aTest()"
.InsertLines 2, "msgbox ""Hello"""
.InsertLines 3, "end sub"
EndWith
End Sub
相关语句:
(1)“模块1”中代码总行数:
ThisWorkbook.VBProject.VBComponents("模块1").CodeModule.CountOfLines
(2)“模块1”中代码公共声明部分的行数:
ThisWorkbook.VBProject.VBComponents("模块1").CodeModule.CountOfDeclarationLines
(3)显示“模块1”中第1行起的3行代码内容:
Sub ShowCodes()
Dims$
s =ThisWorkbook.VBProject.VBComponents("模块1").CodeModule.Lines(1, 3)
Debug.Prints
End Sub
2.建立事件过程
建立事件过程除了使用上面的代码如下面的AddEventsCode1外,还可以使用CreateEventProc方法,如AddEventsCode2所示。
一般方法:
Sub AddEventsCode1()
ThisWorkbook.VBProject.VBComponents("ThisWorkbook").CodeModule.AddFromString_
"Private Sub Workbook_Open()" & Chr(13) & _
"MsgBox ""Hello""" & Chr(13) & _
"End Sub"
End Sub
CreateEventProc方法:
Sub AddEventsCode2()
Dimi%
WithThisWorkbook.VBProject.VBComponents("Sheet1").CodeModule
i =.CreateEventProc("SelectionChange", "Worksheet") + 1
.InsertLines i, "Msgbox ""Hello"""
EndWith
End Sub
上面CreateEventProc的两个参数建立的事件过程为Worksheet_SelectionChange,分别是下划线两边的内容。
四、删除代码
1.删除Sheet1中第2行起的三行代码: 如果只删除1行代码,第二个参数可省略。
Sub DelCodes()
ThisWorkbook.VBProject.VBComponents("Sheet1").CodeModule.DeleteLines2, 3
End Sub
2.删除“模块1”的所有代码:
Sub DelCodes()
WithThisWorkbook.VBProject.VBComponents("模块1").CodeModule
.DeleteLines 1, .CountOfLines
EndWith
End Sub
3.删除过程aTest:
Sub DelCodes()
WithThisWorkbook.VBProject.VBComponents("模块1").CodeModule
.DeleteLines .ProcBodyLine("aTest", 0),.ProcCountLines("aTest", 0)
EndWith
End Sub
4.将“模块1”的第5行代码替换为“x=3”
ThisWorkbook.VBProject.VBComponents("模块1").CodeModule.ReplaceLine 5,"x=3"
五、引用项目
1.增加引用
ThisWorkbook.VBProject.References.AddFromFile"C:\Windows\System32\asctrls.ocx"
2.取消引用
ThisWorkbook.VBProject.References.RemoveThisWorkbook.VBProject.References("ASControls")
这里ASControls是引用的名字,即后面的rf.Name。
3.显示当前所有引用
Sub ShowRefs()
Dimrf As VBIDE.Reference
ForEach rf In ThisWorkbook.VBProject.References
Debug.Print rf.Name, rf.FullPath
Next
End Sub
六、信任及密码
上面所有操作都基于这样的前题:
(1)EXCEL已设置: 工具(T)-宏(M)-安全性(M)-可靠发行商(T)-勾选了“信任对于VB项目的访问(V)”
(2)工程没有设置密码
如果不能满足它们中的任何一个,代码运行就会出错。因为微软不希望我们对VBProject进行操作。幸运的是,借助于SendKeys这道后门我们仍可以完成我们所要做的事。
下面给出绕开这两道门的示意代码,如果你要运行它们,请记得切回EXCEL主界面,而不是在VBE中直接运行。
1.信任对于VB项目的访问
Sub SetAllowableVbe()
OnError Resume Next
DimChgset As Boolean
'陷阱测试,VBProject.Protection在这儿并无实际的意义
Debug.Print ThisWorkbook.VBProject.Protection
IfErr.Number = 1004 Then
Err.Clear
Application.SendKeys "%TMS%T%V{ENTER}"
Chgset = True
DoEvents
EndIf
EndIf
End If
'要执行的操作....
'.....
'操作完成后还原操作前的状态
If Chgset Then Application.SendKeys"%TMS%T%V{ENTER}"
EndSub
2.操作密码工程
SubAllowPass()
Dim pw$
pw = "Password"
If ThisWorkbook.VBProject.Protection =vbext_pp_locked Then
Application.VBE.CommandBars(1).Controls("工具(T)").Controls("VBAProject属性(&E)...").Execute
Application.SendKeys pw &"{ENTER}{ENTER}"
DoEvents
End If
'要执行的操作….
'.....
EndSub
Protection属性返回工程的受保护状态,vbext_pp_locked(1)为受保护,vbext_pp_none(0)表示没有保护。
动态调用方法:
1、 字符串加载方式(只显示核心部分,其余按照前面)
'进入到宏编辑区并获取到WorkBook的脚本模块对象 Set oModule = oWorkbook.VBProject.VBComponents.Item("ThisWorkbook") '定义动态脚本 Dim newCode '所有脚本内容 newCode = "Function tt()" +vbNewLine newCode = newCode + "msgbox ""test"""+ vbNewLine newCode = newCode + "End Function"+ vbNewLine '加载脚本 oModule.CodeModule.AddFromString newCode '执行脚本 oWorkbook.tt '关闭WorkBook,此处false代表不保存直接关闭 oWorkbook.Close false |
注意:创建EOM对象,添加一个WorkBook,获取到VBProject下的VBComponents中WorkBook的编辑区对象,并使用codeModule对象添加需要的代码,接着就可以直接执行方法函数,最后关闭WorkBook。
2、 文本文件加载方式
'进入到宏编辑区并获取到WorkBook的脚本模块对象 Set oModule = oWorkbook.VBProject.VBComponents.Item("ThisWorkbook") ' 直接动态导入函数库文件 oModule.CodeModule.AddFromFile "d:\1.bas" '执行脚本 oWorkbook.tt '关闭WorkBook,此处false代表不保存直接关闭 oWorkbook.Close false |
注意:首先需要创建一个BAS文件,此格式为Excel导出的宏文件格式。在这个BAS文件中加入需要的一些函数。此处就把前面的tt函数加入到BAS中,并且保存到D盘中,在真实项目中,建议使用相对路径,这样方便以后的移植。
Excel信用机制调整
Excel考虑到安全性的问题,默认是限制用户使用脚本直接访问VBProject程序,直接调用外部代码会报错
解决方法一:手工设置
当打开Excel后,依次进入工具→宏→安全性,选择“可靠发行商”选项卡后,看到“信任对于‘Visual Basic项目’的访问”,默认状态下Excel是不会对其进行信任的,把此选项选上。即可做到对VBProject信任状态了
解决办法二:利用WSH对象
'创建WSH对象 Set oWshShell = CreateObject("wscript.shell") '创建EOM对象 Set eom = CreateObject("excel.application") '写入注册表,设置对VBProject进行信任 oWshShell.RegWrite "HKLM\SOFTWARE\Microsoft\Office\11.0\Excel\Security\AccessVBOM" , 1, "REG_DWORD" ‘******************************************************** ‘ 测试主要脚本编写区 ‘********************************************************* '删除注册表 oWshShell.RegDelete "HKLM\SOFTWARE\Microsoft\Office\11.0\Excel\Security\AccessVBOM" '释放对象 Set oWshShell = Nothing Set eom = Nothing |
利用ADO打造Excel数据库
原理:使用基本的数据库连接方式即可
注意点:
SQL语句中如果需要描述表名,需要在后面添加一个“$”符号才能识别【select * from [Sheet1$]】
至于数据库链接字符串的获得使用前面提到的两种方法即可
'定义SQL连接字符串 sqlConnection = "DSN=Excel Files;DBQ=D:\1.xls;" '定义SQL语句 sqlCommand = "select * from [Sheet1$]" '创建ADO对象 Set oExcel = CreateObject("adodb.connection") '打开数据连接 oExcel.Open sqlConnection '执行SQL语句并获得查询结果集 Set oRst = oExcel.Execute(sqlCommand) '获取username字段名对应的字段值 MsgBox oRst.Fields("username") '关闭数据库 oExcel.Close '释放资源 Set oRst = Nothing Set oExcel = Nothing |
如果觉得QTP提供的DataTable扩展性不好的话,可以利用ADO和Excel创建Dictionary扩展QTP性能