以文本方式查看主题

-  Foxtable(狐表)  (http://foxtable.net/bbs/index.asp)
--  专家坐堂  (http://foxtable.net/bbs/list.asp?boardid=2)
----  6月7日更新,Table新增两个属性。  (http://foxtable.net/bbs/dispbbs.asp?boardid=2&id=3058)

--  作者:狐狸爸爸
--  发布时间:2009/6/7 15:37:00
--  6月7日更新,Table新增两个属性。

1、票据设计支持Painter了
2、Table的Find方法的返回值,不再考虑分组行,这样可以直接用Position属性定位
3、给Table增加了两个重要属性:TopPosition和BottomPositiom
4、一些细节改进,例如图片和文件管理器,可以一次加入多个文件,Datalist可以多选。

处理选定的多行


如果我们选定了一行数据,那么通过Position属性可以得到选定行的位置,通过Current属性,可以直接获得选定的行。

如果我们选定了多行,又该如何获得所有选定行的位置,以及选定的那些行呢?

FoxTable提供了两个属性,用于批量处理选定的多行

属性名 说明
TopPosition 返回选定区域的第一个数据行的位置,如果只选定一行,返回值和Position属性相同。
BottomPosition 返回选型区域的最后一个数据行的位置,如果只选定一行,返回值和Position属性相同。


和Position属性一样,这两个属性在计算的时候,均不包括分组行,下图清晰地说明了这种特性。



此主题相关图片如下:1041.gif
按此在新窗口浏览图片

 

但是也稍有不同,如果选定区域的第一行是分组行,TopPosition会向下寻找,直到找到一个不是分组行的数据行,然后返回此行的位置;
同样,如果选定区域的最后一行是分组行,
BottomPosition会向上寻找,直到找到第一个不是分组行的数据行,然后返回此行的的位置。
除非只选定了一行,而且此行恰好是分组行,
TopPosition和BottomPosition属性才会返回-1。
而Position属性不具备上述特性,只要选定的是分组行,就直接返回-1。

下图可以很好地说明这种特性:



此主题相关图片如下:1042.gif
按此在新窗口浏览图片
 

这种忽略分组行的处理方式,能大大减少编码的复杂程度,因为我们的代码通常只是处理数据行的,对于分组行是要忽略的。


示例


锁定用户选定的行:


With
Tables("订单")
    For
i as Integer = .TopPosition To .BottomPosition
        .Rows(i).Locked =
True
    Next
End
With


上述代码,不管是在汇总模式下,还是普通模式下,都能正常地锁定选定的一行或多行,因为代码能够自动排除分组行。
但是如果当前选定的是一行,而且这一行恰好是分组行,那么Position、
TopPosition、BottomPosition三个属性都返回-1,导致上述代码运行出错。
所以比较完美的代码是:


With Tables(
"订单")
    If .
TopPosition > -1 Then \'如果选定区域包括数据行
        For
i as Integer = .TopPosition To .BottomPosition
            .
Rows(i).Locked
= true
        Next
    End If
End With


注意我们根据TopPosition是否大于-1,来判断选定区域是否包括分组行,其理由前面已经讲述,就不再重复。

[此贴子已经被作者于2009-6-8 8:21:32编辑过]

--  作者:狐狸爸爸
--  发布时间:2009/6/7 15:41:00
--  

汇总模式下的行


关于普通模式和汇总模式下的行,之前说得比较零散,现在来总结一下。


不考虑分组行


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
With Tables(
"订单")
    For
i As Integer = 0 To .Rows.Count - 1
        r = .Rows(i)

        If
r("数量") > 200 And r("日期") >= #1/26/1999#
Then
            r(
"折扣") = 0.13
       
End If
    Next
End
With


用For Each语句遍历Rows集合时,一样是忽略分组行的,所以上面的代码等效于:


For Each
r As Row In Tables("订单").Rows
    If
r("数量") > 200 And r("日期") >= #1/26/1999# Then
        r
("折扣") = 0.13

    End If
Next


同样,表示选定行位置的Position属性是不考虑分组行的,下面的代码:


Tables(
"订单").Position = 3


执行后,不管Table是否处于汇总模式下,都能准确地定位到第4个数据行(行号从0开始计算,所以3表示第4个数据行):



此主题相关图片如下:1045.gif
按此在新窗口浏览图片


另两个重要的属性,TopPosition和BottomPosition,分别表示选定区域的第一个数据行位置和最后一个数据行的位置,它们和Position属性一样,在计算行位置的时候,是不考虑分组行的。
例如要锁定用户选定的一行或多行:


With
Tables("订单")
    For
i as Integer = .TopPosition To .BottomPosition
        .Rows(i).Locked =
True
    Next
End
With


上述代码,不管是在汇总模式下,还是普通模式下,都能正常地锁定选定的一行或多行,因为代码自动排除了分组行。
但是有一个例外,如果当前选定的是一行,而且这一行恰好是分组行,那么Position、TopPosition、BottomPosition三个属性都返回-1,导致上述代码运行出错。
所以比较“完美”的代码是:


With Tables(
"订单")
    If .
TopPosition > -1 Then \'如果选定区域包括数据行
        For
i as Integer = .TopPosition To .BottomPosition
            .
Rows(i).Locked
= true
        Next
    End If
End With


此外,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这种自动忽略分组行的特性,能够大大简化我们的编码工作量,我们只需按照常规方式编写代码,无需担心汇总模式的存在,会影响了代码的正常运行,更无需为兼容汇总模式,而另外编写代码。


 

[此贴子已经被作者于2009-6-7 15:47:49编辑过]

--  作者:狐狸爸爸
--  发布时间:2009/6/7 15:42:00
--  
考虑分组行


尽管实际编写代码的时候,要处理分组行的情况很少,但是我们还是介绍一下用代码处理分组行的方法。

前面提到,在汇总模式下,Rows集合在返回指定位置的行的时候,是不考虑分组行的。
如果要包括分组行,可以给Rows加上一个参数True,例如:


Dim
r As Row = Tables("订单").Rows(2, True)


为了测试这种特性,我们首先让订单表进入汇总模式:



此主题相关图片如下:1040.gif
按此在新窗口浏览图片


然后在命令窗口执行下面的代码:


Dim
r1 As Row = Tables("订单").Rows(2)
Dim
r2 As Row = Tables("订单").Rows(2,True)
Output.Show(
"r1: " & r1("产品"))
Output.Show(
"r2: " & r2("产品"
))


执行结果:


r1: PD01
r2: CS02 小计


可以看出
Rows(2)本来应该返回第三行,但是因为第三行是分组行,所以被排除在外,实际返回的是第四行,也就是第三个数据行。
Rows(2,True)在计算行位置的时候,包括了分组行,所以返回的是第三行数据,尽管第三行是分组行。


Rows的Count属性返回总的行数,同样默认是不包括分组行的,如果要包括分组行,可以给Count加上一个参数True,例如:


Dim
c1 As Integer = Tables("订单").Count
Dim
c2 As Integer = Tables("订单").Count(True)
Output.show(
"c1 = " & c1)
Output.show(
"c2 = "
& c2)


在汇总模式下执行上述代码,可以发现c1等于数据行的行数,没有包括分组行;而c2包括了分组行,等于数据行的行数加上分组行的行数,也就是总行数。


Row有一个IsGroup属性,可以判断指定位置的行是否是分组行,例如:


If
CurrentTable.Rows(4, True).IsGroup Then
    Messagebox.Show(
"第五行是分组行!")
End
If


显然,在使用IsGroup属性的时候,Rows必须加上参数True,否则返回的永远是数据行,IsGroup的值永远为False,失去了判断的必要性。


下面举个处理分组行的例子,假定需要将分组行数量列的内容,全部除以100:


Dim
r As Row
With
Tables("订单")
    For i As Integer = 0 To .Rows.Count(True) - 1 \'Count加上参数True
       
r = .Rows(i,True) \'Rows也需要加上参数True
       
If r.IsGroup Then \'如果是分组行
            r(
"数量") = r("数量") /100
       
End If
    Next
End
With


RowSel、TopRow、BottomRow三个属性分表表示当前行位置、选定区第一行位置、选定区最后一行位置;这三个属性和Position、TopPosition、BottomPosition是对应的,不同的是前者前者在计算位置的时候,是考虑分组行的,而后者是不考虑分组行的。实际上RowSel、TopRow、BottomRow三个属性使用的场合非常有限,通常用于Select和Aggregate两个方法,因为只有这两个方法的参数,是考虑分组行的。


例如,我们利用FindRow找出某个符合条件的行后,可以用Position属性定位到这一行,如果我们希望不仅定位到该行,而且定位到该行的某一列,就必须使用Select方法和RowSel属性了。
下面的代码,找出订购产品PD01且数量大于100的行,然后定位到该行的日期列:


With CurrentTable
    Dim
r As Integer
   
Dim p As Integer = .Cols("日期").Index \'获得日期列的位置
    r = .FindRow("产品 = \'PD02\' And 数量 > 100", 0, False)
    If
r > - 1 Then \'如果找到符合条件的行
        .
Position = r \'则选择该行
        .
Select(.RowSel, p)
   
End If

End With


上面的代码不管是汇总模式,还是普通模式,都能正常查找和定位。
如果直接将代码写为:


With CurrentTable
    Dim
r As Integer
   
Dim p As Integer = .Cols("日期").Index \'获得日期列的位置
   
r = .FindRow("产品 = \'PD02\' And 数量 > 100", 0, False)
    If
r > - 1 Then \'如果找到符合条件的行
        .
Select(.Position, p)
   
End If
End With


在普通模式下,上面的代码没有问题,因为此时Positon和RowSel的值是相等的,但是在汇总模式下,因为Position的值并不一定等于RowSel,所以无法正常定位。

再来看看选定整列的代码,例如选定数量列,之前介绍的代码是:


With Tables
("订单")
   
Dim c As Integer= .Cols("数量").Index

    .
Select(0, c, .Rows.Count - 1, c)
End With


这个代码是有缺陷的,要保证在汇总模式下也能正常选定这个数量列,代码应该改为:


With Tables(
"订单")
    Dim
c As Integer= .Cols("数量").Index
    .
Select(0, c, .Rows.Count(True) - 1
, c)
End With


Aggregate方法的参数,同样是考虑分组行的,
例如要统计当前表选定区域的累积值:


Dim
Sum As Double
With
CurrentTable
    Sum =
.Aggregate(AggregateEnum.Sum, .TopRow, .LeftCol, .BottomRow, .RightCol)
End
With
OutPut.Show(Sum)

[此贴子已经被作者于2009-6-7 15:45:07编辑过]

--  作者:gamtings
--  发布时间:2009/6/7 17:16:00
--  
顶,又有更新了!抢个沙发坐坐!!!
--  作者:长今
--  发布时间:2009/6/7 17:21:00
--  
图片点击可在新窗口打开查看
--  作者:yangming
--  发布时间:2009/6/7 17:28:00
--  

更新了!


--  作者:hx9617
--  发布时间:2009/6/7 18:39:00
--  

呵呵 每天都会来查看是否更新,变成了一种习惯,当有一天,正式版发行了,不再频繁更新了,是不是会很寂寞……


--  作者:易狐
--  发布时间:2009/6/7 19:05:00
--  
收到!
--  作者:菜鸟foxtable
--  发布时间:2009/6/7 19:47:00
--  
强烈顶起。
--  作者:ylm
--  发布时间:2009/6/7 21:12:00
--  

顶起!图片点击可在新窗口打开查看