VBA实战技巧精粹010:如何快速选定工作表及Option Base 1

问题背景:经常性的要对同一工作簿中的多个工作表同时进行格式设置等,那就需要首先先对其进行选定,建立工作表组,然后才能对进行操作.

问题提出:①如何快速选定同一工作簿中所有工作表?②如何选定部分工作表?

解决代码:

①如何快速选定同一工作簿中的所有工作表?

Sub 快速选定所有工作表()
    Dim sht As Worksheet
    For Each sht In Worksheets
        sht.Select Replace:=False
    Next sht
    Sheets(1).Select ' 如何取消工作表
    Sheets.Select
    Sheets(1).Select
    Worksheets.Select
    Sheets(1).Select
End Sub
上面的代码提出了两种解决方法:一是利用For each循环语句,但要注意其中的sht.Select replace:=Fasle语句,表示延伸当前选定对象以包括任何以前选定的对象;若为True,则用指定对象代替当前选定的对象.二是直接利有工作表集合Worksheets的Select方法.同时还解决如何取消工作表群组,非常简单-选定其中任一个工作表即可.

②如何选定部分工作表?

需要用到Array函数,解释如下:

Array 函数

返回一个包含数组 Variant

语法

Array(arglist)

所需的 arglist 参数是一个用逗号隔开的值表,这些值用于给 Variant 所包含的数组的各元素赋值。如果不提供参数,则创建一个长度为 0 的数组。

说明

用来表示数组元素的符号由变量名、圆括号以及括号中的所需元素的索引号组成。在下面的示例中,第一条语句创建一个 Variant 的变量 A。第二条语句将一个数组赋给变量 A。最后一条语句将该数组的第二个元素的值赋给另一个变量。

Dim A As Variant A = Array(10,20,30) B = A(2)  

使用 Array 函数创建的数组的下界受 Option Base 语句指定的下界的决定, 除非 Array 是由类型库(例如 VBA.Array )名称限定。如果是由类型库名称限定,则 Array 不受 Option Base 的影响。

注意 没有作为数组声明的 Variant 也可以表示数组。除了长度固定的字符串以及用户定义类型之外,Variant 变量可以表示任何类型的数组。尽管一个包含数组的 Variant 和一个元素为 Variant 类型的数组在概念上有所不同,但对数组元素的访问方式是相同的。

Sub 测试用()
    Dim A As Variant, B As String
    A = Array(10, 20, 30)
    B = A(2)
    Debug.Print B '输出30
    Worksheets(Array("sheet1", "sheet2")).Select
End Sub

但用Array函数未成功,因为我想通过循环将获得的需群组工作表名称添加到Array函数的参数列表中,但未成功,但现在已经明白一点:Array返回数组.

重新编写的代码如下:

'群组后 , 选定的工作就成为活动工作表了
Sub 选定部分工作表()
    Dim ShtCount As Integer, i As Integer, ShtName() As String, sht As Worksheet
    ShtCount = Worksheets.Count
    ReDim ShtName(1 To ShtCount)
    Sheets(1).Select
    For i = 1 To ShtCount Step 2
        ShtName(i) = Sheets(i).Name
        Set sht = Worksheets(ShtName(i))
        sht.Select Replace:=False
    Next i
End Sub

感觉上面的代码有点麻烦,改进如下:

Sub 选定部分工作表改进()
    Dim ShtCount As Integer, i As Integer
    ShtCount = Worksheets.Count
    Sheets(1).Select
    For i = 1 To ShtCount Step 2
        Worksheets(Sheets(i).Name).Select
Replace:=False
    Next i
End Sub

总想利用数组来一次性全选,改进代码如下:

Sub 选定部分工作表改进2()
    Dim ShtCount As Integer, i As Integer, ShtName() As String, arr() As String
    ShtCount = Worksheets.Count
    ReDim ShtName(1 To ShtCount)
    For i = 1 To ShtCount Step 2
        ShtName(i) = Sheets(i).Name
    Next i
    ReDim arr(Int((ShtCount - 1) / 2 + 1))
    For i = 1 To Int((ShtCount - 1) / 2 + 1)
        arr(i) = Sheets(1 + (i - 1) * 2).Name
    Next i
    Worksheets(arr).Select
