VBScript
QTP使用Microsoft的VBScript 作为脚本语言,关于此语言的详细描述不在此书的范围内,这一章节提供一个关于VBScript一些功能的简短的概述,这些功能都是开发QTP脚本的时经常使用的,关于完整的功能说明,请参考QTP的Online help
Sting
这一节讨论字符串处理函数
Lcase an UCase
这两个函数把一个字符串从小写转换成大写,反之亦然
'转换成小写字母
x=LCase("aBc") ' 将会把"abc"赋值给 x
'转换成大写字母
x=Ucase("aBc") ' 将会把"ABC"赋值给 x
strComp
此函数比较两个字符串,当他们相等的时候返回0
'比较字符串
x=strComp("abc","abc") '此调用返回 0
x=strComp("abc","aBc") '此调用返回非0
'如下的调用返回0,因为执行的是文本比较,不区分大小写。
x=StrComp("abc","aBc",vbTextCompare)
StrReverse
此函数将一个字符串反向
'此调用返回"yhw"
x=StrReverse("why")
Len
此字符串返回一个字符串的长度
'此调用返回3
x=Len("abc")
Left
此函数返回指定数目的从字符串的左边算起的字符。
'此调用返回"this is"
x=Left("This is a test",7)
Right
此函数返回指定数目的从字符串的右边算起的字符。
'此调用返回"test"
x=Right("This is a test",4)
Mid
此函数返回指定数目的从字符串的中间算起的字符。如果字符的数目没有指定,则会返回从指定位置到结尾的字符串。
'此调用返回"is a test"
x=Mid("This is a test",6)
'此调用返回"is",因为我们指定从第六个位置算起的两个字符
x=Mid("This is a test",6,2)
InStr
返回某子字符串在另一字符串中第一次出现的位置。从起始位置开始搜索,如果没有找到子字符串,则返回0
'此调用返回6
x=InStr("Find abc in this","abc")
'此调用返回0
x=InStr("Find abc in this","aBc")
'此调用返回6 (问题1,这句话运行时会报错,见VBscript章节中的错误.docx附件)
x=InStr("Find abc in this","aBc",vbTextCompare)
'我们还可以从字符串的指定位置开始搜索
'返回6,因为我们是从第一个字符开始搜索,这和默认情况下是一样的
x=InStr(1,"Find abc in this","abc")
'此调用返回0,因为我们从字符串的第7个字符开始搜索,这意为搜索字符串被认为是“bc in this”
x=InStr(7,"Find abc in this","abc")
问题 14-1 我们如何从字符串“page 4 of 15”中找到当前页和总页数
首先:我们在整个字符串中搜索“ of ”(前后都有空格)
'原文本
s_text="Page 4 of 15"
' 要搜索的文本
s_Search=" of "
'返回7,即" of "的开始位置
i_Index=InStr(s_text,s_Search)
下面,要搜索的字符串“ of ”是4个字符,所以为了得到总页数的值,我们读取从4+i_index后面的所有的字符,我们有两种方法去提取这部分字符-既可以使用Right函数,也可以使用Mid函数,两种方法显示如下,但是Mid 函数会产生一个更清楚的代码
'从搜索字符串的右边开始搜索文本
s_AllPages=Right(s_Text,len(s_text) - i_Index - Len(s_Search))
'我们要知道我们需要的从字符串右侧获取的字符的数量,Len(s_Text)给出字符串" of 15 "的长度,还需要减去字符串" of "的长度
s_AllPages=Mid(s_Text,i_Index+Len(s_Search))
现在当前页的数量通常出现在一个字符串的第六个位置,“ of ”字符的前面。
'我们取得“ of ”的左边的字符串,然后从字符串的第六个位置找到当前的页号
s_CurrentPAge=Mid(Left(s_Text,i_index-1),6)
问题14-2 我们如何获得“if”词语在“if + if=2if”字符串中的数量
'原文本
s_Text ="if + if =2 if"
'要搜索的文本
s_Search ="if"
'此变量常用来存储上一个被发现的索引,然后我们从此索引的下一个位置开始,找到下一个需要发现的字符的位置
i_IndexFound=0
'此变量会用来存储被发现的"if"字符串数量
i_NumCount=0
Do
i_IndexFound=InStr(i_IndexFound + 1,s_Text,s_search)
MsgBox i_IndexFound
If i_IndexFound >0 Then
i_NumCount=i_NumCount+1
Else
Exit Do
End If
'一个无限循环,由loop内的一个条件终结
loop while (True)
还有另外一种方法
'原文本
s_Text ="if + if =2 if"
'要搜索的文本
s_Search ="if"
'从s_Textz 中删除 "if"词语,注意长度的差值
i_NumCount=(Len(s_Text)-Len(replace(s_Text,s_Search,"")))/Len(s_Search)
'值为3
Msgbox i_NumCount
InStrRev
此函数用来搜索一个子字符串,但是从字符串的结尾搜索
它不会把字符串反向再搜索
'此调用返回0
x=InStrRev("abc","cba")
msgbox x
'此调用返回5
x=InStrRev("abc abc","abc")
msgbox x
如下是一个例子关于在什么时候使用InsStr好,以及什么时候使用InStrRev好,通过此例子可以清晰的看出来。
问题14-3. 给出一个完整的文件路径名,从该路径中从提出出文件名,文件路径,以及驱动器盘符
完整的文件路径名是“C:\test\Strings\Function.vbs”我们知道文件名必须显示在字符串最后一个斜杠“\”后面,盘符必须显示在第一个斜杠“\”之前
'完整的文件路径名
s_file="C:\Test\Strings\Function.vbs"
'定位第一个斜杠
i_FirstSlash=InStr(s_File,"\")
'定位最后一个斜杠
i_LastSlash=InStrRev(s_File,"\")
现在我们知道了第一个和最后一个斜杠的位置
'-1 是因为我们不需要":"出现在结果字符串中
s_DriverLetter=Left (s_File,i_FiestSlash -1)
'+1 是因为我们需要忽略"\",并且获取其右边的字符串
s_FileName=Mid(s_file,i_LastSlash +1)
'-1是因为我们需要忽略"\"字符,并且获取其左边的字符
s_FilePath=Left(s_File,,i_LastSlash -1)
LTrim,RTrim and Trim
这些函数分别是用来移除左边的、右边的、以及两边的空格
'返回 "test "
x=LTrim(" test ")
'返回 " test"
x=RTrim(" test ")
'返回 "test"
x=Trim(" test ")
Peplace
此函数用来将某子字符串替换成另一字符串
'返回"the value of 2 is 2" to x
x=Replace("the value of 1 is 2","1","2")
此函数在参数化得时候也非常有用,假设我们输入XML到系统中,并且在XML中参数化一些值,在这种情况下,我们使用Replace函数,如下:
'XML模板字符串
s_XML= "<Variable><name>%NAME%</name></Variable>"
'把参数%NAME% 替换成实际值
s_XML=Replace (s_XML,"%NAME%","Tarun")
Space
此函数用来产生指定数量的空格符
'此调用返回一个包含两个空格符的字符串
x=Space(2)
String
此函数用来产生给定的指定数量的字符
'此调用返回包含3个"A"字符的字符串
x=String(3,"A")
Arrary
此函数返回一个数组,包含字符串变量的数量
'返回一个数组,包含两个字符串
Dim x
x= Array("Tarun","Lawani")
Join
此函数用来把数组内容连接成一个字符串,每个被放入字符串的数组元素都被一个可选的指定的分隔符号分离——如果没有指定分隔符,那么会将使用空字符
'获得一个数组
x=Array("Tarun","LaLwani","wrote","this","book")
'返回"Tarun LaLwani wrote this book"
s_Text=Join(x)
'返回 "Tarun_LaLwani _wrote_this_book"
s_Text=Join(x,"_")
Split
此函数做了和jion函数相反的操作,因此,它会从输入的字符串中创建一个字符串数组。
'要被分离的文本
s_Text ="Tarun_LaLwani_wrote_this_book"
'这将会把 Array("Tarun","LaLwani","wrote","this","book") 赋值给x
x=Split(s_Text,"_")
问题14-4 让我们再次回顾一下页数提取的问题。我们如何从字符串 “page 4 of 15”中找到当前页和总页数的值呢?
对于方法,我们使用Split 函数把每个非空子字符串放入到一个单独的数组元素里边,然后我们能轻松的提取第一个和第三个数组元素,这样就能分别获得当前页数和总页数。
'页数字符串
x="Page 4 of 15"
'分离此字符串,把空格作为分隔符
'这会返回一个 Array("page","4","of","15")
pages=Split(x," ")
'返回字符串"4"
msgbox pages(1)
'返回字符串"15"
msgbox pages(3)
问题 14-5 我们如何把一个字符串分离成单词或者行呢?
VBScript 中的Split函数,允许指定一个分隔符号,如果我们想把一个字符串分离成单词或者行的话,我们需要多个分隔符。下面我们新建一个Split的扩展版本去实现这个任务。
'参数
'pText - 被分离的文本
'Delimiter - 这是一组被用来被当做分隔符的字符,在Delimiter中的每个字符会被当做一个分隔符号,而不是一个完整的字符串
'IncludeDelimiter - 如果设置为真,那么就结果数组也会包括分隔符号
'ReDelimiter -如果设置为真,那么除了指定的分隔符号的任何其他符号都会被当成是分隔符
Public Function SplitEx(ByVal pText, ByVal Delimiter ,ByVal IncludeDelimiter, ByVal RevDelimiter)
'如果Delimiter是空的话,那么把整句都放到字符数组里边
If Delimiter="" Then
iCount = Len(pText)
ReDim outarray(iCount)
For i=1 to iCount
sChar = Mid(pText,i,1)
outarray(i-1)= sChar
Next
Else
'用来存储单词的变量
sword=""
icount=Len(pText)
ReDim outarray(0)
'循环字符串中的每一个字符
For i=1 To iCount
sChar = Mid(pText ,i,1)
'如果该字符是其中的一个分隔符,并且reDelimiter标志是false的话,
'那么创建此单词,并且把它放到结果数组里边
If (InStr(Delimiter,sChar)<>0) and not reDelimiter Then
'把此单词放到数组里边
If sword<> "" Then
outarray(UBound(outarray)) = sword
sword=""
'把数组长度加1
ReDim Preserve outarray(UBound(outarray) +1)
End If
'如果IncludeDelimiter标志为True的话,那么也把分隔符放到数组里边。
If IncludeDelimiter Then
outarray(UBound(outarray)) = sChar
ReDim Preserve outarray(UBound(outarray) +1)
End If
ELseIf(InStr(Delimiter, sChar) =0 and RevDelimiter ) then
'如果这个字符不是分隔符,并且RevDelimiter标志为True的话,那么创建该单词
If sword<> "" Then
outarray(UBound(outarray)) = sword
sword=""
ReDim Preserve outarray(UBound(outarray) +1)
End If
'此分隔符单词总是被放到数组里边
outarray(UBound(outarray)) = sChar
ReDim Preserve outarray(UBound(outarray) +1)
Else
'继续捕获该单词
sword=sword + sChar
End IF
Next
'如果单词不为空,那么把它加到数组里边
If sword<> ""Then
outarray(UBound(outarray)) = sword
ReDim Preserve outarray(UBound(outarray) +1)
End If
End If
'把数组的长度减1,因为当我们根本没有数据的时候数组长度是以1开始的
ReDim Preserve outarrary(UBound(outarray) -1)
SplitEx = outarray
End Function
现在我们把句子分离成单词或则行,我们可以使用SplitEx 函数,如下:
'用法:
'返回Array("You","can't","do","this","can","you")
x= SplitEx("You can't do this,can you?"," ,?:.",false,false)
'返回Array("You"," "," can't "," ","do"," ","this",",","can"," ","you","?")
x= SplitEx("You can't do this,can you?"," ,?:.",True,False)
'返回 Array("line1","Line2","Line3")
x= SplitEx("Line1"&vbCrlf&"Line2"&vbCrlf&"Line3",vbCrLf,False,False)
Fileter
此函数返回包含指定子字符串的字符串数组的子集。
'获得一个数组
x=Array("Tarun","Lalwani","wrote","this","book")
'这会把Array("Tarun","Lalwani")赋给x_Found,因为这两个元素中都包含“r”
x_Found= Filter(x,"r")
Escape/UnEscape
此函数把所有特定字符转化成他们的换吗值。比如“ ”被转换为“%20”,其中20是“”ASCII码值.这个用于在HTML中把特定字符进行编码,并且通过它作为URl的一部分。UnEscape方法能用来对字符串进行解码,并且把“%XXX”字符转换成他们的实际字符。
'编码一字符串
'x="http%3A//mycompany.com/cart%3Faction%3DAdd%26ProdId%3D12%26QTY%3D2"
x=Escape("http://mycompany.com/cart?action=Add&ProdId=12&QTY=2")
'解码一个编码字符串
'x= http://mycompany.com/cart?action=Add&ProdId=12&QTY=2
x=UnEscape(x)
转换函数
这些函数把一个数据类型转换成另一个数据类型,虽然VBScript使用Variant作为它的唯一的主数据类型,但是Variant有子类型,通过使用在本章节描述的函数能动态进行转换。
CBool,CByte,CCur,CDate,CInt,CLng,CSng.CStr
'现在x 包含一个日期格式的字符串
x="12/13/2006"
'现在 x 包含一个日期型的数据
x=CDate(x)
Asc
此函数返回字符的ASCII码值
'返回十进制65
x=Asc("A")
Chr
把ASCII码值转换成字符
'返回字符串“A”
x=Chr(65)
Hex/Oct
将数字转换为表示十六进制或者八进制的字符串。
'返回十六进制 F5
x= Hex(245)
'返回八进制 120
x= Oct(80)
日期和时间函数
这些函数被被用来获取当前日期或者时间,或者同时获取两者
Date
此函数返回当前日期:
'获取本机的当前日期
x=Date()
Time
此函数返回当前时间:
'获取本机的当前时间
x=Time()
Now
'获取本机的当前日期和时间
x=Now()
此函数返回当前日期和时间:
Day/Month/Year
这些函数用来提取日期中的不同的部分。
'此会返回13
s_Day=Day("12/13/2006")
'此会返回12
s_Month=Month("12/13/2006")
'此会返回2006
s_Year=Year("12/13/2006")
Hour/Minute/Seconds
这些函数用来提取时间中的不同的部分。
'这会返回22
s_Hour= Hour("10:32:30 PM")
'这会返回32
s_Minute= Minute("10:32:30 PM")
'这会返回30
s_Second= Second("10:32:30 PM")
Weekday
此函数返回一星期中某天相对应的数值,在星期日值为1,星期六值为7。
DateDiff
此函数用来确定两个日期之间的时间间隔,该间隔可以基于星期,月,天…等
'返回2
x=DateDiff("d","12/13/2006","12/15/2006")
注意:
后一个日期或最新的日期要作为第二个参数以产生一个正的差值,否则会返回一个负数
问题14-6 我们如何计算两个日期之间的工作日(差额应当排除休息日)
此问题可以分成两部分去解决,第一,要获得两个日期之间的差值,这个比较容易,第二,这部分比较困难,就是获得两个日期间隔之间的休息日的数量,这个值是这样计算的,即通过把两个日期之间的差值除以7,还有剩下的就是确定在差值不是7的整数倍的情况下,是否有休息日的存在,我们知道weekday函数返回一个数值,代表了一个星期中的某一天,像1代表的就是星期天,7代表星期六,现在我们画一个小型的图表,了解一下如何检查间隔中是否有休息日。
如上的表格显示了从10/1到10/12之间的每一天的和他们对应的值,现在假设我们需要确定星期一是否在10/3日到10/7日之间。星期一的值2,开始日期的值为3,结束日期的值为7,所以如果检查2(星期一)在3(星期二)和7(星期六)之间,那么就可以知道此日期是否在日期间隔之间。现在问题是,如果是10/5到10/9号之间,起始日期的值为5,结束日期的值为2,结束日期的值比起始日期的值还小,现在如果想检查某一天的存在,那么就需要检查这一天是否在2到5之间(即1,3,4不在此之间)。下面给出了HowManyWeekDays函数。
'用来检查在一个时间间隔中某个日期出现的次数
Function HowManyWeekDays(ByVal startDate,ByVal endDate,ByVal DayToCheck)
Dim startWeekDay
Dim endWeekDay
'两个日期的差值除以7之后的值
Howmanyweekdays=DateDiff("d",CDate(startDate),CDate(endDate))\7
startWeekDay=Weekday(startDate)
endWeekDay=Weekday(endDate)
'检查边界条件
If endWeekDay>=startWeekDay Then
If DayToCheck>=startWeekDay and DayToCheck<=endWeekDay Then
Howmanyweekdays=Howmanyweekdays+1
End If
Else
If DayToCheck<=startWeekDay or DayToCheck>=endWeekDay Then
Howmanyweekdays=Howmanyweekdays+1
End If
End If
End Function
注意:在无需使用ByRef的时候,经常使用ByVal是个好习惯,因为参数默认使用ByRef。
需要检查的日期是星期天即1,星期六即7
如下是最终的函数,计算两个日期之间的工作日。
'函数获得两个日期之间的工作日
Function GetBussinessDays(Byval startDate,Byval endDate)
GetBussinessDays=DateDiff("d",startDate,endDate) - HowManyWeekDays(startDate,endDate,vbSunday) - HowManyWeekDays(startDate,endDate,vbSaturday)
End Function
Timer(问题二:此处说午夜是:12:00 am,而我却认为是00:00am)
此函数用来返回返回午夜 12 时以后已经过去的秒数。它能够用来计算任务的开始和结束的时间差。
注意:如果这个任务在午夜之前开始,午夜之后结束,那么被计算出来的时间差是不正确的。
'获取当前的计数器
StartTime= Timer()
'做一些能消耗时间的任务
'获取当前的计数器
EndTime= Timer()
'给出秒数的差值
msgbox EndTime-StartTime
Misc
此章节包含了一些其他的有用的函数
TypeName
此函数返回一个字符串,提供有关变量的 Variant 子类型信息。
'转换成double型的
x= CDbl(4)
'返回 "double"
MsgBox TypeName(x)
'转换成字符型的
x=CStr(4)
'返回 "String"
MsgBox TypeName(x)
VarType
此函数返回一个常量,代表一个变量的Variable子变量类型。
'转换成整型
x=CInt(4)
'获取变量的类型
If VarType(x)=vbInteger Then
msgbox "It's a interger"
End If
要获得完整的TypeName和VarType值 的列表,请参考VBScript Online Help,
GetRef
GetRef方法能被用来给一个函数创建指针对象,如下的代码给出了同样的用法。
'自定义一个文本比较函数
'我们只关心前5个字符
Function ComparePartText(Text1,Text2)
If Left(Text1,5)=Left(Text2,5) Then
ComparePartText=True
Else
ComparePartText=False
End If
End Function
'此函数比较两个字符串
Function CompareText(Text1,Text2)
If Text1=Text2 Then
CompareText=True
Else
CompareText=False
End If
End Function
'该函数基于比较函数比较两个文本
Function IsEqual(Text1,Text2,CompareFuncPointer)
IsEqual=CompareFuncPointer(text1,text2)
End Function
Text1="TarrunLalwani"
Text2="Tarrun Lalwani"
'显示True
Msgbox IsEqual(Text1,Text2,GetRef("ComparePartText"))
'显示False
Msgbox IsEqual(Text1,Text2,GetRef("CompareText"))
上面的代码,我们传了一个指针给比较函数,在做文本比较的时候通过IsEqual方法被使用。
CreateObject
创建并返回对 Automation 对象的引用。
'定义变量
Dim ExcelSheet
'为ProgID"Excel.Application"创建一个COM对象
Set ExcelSheet = CreateObject("Execl.Application")
sRemoteServer="127.1.1.1"
'为ProgID"Excel.Application"创建一个COM对象
Set ExcelSheet = CreateObject("Execl.Application",sRemoteServer)
GetObject
返回对文件中或者已经打开的应用程序的 Automation 对象的引用
'从运行的文件中获得execl application
Set ExcelObject=GetObject("C:\test\Default.xls")
问题14-7 从一个字符串中获取两个指定字符之间的子字符串。
举例:一个字符串包含“DEL(DELHI),我们需要获取括符“(”和“)”之间的文本。我们的函数任然会从字符的起始位置开始搜索。
'函数用来获得两个指定字符之间的子字符串
Set ExcelObject=GetObject(,"Excel.Application")
Public Function GetStrBetweenChar(Byval Start,ByVal s_Text,Byval s_Startchar,Byval s_EndChar)
GetStrBetweenChar = ""
Dim i,Count,s_Char
i=InStr(Start, s_Text, s_StartChar)
If i<>0 Then
i=i + Len(s_StartChar)
Count=InStr(i,s_Text,s_EndChar)
If Count<>0 Then
GetStrBetweenChar = Mid(s_Text,i,Count -i)
End If
End If
End Function
'应用:
'此会返回"DELHI"
MsgBox GetStrBetweenChar(1,"DEL (DELHI)","(",")")
问题14-8 函数用来获得从某字符开始的子字符串
举例:对于此字符串“DEL(DELHI)”,当起始符为“(”时函数将返回“DELHI)”此算法和上一个函数有点像,但是不同是我们不需要考虑结束字符。
'从一个字符开始获得子字符串
Public Function GetStrFormChar(ByVal Start,ByVal s_Text,ByVal s_StartChar,ByVal ReturnSameNotFound)
If ReturnSameNotFound=True Then
GetStrFormChar=s_Text
Else
GetStrFormChar=""
End If
如果最后一个参数,ReturnSameNotFound=True,那么起始字符没有找到的话,函数将返回同样的字符串
Dim i,count,s_Char
i=InStr(Start,s_text,s_StartChar)
If i<>0 Then
i=i+len(s_StartChar)
GetStrFormChar=Mid(s_Text,i)
End If
End Function
'此会返回(DELHI)
Msgbox GetStrFormChar(1,"DEL(DELHI)","DEL",False)
'此会返回DEL(DELHI)
Msgbox GetStrFormChar(1,"DEL(DELHI)","BEL",True)
'此会返回“”
Msgbox GetStrFormChar(1,"DEL(DELHI)","BEL",False)
问题14-9 编写一个函数,逐个单词地去读取一个字符串,并且两个单词之间被一个或多个空格分开。
此窍门就是,我们会从指定的位置开始过滤字符串,然后从过滤后的字符串中搜索一个空格符,然后返回一个直到到空格位置的字符串。
'函数获取从某位置开始的单词
Public Function GetWordFromPos(ByVal Start,ByVal s_Text)
GetWordFromPos=""
Dim i, count, s_Char, index
i=Start
Count= Len(s_text)
If Start >=count Then
GetWordFromPos=""
Else
s_Text=Trim(Mid(s_Text,i))
index=InStr(s_text," ")
If index Then
GetWordFromPos=Mid(s_Text,1,index-1)
End If
End If
End Function
'此会返回"Tarun"
MsgBox GetWordFromPos(1,"Tarun Lalwani wrote this book")
'此会返回"arun"
MsgBox GetWordFromPos(2,"Tarun Lalwani wrote this book")
'此会返回"Lalwani"
MsgBox GetWordFromPos(6,"Tarun Lalwani wrote this book")
问题14-10.创建一个TrimAll函数,此函数不仅能过滤空格符,其他的空白符,像新行符,回车符,换行符号等。
'函数从过滤字符串的开始到结束过滤所有类型的空白符。
Function TrimALL(ByVal strText)
Dim strLen
Dim strChar
strLen=Len(strText)
TrimAll=""
Dim i
For i=1 To strLen
strChar=Mid(strText, i, 1)
Select Case strChar
Case vbCrLf,vbNewLine,vbTab,vbLf,vbFormFeed,vbCr," "
Case Else
Exit For
End Select
Next
strText= Mid(strText,i)
strLen=Len(strText)
For i=strLen to 1 Step -1
strChar=Mid(strText, i, 1)
Select Case strChar
Case vbCrLf,vbNewLine,vbTab,vbLf,vbFormFeed,vbCr," "
Case Else
Exit For
End Select
Next
strText=Left(strText, i)
TrimALL=strText
End Function
x= vbCrlf + vbNewLine + "wTarun" + vbLf
'此会把"Tarun"赋值给x
x=TrimALL(x)
问题14-11创建一个FilterStr函数,此函数用一个字符串和一个字符集作为输入,并且将基于字符集中的字符去过滤字符串。
举例:使用字符串“212-203-9587”,字符集“0123456789”,此函数是返回”2122039587”,还是”--”取决于标记的设置,该算法判断字符串中的每一个字符,并且检查它在字符集中是否存在,且根据bInCharset标记来创建恰当的返回字符串。
'此函数从字符串中过滤一个字符集
Function FilterStr(ByVal strText,Byval strCharset,Byval bInCharset)
Dim strlen
Dim strChar
strLen=Len(strText)
FilterStr=""
Dim i
If bInCharset Then '返回strText中的每个在字符集中存在的字符
For i=1 To strLen
strChar=Mid(strText,i,1)
If InStr(strCharset,strChar) <>0Then
FilterStr=FilterStr + strChar
End If
Next
Else '返回在strText中的每个在字符集中不存在的字符
For i=1 To strLen
strChar=Mid(strText,i,1)
If InStr(strCharset,strChar)=0 Then
FilterStr=FilterStr + strChar
End If
Next
End If
End Function
'此会返回“2122122122”
Msgbox FilterStr("212-212-2122","0123456789",True)
'此会返回“- -”
Msgbox FilterStr("212-212-2122","0123456789",False)
'此会返回“2122122122”
Msgbox FilterStr("212-212-2122","-",False)
问题14-12 创建两个函数,一个函数返回路径部分,另一个函数返回文件名称(当我们传一个完整路径名称或一个文件名的时候)
'函数从文件名中获得文件路径
Function GetFilePath(Byval s_FileName)
GetFilePath=""
On Error Resume Next
GetFilePath=left(s_FileName,Len(s_FileName)-InStr(StrReverse(s_Filename),"\")+1)
End Function
'函数从路径中获得文件名
Function GetFileName(Byval s_FileName)
GetFileName=""
On Error Resume Next
GetFileName=Right(s_FileName,InStr(StrReverse(s_Filename),"\")-1)
End Function
'将会返回“test.vbs”
MsgBox GetFileName("C:\Test\Test.vbs")
'将返回C:\Test\
MsgBox GetFilePath("C:\Test\Test.vbs")
问题14-13. 写一个函数,比较两个字符串,忽略新行符,换行符号,制表符等空白字符。
'函数从字符串的内部清理空白符
Function CleanText(s_Text)
CleanText=s_Text
CleanText=Replace(CleanText,VbCrLf,"")
CleanText=Replace(CleanText,vbCr,vbLf)
CleanText=Replace(CleanText,Chr(7),"")
CleanText=Replace(CleanText,VbCrLf,vbLf)
CleanText=Replace(CleanText,vbVerticalTab,vbLf)
CleanText=Replace(CleanText,vbTab,"")
End Function
'应用
If CleanText(text1) =CleanText(text2) Then
msgbox "String equal after cleaning"
End If
问题14-14 写一个函数,用另一个字符去代替给定的重复出现的字符。
举例:当给出的输入字符串为“Tarun Lalwani”,用下划线去代替重复出现的空格符,此函数将返回“Tarun Lalwani”。
'此函数会把一个指定连续的字符替换成另一个字符
Function ReplaceMultipleByOne(ByVal strText,ByVal strSearch,ByVal strReplace)
Dim i,strLen,strChar
Dim bFlag
bFlag = False
strLen=Len(strText)
For i=1 to strLen
strChar = Mid(strText,i,1)
If strChar = strSearch Then
If not flag Then
bFlag=true
ReplaceMultipleByOne=ReplaceMultipleByOne+strReplace
End If
Else
bFlag=False
ReplaceMultipleByOne=ReplaceMultipleByOne+strChar
End If
Next
End Function
Arrays
VBScript提供了两种类型的数组-固定长度数组和动态数组
固定长度数组
代码示例:
'创建一个三个成员的固定长度数组
Dim X(2)
X(0)="This"
X(1)="is a"
X(2)="test"
For i=LBound(X) to UBound(X)
Msgbox X(i)
Next
LBound和UBound函数别返回数组的上界和下下界,如上的例子将返回0和2。
动态数组
'创建一个动态数组
Dim X()
'在第一次此使用数组的时候,必须以一定的维数来初始化数组
ReDim X(2)
X(0)="This"
X(1)="is a"
X(2)="test"
每当我们需要改变数组大小的时候,我们可以ReDim一个动态数组。但是每一次这样做,数组里的值都会被破坏,除非我们使用‘Preserve’关键字,如下:
'重新分配数组的维数
ReDim Preserve X(5)
如上的语句,重新定义的数组的长度,同时也保存了前三个元素的值。
就多维数组来说,Preserve关键字只能用于最后维的大小的调整。
'动态数组
Dim X()
ReDim X(2,3)
'此句没有问题,因为我们在保留数组的同时,只改变了最后一维的大小
ReDim Preserve X(2,5)
'此句会抛出一个异常,因为数组的第一维被修改了
ReDim Preserve X(3,5)
'此句没有问题,因为普通的Redim 是没有限制的
ReDim Preserve X(4,5,6)
问题 14-15 如果获得多维数组的上界值和下界值。
关于多维数组array(4,5,6),第一维的上界值将会返回4,要获得其他维数的,我们可以使用UBound的使用可选参数
Dim X(4,5,6)
'返回4,如果第二个参数没有指定,那么默认为1
MsgBox UBound(X,1)
'返回5,即第二维的上界值
MsgBox UBound(X,2)
'返回6,即第三维的上界值
MsgBox UBound(X,3)
Execute 语句
VBScript 提供了一个非常好的语句,Execute,用来在run-time时,执行被定义为字符串的语句。
Execute [语句]
'全局变量x
Dim x
Execute "x=2"
MsgBox x
'在字符串的内部我们需要使用"作为转义字符去定义一个"
x="Browser(""micClass:=Browser"")"
'x会获得浏览器对象
Execute ("Set x="& x)
MsgBox x.Exist(0)
类似的,我们还有一个ExecuteGlobal语句,执行于全局作用域内。
'全局变量 x
Dim x
x=4
Call Func1
Sub Func1
Dim x
x=3
'会输出 3,局部变量
Execute "Msgbox x"
'会输出4,在全局作用域中执行的语句
ExecuteGlobal "Msgbox x"
End Sub
Execute语句作用于局部作用域中,消息框显示的值为3,但是ExecuteGlobal语句作用于全局作用域中,消息框显示的值为4
Eval 函数
Eval函数是用来计算一个表达式
'把2赋值给x
Execute "x=2"
'比较x和3,将会返回false
Msgbox Eval("x=3")
问题:14-16 如何在Run-Time时声明并且初始化一个常量
有些时候,在Run-time 时用来声明一个常量非常有用。
'在加载的时候定义一个只读的变量
Const URL1="http://www.noone.com"
x= "http://www.noone.com"
'在run-time的时候定义一个常量
Execute "Const URL2=" &x
VBScript的可选参数
VBScript不支持可选参数,但是可以使用一些变通的方法,来解决类似的问题。
方法一:可选参数使用Null/Empty
方法二:可选参数使用数组成员
方法三:可选参数使用数组(key,value)对。
方法四:可选参数使用混合对(key,value 或 key:=value)
使用 Null/Empty 值
此方法使用Null 或者Empty值作为可选参数
'此方法用来检查参数是否是一个Null值或则Empty值
Public Function IsMissing(Byval Param)
On error resume next
'验证参数是否为Null值或者Empty值
IsMissing = IsEmpty(Param) or IsNull(Param)
'如果出现了错误,此时可能是一个对象,返回False
If err.Number<>0 Then IsMissing =False
End Function
' Method1展示:可选参数使用Null值或者Empty值
Public Function OptParameter_Method1(Byval Param1,Byval Param2)
If IsMissing(Param1) Then Param1="Tarun"
If IsMissing(Param2)Then Param2="Lalwani"
MsgBox Param1&" "&Param2
End Function
'应用:
Call OptParameter_Method1("Tarun",Null)
Call OptParameter_Method1("Tarun","Lalwani")
Call OptParameter_Method1(Empty,"Lalwani")
使用Array的值
此方法定义一个数组,作为输入的参数,然后使用数组中的一个或多个数组元素和实际的参数。
'可选参数Method2
Public Function OptParameter_Method2(Arguments)
'从Arguments中获取值
FirstName=Arguments(0)
LastName=Arguments(1)
If IsMissing(FirstName) Then FirstName="Tarun"
If IsMissing(LastName)Then LastName="Lalwani"
'对数据做处理
'如果你想让此引用生效,那么重新赋值给数组
Arguments(0)= FirstName
Arguments(1)=LastName
MsgBox FirstName&" "&LastName
End Function
'应用
Call OptParameter_Method2(Array("Tarun",Null))
Call OptParameter_Method2(Array(Null,Null))
此方法的问题是,如果最后一个参数都丢失,那么我们每次都会传一个Null。假设参数丢失,我们可以改进此方法,在参数丢失的情况下自动的扩展此数组。
'可选参数Method2A
Public Function OptParameter_Method2A(Arguments)
Const ParamCount=2
Dim Params
'检查是否有数组
If IsMissing(Arguments) Then
ReDim Params(ParamCount-1)
Else
'如果Arguments不是一个数组的话,那么使它成为一个数组
If VarType(Arguments)< vbArray Then
Arguments=Array(Arguments)
End If
Params= Arguments
'重新定义数组的长度,以获参数的期望的长度
'使用preserve防止其他的参数丢失。
ReDim Preserve Params(ParamCount -1)
End If
'在这里不再重复此代码
Call OptParameter_Method2(Params)
End Function
Call OptParameter_Method2A(Null)
Call OptParameter_Method2A("Tarun")
Call OptParameter_Method2A(Array(Null,"Lalwani"))
Call OptParameter_Method2A(Array("Tarun"))
使用形式为(Key,Value)对的数组
在这个方法里边,我们给参数传一对值,一个是名称,另一个是值,在此例子里边参数的个数必须是偶数,我们会从数组中创建一个dictionary,并且把它作为参数,我们首先看一下如何从数组参数转化为dictionary。(问题3:如下应该显示GetArgumentsList_v1方法,但是却显示的上一个例子使用的方法- Method2A,GetArgumentsList_v1我自己写了一个,可以运行成功,详见附件)
'方法2A
Public Function OptParameter_Method2A(Arguments)
Const ParamCount=2
Dim Params
'检查是否有数组
If IsMissing(Arguments) Then
ReDim Params(ParamCount-1)
Else
'如果Arguments不是一个数组的话,那么使它成为一个数组
If VarType(Arguments)< vbArray Then
Arguments=Array(Arguments)
End If
Params= Arguments
'重新定义数组的长度,以获参数的期望的长度
'使用preserve防止其他的参数丢失。
ReDim Preserve Params(ParamCount -1)
End If
'在这里不再重复此代码
Call OptParameter_Method2(Params)
End Function
Call OptParameter_Method2A(Null)
Call OptParameter_Method2A("Tarun")
Call OptParameter_Method2A(Array(Null,"Lalwani"))
Call OptParameter_Method2A(Array("Tarun"))
现在我们看下如何应用上面的方法。
'方法展示
Public Function OptParameter_Method3(Arguments)
Set Params = CreateObject("Scripting.Dictionary")
GetArgumentsList_v1 Params,Arguments
FirstName= GetParamValue(Params,"FirstName","Tarun")
LastName= GetParamValue(Params,"LastName","Lalwani")
MsgBox FirstName &" "&LastName
End Function
'应用
Call OptParameter_Method3(Null)
Call OptParameter_Method3(Array("FirstName","Tarun","LastName","Lalwani"))
Call OptParameter_Method3(Array("FirstName","Tarun"))
Call OptParameter_Method3(Array("LastName","LastName"))
(问题4:如上的GetParamValue函数在书本中也未出现,我自己写了一个函数,详见附件)
使用形式为key:=Value的数组
在此方法中,函数的参数是以key:=value的方式传递的,此函数把传递的值转化成dictionary,如下:
'此函数把数组中转化为dictionary
Public sub GetArgumentsList_v2(ArgListDict, Arguments)
'设置比较模式为文本模式,这样参数就不会对字符敏感。
ArgListDict.CompareMode = vbTextCompare
'如果参数缺少那么不处理
If IsMissing(Arguments) Then Exit Sub
Dim i,iCount
iCount=uBound(Arguments)
For i=LBound(Arguments) to iCount step 1
valPos=InStr(Arguments(i),":=")
ParamName = Left(Arguments(i),valPos-1)
ParamValue=Mid(Arguments(i),valPos+2)
ArgListDict.Add ParamName,ParamValue
Next
End Sub
'方法演示
Public Function OptParameter_Method4(Arguments)
Set Params = CreateObject("Scripting.Dictionary")
GetArgumentsList_v2 Params,Arguments
FirstName= GetParamValue(Params,"FirstName","Tarun")
LastName= GetParamValue(Params,"LastName","Lalwani")
MsgBox FirstName &" "&LastName
End Function
'应用
Call OptParameter_Method4(Null)
Call OptParameter_Method4(Array("FirstName:=Tarun"),"LastName:=Lalwani")
Call OptParameter_Method4(Array("FirstName:=Tarun"))
Call OptParameter_Method4(Array("LastName:=Lalwani"))
使用形式为(key,value 或者 Key:=value)混合的数组
此方法既可以支持使用(Key,Value)传参数给函数,也可是使用Key:=value组合,使用此方法的优点是可以以任何顺序传参,而且可以在使用(Key,Value)对的同时,传递对象
'此函数把数组中转化为dictionary
Public sub GetArgumentsList_v3(ArgListDict, Arguments)
'设置比较模式为文本模式,这样参数就不会对字符敏感。
ArgListDict.CompareMode = vbTextCompare
'如果参数缺少那么不处理
If IsMissing(Arguments) Then Exit Sub
Dim i,iCount
iCount=uBound(Arguments)
For i=LBound(Arguments) to iCount step 1
valPos=InStr(Arguments(i),":=")
If valPos=0 Then
'这是一个key,value对
ParamName=Arguments(i)
'移到value的位置
i=i+1
ParamValue=Arguments(i)
Else
'这是一个 Key:=value对
ParamName = Left(Arguments(i),valPos-1)
ParamValue=Mid(Arguments(i),valPos+2)
End if
ArgListDict.Add ParamName,ParamValue
Next
End Sub
'方法展示
Public Function OptParameter_Method5(Arguments)
Set Params = CreateObject("Scripting.Dictionary")
GetArgumentsList_v3 Params,Arguments
FirstName= GetParamValue(Params,"FirstName","Tarun")
LastName= GetParamValue(Params,"LastName","Lalwani")
MsgBox FirstName &" "&LastName
End Function
'应用
Call OptParameter_Method5(Null)
Call OptParameter_Method5(Array("FirstName,Tarun","LastName:=Lalwani"))
Call OptParameter_Method5(Array("FirstName:=Tarun"))
Call OptParameter_Method5(Array("LastName:=Lalwani"))