VBA实战技巧精粹015:关于Split函数的一些认识

在前面已经用过Split函数了,可以方便的获取指定单元格的行标或列标,具体的用法可以参见以下代码:

Sub 获取指定列的字母()
    Debug.Print Cells(1, 27).Address
    Debug.Print Split(Cells(1, 27).Address, "$")(1)
End Sub
下面是关于Split函数的一些认识,肯定不全,但也得记下来,不然以后怎么再复习呢。切记:好记性不如烂笔头,更不如臭博客。

先抄一段官方解释:

描述

返回一个下标从零开始的一维数组,它包含指定数目的子字符串。

语法

Split(expression[, delimiter[, limit[, compare]]])

Split函数语法有如下命名参数:

部分 描述
expression 必需的。包含子字符串和分隔符的字符串表达式 如果expression是一个长度为零的字符串(""),Split则返回一个空数组,即没有元素和数据的数组。
delimiter 可选的。用于标识子字符串边界的字符串字符。如果忽略,则使用空格字符(" ")作为分隔符。如果delimiter是一个长度为零的字符串,则返回的数组仅包含一个元素,即完整的 expression字符串。
limit 可选的。要返回的子字符串数,–1表示返回所有的子字符串。
compare 可选的。数字值,表示判别子字符串时使用的比较方式。关于其值,请参阅“设置值”部分。





设置值

compare参数的设置值如下:

常数 描述
vbUseCompareOption –1 Option Compare语句中的设置值执行比较。
vbBinaryCompare 0 执行二进制比较。
vbTextCompare 1 执行文字比较。
vbDatabaseCompare 2 仅用于Microsoft Access。基于您的数据库的信息执行比较。

连段示例代码都没有,看来对这个函数应该是比较好掌握,也是,语法比较简单,但问题的焦点不在这儿,而是它最终返回的数值问题:①到底是不是从0开始?②受不受Option Base 1的约束?③到底如何理解数组的上标和下标,是表示数组长度吗?

关于①与②的问题其实是一个问题:如果受Opiton Base 1的约束,那就从1开始,如果不受,那就从0开始了。帮助里说的很清楚了,返回一个下标从0开始的一维数组(顺便解决一个,水平方向的一维数组!!),言外之意就是不受Option Base 1的约束。

关于③:利用Lbound函数及Ubound函数可以分别得到指定数组的下标及上标,但要注意,这仅是说明了该数组的第1个元素及最后1个元素所对应的索引号,而上标并不一定是该数组的长度,如果数组从0开始计数,例如Split函数返回的数组,那上标只是最后1个元素对应的索引号,并不是数组的长度了。那不管是下标是不是从0开始,应该如何计算数组的长度呢?或者说有没有一个通用的方法来计算数组的长度?当然有啊,就是Ubound(arr)-Lbound(arr)+1,这就是标准的计算数组长度的公式,而不用考虑下标是否从0开始了。

下面是关于以上方法的一个验证:

Sub split函数赋值给单元格()
    Dim i As Integer, s As String
    For i = 1 To 2
        Cells(i, 1).Value = Split(Cells(i, 1).Address, "$")(1)
        s = s & Cells(i, 1).Address
    Next i
    
    Debug.Print UBound(Split(s, "$")) - LBound(Split(s, "$")) + 1
    Range("C1").Resize(UBound(Split(s, "$")) + 1, 1).Value = Application.WorksheetFunction.Transpose(Split(s, "$"))
    For i = 0 To UBound(Split(s, "$"))
        Cells(i + 1, 4).Value = Split(s, "$")(i)
    Next i
End Sub
需要注意一点,在模块开始部分务必加上Option Base 1

在上一句的基础上,再验证以下代码:

Sub 验证()
    Dim arr() As Variant
    arr = Array("11", "22", "3")
    Debug.Print UBound(arr)
    Debug.Print arr(0)
End Sub
运行后会提示:下标超界,什么原因呢?原来是由于你在模块开始部分加上了Option Base 1了,导致array函数返回的数组下标(索引号)变成从1开始,你非要输出arr(0)当然要错了,那如果不加Opiton Base 1呢?再输出arr(0)当然没问题了。