End Sub

'进一步的改进如下:
Sub 选定部分工作表改进3()
    Dim ShtCount As Integer, i As Integer, arr() As String
    ShtCount = Worksheets.Count
    ReDim arr(Int((ShtCount - 1) / 2 + 1)) '计算需要循环几次,即为arr数组需要重定义的元素数.
    For k = 1 To Int((ShtCount - 1) / 2 + 1)
        arr(k) = Sheets(1 + (k - 1) * 2).Name '需要算出每次循环对应的工作表索引号.(默认从1开始)
    Next k
    Worksheets(arr).Select
End Sub
这里就要用到数学上的数列知识了:

有一循环语句:for i=m to n step j,现需要计算一共循环了几次:(m代表工作表开始的索引号,n代表结束的索引号)

用k表示循环次数,那么n=m+(k-1)*j,解得:k=(n-m)/j+1,但出来的结果一般情况会有小数部分,则实际k值为取整.即为:

k=int((n-m)/j+1)

那么上面的循环就可以用循环次数来进行代替:for k=1 to int((n-m)/j+1)

可是如何确定每次循环对应的工作表索引号?

m+(k-1)*j就是这k次循环所对应的工作表索引号.

进一步的改进代码如下:

'进一步的改进如下:
Sub 选定部分工作表改进4()
    Dim ShtCount As Integer, k As Integer, arr() As String
    ShtCount = Worksheets.Count
    ReDim arr(Int((ShtCount - 1) / 2 + 1))
    For k = 1 To Int((ShtCount - 1) / 2 + 1)
        arr(k) = Sheets(1 + (k - 1) * 2).Name
    Next k
    Worksheets(arr).Select
    ActiveCell.ClearContents
    ActiveCell.Value = "qufuyizhong"
    Cells.Columns.AutoFit
End Sub

③关于Option Base 1

option base:在模块级别中使用,用来声明数组下标的缺省下界

所以需要将此语句放在模块内开始部分,不能放在中间.验证如下.

源代码:

Option Base 0
Sub 测试用()
    Dim A As Variant, B As String
    A = Array(10, 20, 30)
    B = A(2)
    Debug.Print "数组A的第2个元素值为:" & A(2) '输出30
    ReDim A(5)
    Debug.Print LBound(A)
    Debug.Print UBound(A)
End Sub
输出:

数组A的第2个元素值为:30
 0
 5

Option Base 1
Sub 测试用()
    Dim A As Variant, B As String
    A = Array(10, 20, 30)
    B = A(2)
    Debug.Print "数组A的第2个元素值为:" & A(2) '输出30
    ReDim A(5)
    Debug.Print LBound(A)
    Debug.Print UBound(A)
End Sub
输出:

数组A的第2个元素值为:20
 1
 5
两段代码的UBound(A)的值均为5!!这是怎么回事?借用帮助中一句话解释:如果不显式指定 lower,则数组的下界由 Option Base 语句控制。如果没有 Option Base 语句则下界为 0。也就是说如果如果Option Base 1则从1开始到5,而如果Option Base 0则从0开始到5,这样第1种情况元素有5个,而第2咱情况元素有6个.

那谁不会受Option Base 1的限制呢?由字典创建的数组不会受它的限制,仍然是从0开始,这点一定要注意.

43 Things: Excel, Excel VBA, 循环
BuzzNet: Excel, Excel VBA, 循环
del.icio.us: Excel, Excel VBA, 循环
Flickr: Excel, Excel VBA, 循环
IceRocket: Excel, Excel VBA, 循环
LiveJournal: Excel, Excel VBA, 循环
Technorati: Excel, Excel VBA, 循环
菊子曰 本文用菊子曰发布
posted @ 2011-04-14 13:31  surfacetension  阅读(1268)  评论(0编辑  收藏  举报