汇总模式下的行
关于普通模式和汇总模式下的行,之前说得比较零散,现在来总结一下。
不考虑分组行
Foxtable的代码默认是不考虑分组行的,我们不用担心汇总模式的出现,会影响代码的正常运行,下面我们逐个回顾一下这方面的特性。
首先看看Rows集合,该集合可以返回Table中指定位置的行,例如:
Dim
r As Row = Tables("订单").Rows(2)变量r将等于订单表的第3个数据行,因为行号是从0开始计算的,所以2表示第3个数据行。
如果Table处于汇总模式下,Rows在计算行位置的时候,并不会包括分组行。
Rows的Count属性返回的是数据行的行数,也是排除分组行的,你可以在命令窗口执行下面的代码:
Output.Show(
Tables("订单").Rows.Count)不管订单表是在汇总模式还是普通模式下,上述代码的执行结果都是一样的,因为Count返回的始终是数据行的行数。
因为上述特性,所以下面的代码,不管在何种模式下,都能够正常地运行:
Dim
r As Row用For Each语句遍历Rows集合时,一样是忽略分组行的,所以上面的代码等效于:
For Each
r As Row In Tables("订单").Rows同样,表示选定行位置的Position属性是不考虑分组行的,下面的代码:
Tables(
"订单").Position = 3执行后,不管Table是否处于汇总模式下,都能准确地定位到第4个数据行(行号从0开始计算,所以3表示第4个数据行):
另两个重要的属性,TopPosition和BottomPosition,分别表示选定区域的第一个数据行位置和最后一个数据行的位置,它们和Position属性一样,在计算行位置的时候,是不考虑分组行的。
例如要锁定用户选定的一行或多行:
With
Tables("订单")上述代码,不管是在汇总模式下,还是普通模式下,都能正常地锁定选定的一行或多行,因为代码自动排除了分组行。
但是有一个例外,如果当前选定的是一行,而且这一行恰好是分组行,那么Position、TopPosition、BottomPosition三个属性都返回-1,导致上述代码运行出错。
所以比较“完美”的代码是:
With Tables(
"订单")此外,Table两个用于查找的方法Find和FindRow,其返回的行位置,也是不考虑分组行的;这样我们可以直接用Position定位
于查找到的行。
例如在第一列查找“abc”,不区分大小写,不用完全匹配:
With
CurrentTable
Dim r
As Integer
r
= .Find("abc",
0,
0,
False, False, True)
If r
> - 1
Then '如果找到符合条件的行
.Position
= r '则选择该行
End If
End With
同样不管是在汇总模式下,还是普通模式下,上述的代码都能准确地查找定位,因为Find方法和Position都是不考虑分组行的。
绝大多数时候,我们的代码都是用于处理数据行,而不是分组行的,所以
Foxtable这种自动忽略分组行的特性,能够大大简化我们的编码工作量,我们只需按照常规方式编写代码,无需担心汇总模式的存在,会影响 了代码的正常运行,更无需为兼容汇总模式,而另外编写代码。考虑分组行
尽管实际编写代码的时候,要处理分组行的情况很少,但是我们还是介绍一下用代码处理分组行的方法。
前面提到,在汇总模式下,Rows集合在返回指定位置的行的时候,是不考虑分组行的。
如果要包括分组行,可以给Rows加上一个参数True,例如:
Dim r As Row = Tables("订单").Rows(2, True)
为了测试这种特性,我们首先让订单表进入汇总模式:
然后在命令窗口执行下面的代码:
Dim
r1 As Row = Tables("订单").Rows(2)执行结果:
r1: PD01
r2: CS02 小计
可以看出Rows(2)本来应该返回第三行,但是因为第三行是分组行,所以被排除在外,实际返回的是第四行,也就是第三个数据行。
Rows(2,True)在计算行位置的时候,包括了分组行,所以返回的是第三行数据,尽管第三行是分组行。
Rows的Count属性返回总的行数,同样默认是不包括分组行的,如果要包括分组行,可以给Count加上一个参数True,例如:
Dim
c1 As Integer = Tables("订单").Count在汇总模式下执行上述代码,可以发现c1等于数据行的行数,没有包括分组行;而c2包括了分组行,等于数据行的行数加上分组行的行数,也就是总行数。
Row有两个和汇总模式有关的属性:
名称 | 说明 |
IsGroup | 逻辑型,判断该行是否是汇总模式下的分组行 |
Level | 整数型,返回分组行的级别,总计行的Level属性为-1,第一个分组为0,第二个分组为1,其余依次类推。 |
例如:
If
CurrentTable.Rows(4, True).IsGroup Then显然,在使用IsGroup属性的时候,Rows必须加上参数True,否则返回的永远是数据行,IsGroup的值永远为False,失去了判断的必要性。
下面举个处理分组行的例子,假定需要将分组行数量列的内容,全部除以100:
Dim
r As RowRowSel、TopRow、BottomRow三个属性分别表示当前行位置、选定区第一行位置、选定区最后一行位置;这三个属性和Position、TopPosition、BottomPosition是对应的,不同的是前者在计算位置的时候,是考虑分组行的,而后者是不考虑分组行的。实际上RowSel、TopRow、BottomRow三个属性使用的场合非常有限,通常用于Select和Aggregate两个方法,因为只有这两个方法的参数,是考虑分组行的。
例如,我们利用FindRow找出某个符合条件的行后,可以用Position属性定位到这一行,如果我们希望不仅定位到该行,而且定位到该行的某一列,就必须使用Select方法和RowSel属性
了。
下面的代码,找出订购产品PD01且数量大于100的行,然后定位到该行的日期列:
With CurrentTable
Dim
上面的代码不管是汇总模式,还是普通模式,都能正常查找和定位。
如果直接将代码写为:
With CurrentTable
Dim
在普通模式下,上面的代码没有问题,因为此时Position和RowSel的值是相等的,但是在汇总模式下, 因为Position的值并不一定等于RowSel,所以无法正常定位。
再来看看选定整列的代码,例如选定数量列,之前介绍的代码是:
With
Tables("订单")
Dim c As
Integer=
.Cols("数量").Index
.Select(0,
c, .Rows.Count
- 1,
c)
End With
这个代码是有缺陷的,要保证在汇总模式下也能正常选定这个数量列,代码应该改为:
With Tables(
"订单")Aggregate方法的参数,同样是考虑分组行的,例如要统计当前表选定区域的累积值:
Dim
Sum As Double