VBA字符串用法自整理Word格式文档下载.docx
- 文档编号:20258770
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:32
- 大小:33.19KB
VBA字符串用法自整理Word格式文档下载.docx
《VBA字符串用法自整理Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《VBA字符串用法自整理Word格式文档下载.docx(32页珍藏版)》请在冰豆网上搜索。
后面的讨论假设默认情况下。
2).如果模式中没有使用通配符(?
、*、#)和字符列表,此时Like运算符等价于=(等号)运算符。
下面表达式的结果相同。
sLike"
AB"
s="
3).字符列表
理解字符列表的用法是学会Like的难点
(1)一个字符列表匹配的是字符串中的一个字符,不管字符列表中实际有多少个字符。
"
Like[ABCDEGHIJ2345]结果为True
Like[ABCDEGHIJ2345]结果为False
唯一的例外是[]被看作长度为零的字符串。
问:
“一个字符列表匹配的是字符串中的一个字符,不管字符列表中实际有多少个字符。
”
这个不理解。
为什么"
Like[ABCDEGHIJ2345]结果为True而多一个B就为“False”
答:
和模式[ABCDEGHIJ2345]匹配的字符串需符合两个条件:
1.它是有1个字符组成的字符串.因为这个模式只有一个字符列表.
2.这个字符是ABCDEGHIJ2345中的一个.
符合这两个条件.所以为TRUE
不符合第1个条件.结果为FALSE
不也是包含在ABCDEGHIJ2345的吗?
难道有两个字符以上就不能比较是否包含在另一个字符串(字符列表)里面?
谢谢!
如果要判断字符串是否由两个上面的字符组成:
模式为[ABCDEGHIJ2345][ABCDEGHIJ2345]
这时上面的"
不匹配,"
匹配
(2)字符列表中的单个字符,没有顺序要求,上面[ABCDEGHIJ2345]和[ACDEGHIJ2345B]、[3ABCDEGHIJ245]...等等是一样的表达。
(3)字符列表中一段连续的字符(称为区间,一个字符列表可以有多个区间,广义上,单个字符也可被看作一个区间),可以使用连字符(-,减号)简化表达式,如上面的表达式[ABCDEGHIJ2345]可以简化为[A-EG-J2-5],连字符要遵循从小到大的顺序(升序),即连字符(-)右端的字符应大于左端的字符,如其中的A-E不能写成E-A,后者系统会报错。
但多个区间之间没有顺序要求,这意味着[G-J2-5A-E]、[2-5G-JA-E]...等是同一表达。
但下面的表达是错误的,同时也是常见的:
[A-EG-J2-5]、[A-E,G-J,2-5]、[A-E;
G-J;
2-5]
也许只是一种习惯或想当然,第一个除了要求表达的ABCDEGHIJ2345外,还多加了一个空格;
后面两个分别多了逗号(,)和分号(;
)。
"
"
Like[A-EG-J2-5]结果为False
Like[A-E,G-J,2-5]结果为True
(4)被中括号([])括起的字符列表中的字符,?
、*、#不被理解为通配符,而是表示符号自身。
如果要表示-(减号,连字符),可以放在列表的开头或结尾。
如[ABC-]、[-ABC]。
3"
结果为True
[?
]"
结果为False
这一特性通常被用作特殊字符的表示,例如,除了通配符外,左括号([)等特殊字符都可以将它们用方括号括起来。
要注意的是,也不能在一个组内使用右括号(])与自身匹配,但在组外可以作为个别字符使用。
(5)在字符列表加上!
(感叹号)开头,表示要匹配的是不在字符列表中的任一字符(不包括开头的!
自身)。
!
]表示除了感叹号之外的任一字符。
4).例子
下面是EXCEL/VBA帮助中举的几个Like运算符的例子,对照结果看看,如果和你想的结果都一样,说明你已经基本掌握了Like用法。
DimMyCheck
MyCheck="
aBBBa"
a*a"
'
返回True。
F"
[A-Z]"
A-Z]"
返回False。
a2a"
a#a"
aM5b"
a[L-P]#[!
c-e]"
BAT123khg"
B?
T*"
CAT123khg"
5).思考题
假设有一字符串s,写出表达式,判断s是否是仅由字母组成并且以字母e(E)结尾的字符串。
Sub主程序()
字符串("
aasdfasdba1E"
)
EndSub
Function字符串(sAsString)
DimbAsLong,aAsLong
IfMid(s,Len(s),1)Like"
[eE]"
Then
b=b+1
Fora=1ToLen(s)-1
IfMid(s,a,1)Like"
[a-zA-Z]"
EndIf
Next
Ifb=Len(s)Then
MsgBox"
完全正确"
EndFunction
总是测试不成功,在这个基础上,改一改吧:
Sub字符串()
DimsAsString
aasdfasdbaE"
Fora=1ToLen(s)
Ifb=Len(s)AndRight(s,1)Like"
Else
No"
2.StrComp函数
StrComp函数返回字符串比较的结果。
其语法为:
StrComp(string1,string2[,compare])
其中,参数string1和strng2为必需的参数,可以是任何有效的字符串表达式。
参数Compare为可选参数,如果该参数为Null,将发生错误。
如果参数Compare设置为常数vbUseCompareOption或-1或忽略该参数,将使用OptionCompare语句设置进行比较;
如果忽略该参数且没有设置OptionCompare语句,则按二进制进行比较;
如果参数Compare设置为常数vbBinaryCompare或0,则用二进制进行比较;
如果参数Compare设置为常数vbTextCompare或1,则按文本进行比较;
如果参数Compare设置为常数vbDatabaseCompare或2,此时仅适用于MicrosoftAccess,进行基于数据库信息的比较。
StrComp函数的返回值为:
如果String1<
String2,则返回值为-1;
如果String1=String2,则返回值为0;
如果String1>
String2,则返回值为1;
如果String1或String2为Null,则返回值为Null。
看看下面的示例:
SubtestStringCompare()
DimMyStr1AsString,MyStr2AsString,MyComp1,MyComp2,MyComp3,MyComp4
MyStr1="
ABCD"
MyStr2="
abcd"
MyComp1=StrComp(MyStr1,MyStr2,1)
&
apos;
返回0
MyComp2=StrComp(MyStr1,MyStr2,0)
返回-1
MyComp3=StrComp(MyStr1,MyStr2)
MyComp4=StrComp(MyStr2,MyStr1)
返回1
MsgBox"
StrComp(MyStr1,MyStr2,1)的结果为:
MyComp1
StrComp(MyStr1,MyStr2,0)的结果为:
MyComp2
StrComp(MyStr1,MyStr2)的结果为:
MyComp3
StrComp(MyStr2,MyStr1)的结果为:
MyComp4
示例说明:
如果StrComp函数的第三个参数值为1,则以文本比较的方式进行字符串比较;
如果第三个参数值为0或忽略该参数,则以二进制比较的方式进行字符串比较。
注意,文本比较的方式不区分字母大小写,而二进制比较方式则区分大小写。
示例:
完成一次简单的单一比较,如
IfUCase(sString1)<
UCase(sString2)Then
比使用StrComp函数:
IfStrComp(sString1,sString2,vbTextCompare)=-1Then
在性能上要提高30%,且更容易阅读和理解。
OptionCompare
在模块级别中使用,用于声明字符串比较时所用的缺省比较方法。
OptionCompare{Binary|Text|Database}
说明:
如果使用,则OptionCompare语句必须写在模块的所有过程之前。
OptionCompare语句为模块指定字符串比较的方法(Binary、Text或Database)。
如果模块中没有OptionCompare语句,则缺省的文本比较方法是Binary。
OptionCompareBinary是根据字符的内部二进制表示而导出的一种排序顺序来进行字符串比较。
在MicrosoftWindows中,排序顺序由代码页确定。
典型的二进制排序顺序如下例所示:
A<
B<
E<
Z<
a<
b<
e<
z
OptionCompareText根据由系统国别确定的一种不区分大小写的文本排序级别来进行字符串比较。
当使用OptionCompareText对相同字符排序时,会产生下述文本排序级别:
(A=a)<
(_=_)<
(B=b)<
(E=e)<
(_=_)<
(Z=z)<
(_=_)
OptionCompareDatabase只能在MicrosoftAccess中使用。
当需要字符串比较时,将根据数据库的国别ID确定的排序级别进行比较。
二、字符串替换:
Mid语句
Mid语句:
替换字符串的部分内容
是的,你没有看错,我是说Mid语句,而不是Mid函数。
让我们看一个例子。
已知:
字符串s="
12345"
,整数i=2
要求:
将s的第i个字符替换为"
d"
通常的方法(Mid函数):
s=left(s,i-1)&
mid(s,i+1)
Mid语句的方法:
Mid(s,i,1)="
下面我们来看看帮助中介绍的的Mid语句
在一Variant(String)变量中以另一个字符串中的字符替换其中指定数量的字符。
语法
Mid(stringvar,start[,length])=string
stringvar必要参数。
被更改的字符串变量名。
start必要参数;
Variant(Long)。
stringvar中被替换的字符开头位置。
length可选参数;
被替换的字符数。
如果省略,string将全部用上。
string必要参数。
字符串表达式,替换部分stringvar的址?
说明
被替换的字符数量总是小于或等于stringvar的字符数。
示例
SubUseMid()
Dims$
s="
Mid(s,2,1)="
Debug.Prints'
1d345--替换1个字符,第2个字符被替换为d
df"
1d345--只替换1个字符,第2个字符被忽略
Mid(s,2,2)="
1df45--替换2个字符
Mid(s,5,1)="
1234d--只替换1个字符,第2个字符被忽略
Mid(s,5,2)="
1234d--只替换1个字符,第2个字符超出s长度,被忽略
Mid(s,6,1)="
出错--6超出s长度
Debug.Prints
相关
简单的介绍一下相关的三个函数,也许你已经对它们很熟悉了,我写在这儿的目的只是让这段文字看起来更完整。
关于它们的具体细节,请参考帮助文档。
1.Mid函数
Mid(string,start[,length])
返回从字符串string的start位置取出的指定长度length的字符,如省略length或length超过文本的字符数(包括start处的字符),将返回字符串中从start到尾端的所有字符。
2.Right函数
返回Variant(String),其中包含从字符串右边取出的指定数量的字符。
Right(string,length)
Right函数的语法具有下面的命名参数:
string
必要参数。
字符串表达式,从中最右边的字符将被返回。
如果string包含Null,将返回Null。
length
必要参数;
为Variant(Long)。
为数值表达式,指出想返回多少字符。
如果为0,返回零长度字符串("
如果大于或等于string的字符数,则返回整个字符串。
3.Left函数
返回Variant(String),其中包含从字符串左边算起指定数量的字符。
Left(string,length)
Left函数的语法有下面的命名参数:
字符串表达式其中最左边的那些字符将被返回。
数值表达式,指出将返回多少个字符。
三、与字符串数组有关的三个函数
1.Split函数
返回一个下标从零开始的一维数组,它包含指定数目的子字符串。
Split(字符串[,分隔符[,要返回的子字符串数量[,比较方式]]])
后三项可选,默认:
分隔符为空格,返回全部子字符串,用OptionCompare语句中的设置值执行比较。
下面是将1-12转化为一月-十二月的自定义函数的例子。
FunctionNum2ch(ByValnAsInteger)AsString
DimArr
Arr=Split("
一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月"
"
)
Num2ch=Arr(n)
EndFunction
和Array函数相比,用Split的好处在于生成的数组是字符型的,写法上也更简洁。
注意“一月”前的逗号,这是因为Split生成的数组下标是从0开始的,且不受OptionBase句的影响。
2.Join函数
返回一个字符串,该字符串是通过连接某个数组中的多个子字符串而创建的。
Join(源数组[,分隔符])
默认:
分隔符为空格
当将分隔符设为空串(””)时,会返回一个各数组元素会直接相连的字符串。
该函数是Split函数的反函数,它是将数组转化为字符串。
Join和Split相配合,可用于扩充控件TAG属性的传递数量;
在不定参数的传递时,可使代码看起来更简洁。
下面只是它们配合的示例,并不是这儿真有必要这样做:
SubaMain()
Dimarr(1To2),s$
arr
(1)=1:
arr
(2)=2
s=Join(arr,"
Debug.PrintMyadd(s)
EndSub
FunctionMyadd(ByValsAsString)
Dimarr,x
arr=Split(s,"
ForEachxInarr
Myadd=Myadd+Val(x)
Nextx
3.Filter函数
返回一个下标从零开始的数组,该数组包含基于指定筛选条件的一个字符串数组的子集。
Filter(源数组,要搜索的字符串[,返回子串包含还是不包含要搜索字符串[,比较方式]])
如果在源数组中没有发现与要搜索的字符串相匹配的值,Filter返回一个空数组。
如果源数组是Null或不是一个一维数组,则产生错误。
注意是“包含”要搜索的字符串,而不是“等于”要搜索的字符串。
这意味着,如果一数组元素为字符串“AB”,用“A”、“B”、“AB”中的任何一个去搜索(上面第三个参数为默认值True),都会作为新的数组的元素被返回。
但这并不影响你创造成“包含”等同于“等于”的条件,或者数据本身就符合这一要求的条件。
在“包含”等同于“等于”的数组中,我们可以用下面的办法来判断一个字符串是否属于某个数组。
IfUBound(Arr)=UBound(Filter(Arr,"
要找的字符串"
False))Then‘说明在数组Arr中找不到
四、快速交换字符串
很多时候其实我们对速度是不强求的,速度的要求只会在特殊的场合才显得重要,当然,除非你是一个严格要求自己追求优秀的人。
有过C程序经历的人,常常对VB中不能象C一样使用指针耿耿于怀,指针是C的基本技术,期望使用它不仅仅是随心所欲地的需要,其实也是对速度的追求,后来你应该能找到在VB中使用指针的方法,笔者也曾经想把这种技术结合VBA的特点介绍给大家,但VBA下试验的结果却让人失望,VB和VBA差别还是蛮大的!
所幸没有被完全否定,下面的要讲的,就是勉强还可以适用于VBA的一个。
正因为如此,我不打算对这个几乎在VBA下没用的技术多费笔墨了,只说一个抽象的概念吧--什么是指针?
--免得用时被人问起,你又无话可说的尴尬。
--指针即地址,在VBA下,它就是一个Long类型的整数!
足矣!
剩下的,照着下面的葫芦画瓢吧。
我们要做的是交换两个字符串。
常规的方法:
SubChgStr1(s1AsString,s2AsString)
s=s1:
s1=s2:
s2=s
指针的方法:
PrivateDeclareSubCopyMemoryLib"
kernel32"
Alias"
RtlMoveMemory"
(DestinationAsAny,SourceAsAny,ByValLengthAsLong)
SubChgStr2(s1AsString,s2AsString)
Dimtmp&
CopyMemorytmp,ByValVarPtr(s1),4
CopyMemoryByValVarPtr(s1),ByValVarPtr(s2),4
CopyMemoryByValVarPtr(s2),tmp,4
哪一个更快,不说你也知道了。
在VB下,编译后,后者比前者要快一倍。
VBA下,没有这么悬殊,笔者测试的结果,应该快25%以上。
但由于后者不受交换字符串长短的影响,所以在交换长字符串时,优势会更明显。
下面是测试代码,有兴趣试试吧:
注意:
有时下面的测试并不能得到上面的结果,但如果你加大两个字符串的长度到一定程度,上面的结论是成立的。
SubaTest()
Dimi&
tm&
t1
Dims1$,s2$
tm=999999'
测试次数
s1="
abc"
s2="
cde"
t1=Timer
Fori=1Totm
ChgStr1s1,s2
Nexti
Debug.PrintTimer-t1
ChgStr2s1,s2
五、定长字符串
先来看一段代码:
Debug.PrintLen(s)=1
Debug.Prints="
你是否认为上面的输出必然是两个TRUE,答案自然是否定的。
选择从这儿开始,只是为了加深你的印象。
在VBA中,字符串有两种类型,一种是变长的字符串,这是我们常用的,声明的方法可以是下面的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VBA 字符串 用法 整理