从以下两段代码现在可以看出:Split函数生成的数组不受Option Base 1的约束,而Array函数生成的数组受Option Base 1的约束,那么到底哪些返回的结果是数组,哪些不是,在返回数组的基础上,又有哪些受Option Base 1的约束,哪些又不受呢?

慢慢总结吧。

再补充:

Sub split函数赋值给单元格()
    Dim i As Integer, s As String,
y As Variant
    For i = 1 To 2
        Cells(i, 1).Value = Split(Cells(i, 1).Address, "$")(1)
        s = s & Cells(i, 1).Address
    Next i
    s = "$A$1$A$2"
    Debug.Print UBound(Split(s, "$")) - LBound(SplitVariant(s, "$")) + 1
    Range("C1").Resize(UBound(Split(s, "$")) + 1, 1).Value = Application.WorksheetFunction.Transpose(Split(s, "$"))
   
For Each y In Split(s, "$")
        Debug.Print y
    Next y
End Sub

注意到红体字了吗?这是利用遍历的一样可以输出每个元素,但要注意是所有元素,包括前为空的那个,而实际上我需要的是后4个,所以方法可以借鉴,但不如利用for循环来的更精确。

关于Variant的解释:(来自官方解释,抄袭,严重的抄袭!)

Variant 数据类型是所有没被显式声明(用如 DimPrivate、PublicStatic语句)为其他类型变量数据类型Variant 数据类型并没有类型声明字符

Variant 是一种特殊的数据类型,除了定长 String 数据及用户定义类型外,可以包含任何种类的数据。Variant 也可以包含 EmptyErrorNothing Null等特殊值。可以用 VarType 函数或 TypeName 函数来决定如何处理 Variant 中的数据。

数值数据可以是任何整型或实型数,负数时范围从
-1.797693134862315E308 到 -4.94066E-324,正数时则从 4.94066E-324 到 1.797693134862315E308。通常,数值 Variant 数据保持为其 Variant 中原来的数据类型。例如,如果把一个
Integer赋值给 Variant,则接下来的运算会把此 Variant 当成 Integer 来处理。然而,如果算术运数针对含 ByteIntegerLong Single 之一的Variant 执行,并当结果超过原来数据类型的正常范围时,则在 Variant 中的结果会提升到较大的数据类型。如 Byte 则提升到 IntegerInteger 则提升到 Long,而 LongSingle 则提升为 Double。当 Variant 变量中有 CurrencyDecimal Double 值超过它们各自的范围时,会发生错误。

可以用 Variant 数据类型来替换任何数据类型,这样会更有适应性。如果 Variant 变量的内容是数字,它可以用字符串来表示数字或是用它实际的值来表示,这将由上下文来决定,例如:

Dim MyVar As Variant MyVar = 98052  

在前面的例子中,MyVar 内有一实际值为 98052 的数值。像期望的那样,算术运算子可以对 Variant 变量运算,其中包含数值或能被解释为数值的字符串数据。如果用 + 运算子来将 MyVar 与其他含有数字的 Variant数值类型的变量相加,结果便是一算术和。

Empty 值用来标记尚未初始化(给定初始值)的 Variant 变量。内含 EmptyVariant 在数值的上下文中表示 0,如果是用在字符串的上下文中则表示零长度的字符串 ("")。

不应将 Empty Null 弄混。Null 是表示 Variant 变量确实含有一个无效数据。

Variant 中,Error 是用来指示在过程中出现错误时的特殊值。然而,不像对其他种类的错误那样,程序并不产生普通的应用程序级的错误处理。这可以让程序员,或应用程序本身,根据此错误值采取另外的行动。可以用 CVErr 函数将实数转换为错误值来产生 Error 值。


 

菊子曰 这就是菊子曰啦!
posted @ 2011-04-29 10:12  surfacetension  阅读(6495)  评论(0编辑  收藏  举报