ActiveReports工作总结8——用代码控制布局

vs2005+ActiveReportsNet2



承接上节,最终出来的效果是这样的(见图),可以看出布局不能满足我们平时帐票的要求,至少各个TextBox之间不能有间距吧?

<!--[if !vml]-->
<!--[endif]-->

 

希望有的效果:

<!--[if !vml]--><!--[endif]-->

 

最简单的方法,当然是直接在rpt界面上拖动控件,把布局弄好就可以了,这对于简单的报表当然没有问题。需要布局的有:textbox等控件,pageHeader/footer,GroupHeader/Footer,Detail等。

不过这样会有很多问题:

(1),首先,比较容易误操作,尤其是在一些比较精密的帐票中,用户是不会允许哪怕1毫米的误差。

(2),还有,假如直接在rpx上布局的话,会把模版弄的很紧凑,几个控件比较难区分,假如我用代码来布局的话,模版上的布局就只需要大致有个样子,看起来清楚多了。

(3),更重要的是如果有子模版的情况下。SubReport的宽度是很难确定的。主模版上的SubReport的控件宽度应该是和它对应的子模版(subX.rpx)的宽度相等的,但你在画主模版的时候,是确定不了子模版的宽度的(子模版可能会分栏,但ColumnCount我们有时候是不能确定的,要根据传入的数据源确定的)

 

在我们的项目中,一般要求在代码中控制布局(除了一些特殊的特注帐票)。

 

1ok,下面就说说用代码控制布局的具体方法:(字数比较多,可以结合步骤2的代码来看)

(1),创建各个主/子模版,把上面的控件大致布局好(恩,装个样子就可以了)

先处理子模版。无子模版直接到(7)

(2),设置子模版上所有控件的宽度。见注1

(3),对子模版上的所有控件排位置。

(4),设置子模版的groupHeader/groupFooterdetail(包括heightdetailcolumnCount)(用于布局),以及PrintWidth(用于打印出实际的宽度)

(5),子模版创建一个ReadOnly Property ReportWidth(该属性return的就是该模版具体要打印出来的宽度,比如sub1.rpx的宽度是2textbox的总宽度;sub2.rpx的宽度是txtScore的宽度)。

这里也可以把分栏考虑进去,这样的话,sub1的宽度就是2textbox宽度*1;sub2的宽度就是txtScore.width*2

考虑分栏的话,需要注意的是,我们举例的这张帐票,page1sub2只有1列,而page2却有2列,所以宽度不能简单的用txtScore.widh*2。最好这里不考虑分栏,而把分栏放到主模版里的GroupHeader1_Format事件中处理。(不过我们项目中每页的分栏数不同的帐票好像很少有)

本例在sub reportreportwidth中没有考虑分栏。

(6),子模版如果分栏,并且栏数不确定(根据用户的选择,栏数是动态的)。则创建一个public属性RealColumnCount,主模版根据数据源,把真正的ColumnCount传给子模版。

如果字模版分栏,但是是固定的,(比如栏是月份,固定12),大可以把detailcolumnCount设死。

 

处理主模版

(7),在GroupHeader1_format事件中设置子报表。

(8),设置主模版上所有控件的宽度(不包括subReport控件)。见注1

(9),如果有subreport的话,计算它们的宽度。

       1)如果不分栏,宽度就是子模版的ReportWidth

       2)如果分栏,但栏数是静态固定的(比如12),则宽度就是子模版ReportWidth*12

       3)如果分栏,栏数是动态的,但每页都是一样的(比如A,B 2班,任意门科目的成绩,    虽然,科目数目不确定,但每班要么都显示3门,要么都显示4门)

这种情况,先在ReportStart事件中通过数据源算出columnCount,然后宽度就是子模版ReportWidth*columnCount

       4)如果分栏,栏数是动态的,而且每页都可能不一样,比如本例,page1只有1列,page2     却有2列。

这种情况,可以把subReport的宽度放到GroupHeader1_Format事件中去计算,计算方法同3),这样的话,每页都会把subReport的宽度重新算一下。

 

本例的情况属于4)。一般可以用3)的话,尽量不用4)4)由于每个page都要重绘,效率比较低。

(10),对主模版上的所有控件排位置。(如果subReport是在GroupHeader1_format事件中计算的,则,排位置也要在该事件中处理,并不绝对)

(11),设置主模版的PageHeader/PageFooterGroupHeader/GroupFooterDetail。以及整个模版的PrintWidth

 

1:我们项目中对各种用途的控件宽度都有规定的,比如生徒氏名8单位宽度,科目名6单位宽度。具体宽度写在公共类里了,到时调用一下就可以了。

本文就略过这步了,textboxlabel宽度就直接在画面上拉。

 

2,接下去,我们实际来做!

本节的代码由上节的代码修改而成,前面的模版、控件创建,数据源准备等都跳过。

直接看看具体子模版和主模版中的代码(代码中我会用Setp x来指明对应的具体步骤):

 

       1Sub1.vb

<!--[if !vml]-->
<!--[endif]-->

     Private   Sub  sub1_ReportStart( ByVal  sender  As   Object ByVal  e  As  System.EventArgs)  Handles   Me .ReportStart

 

        
' <--------Step (2)---------->

        
' Set contols' width

        
' me.lblID.Width=xxx

        
'

        
'

        
' <--------Step (2)---------->

 

        
' <--------Step (3)---------->

        
' Arrange contols

        
Me .lblID.Left  =   0

        
Me .lblID.Top  =   0

        
Me .lblName.Left  =   Me .lblID.Left  +   Me .lblID.Width

        
Me .lblName.Top  =   Me .lblID.Top

 

        
Me .txtID.Left  =   0

        
Me .txtID.Top  =   0

        
Me .txtName.Left  =   Me .txtID.Left  +   Me .txtID.Width

        
Me .txtName.Top  =   Me .txtName.Top

        
' <--------Step (3)---------->

 

 

        
' <--------Step (4)---------->

        
' Set all sections & PrintWidth

        
Me .PageHeader.Height  =   0

        
Me .GroupHeader1.Height  =   Me .lblID.Height

        
Me .Detail.Height  =   Me .txtID.Height

 

        
' Set columnCount

        
Me .Detail.ColumnCount  =   1

 

        
' Set PrintWidth

        
Me .PrintWidth  =   Me .lblName.Left  +   Me .lblName.Width

        
' <--------Step (4)---------->

    
End Sub

 

    
' <--------Step (5)---------->

    
Public   ReadOnly   Property  ReportWidth()  As   Single

        
Get

            
Return   Me .txtID.Width  +   Me .txtName.Width

        
End   Get

    
End Property

    
' <--------Step (5)---------->


 

2sub2.vb

<!--[if !vml]-->
<!--[endif]-->

需要注意,这里我把detailcolumnCount改成1了,在代码中去修改它。

 

 

 

3)主模版rpt1.vb

<!--[if !vml]-->
<!--[endif]-->

这里的代码有点复杂,主要由于每页都要动态求sub2的宽度,否则GroupHeader1_Format事件中只需要生成子报表,其他布局全可以写在rpt1_ReportStart事件中了。

     Private   Sub  GroupHeader1_Format( ByVal  sender  As   Object ByVal  e  As  System.EventArgs)  Handles  GroupHeader1.Format

        
' <--------Step (7)---------->

        
' subReport1

        
Dim  sub1  As   New  sub1

        
Me .subReport1.Report  =  sub1

        
' 為子報表設置数据源

        
Dim  dvStudent  As  DataView  =   New  DataView( CType ( Me .DataSource, DataSet).Tables( 0 ),  " Class=' "   &   Me .Fields( " Class " ).Value.ToString  &   " ' " "" , DataViewRowState.CurrentRows)

        
Me .subReport1.Report.DataSource  =  dvStudent

 

        
' subReport2

        
Dim  sub2  As   New  sub2

        
Me .subReport2.Report  =  sub2

        
' 為子報表設置数据源

        
Dim  dvScore  As  DataView  =   New  DataView( CType ( Me .DataSource, DataSet).Tables( 1 ),  " Class=' "   &   Me .Fields( " Class " ).Value.ToString  &   " ' " "" , DataViewRowState.CurrentRows)

 

        
With   CType ( Me .subReport2.Report, sub2)

            .DataSource 
=  dvScore

            
' Set subReport's ColumnCount

            .RealColumnCount 
=   CInt (dvScore.Count  /  dvStudent.Count)

        
End   With

        
' <--------Step (7)---------->

 

 

        
' <--------Step (9)---------->

        
Me .subReport1.Width  =  sub1.ReportWidth

        
Me .subReport2.Width  =  sub2.ReportWidth  *   CInt (dvScore.Count  /  dvStudent.Count)

        
' <--------Step (9)---------->

 

 

        
' <--------Step (10)---------->

        
Me .subReport2.Left  =   Me .subReport1.Left  +   Me .subReport1.Width

        
Me .subReport2.Top  =   Me .subReport1.Top

        
' <--------Step (10)---------->

 

 

        
' <--------Step (11)---------->

        
' Set PrintWidth

        
Me .PrintWidth  =   Me .subReport2.Left  +   Me .subReport2.Width

        
' <--------Step (11)---------->

    
End Sub

 

    
Private   Sub  rpt1_ReportStart( ByVal  sender  As   Object ByVal  e  As  System.EventArgs)  Handles   Me .ReportStart

        
' <--------Step (8)---------->

        
' Set contols' width

        
' me.lblClass.Width=xxx

        
'

        
'

        
' <--------Step (8)---------->

 

 

        
' <--------Step (10)---------->

        
' Arrange Controls.

        
Me .lblClass.Left  =   0.5

        
Me .lblClass.Top  =   0.5

        
Me .txtClassNo.Left  =   Me .lblClass.Left  +   Me .lblClass.Width

        
Me .txtClassNo.Top  =   Me .lblClass.Top

 

        
Me .subReport1.Left  =   Me .lblClass.Left

        
Me .subReport1.Top  =   Me .lblClass.Top  +   Me .lblClass.Height

        
' <--------Step (10)---------->

 

 

        
' <--------Step (11)---------->

        
' Set all sections & PrintWidth

        
Me .PageHeader.Height  =   Me .Label1.Height

        
Me .Detail.Height  =   0

        
' <--------Step (11)---------->

End Sub


 

 

3,最终的效果。

<!--[if !vml]-->
<!--[endif]-->

<!--[if !vml]-->


    Private   Sub  sub2_ReportStart( ByVal  sender  As   Object ByVal  e  As  System.EventArgs)  Handles   Me .ReportStart

        
' <--------Step (2)---------->

        
' Set contols' width

        
' me.lblSubject.Width=xxx

        
'

        
'

        
' <--------Step (2)---------->

 

        
' <--------Step (3)---------->

        
' Arrange contols

        
Me .lblSubject.Left  =   0

        
Me .lblSubject.Top  =   0

 

        
Me .txtScore.Left  =   0

        
Me .txtScore.Top  =   0

        
' <--------Step (3)---------->

 

 

        
' <--------Step (4)---------->

        
' Set all sections & PrintWidth

        
Me .PageHeader.Height  =   0

        
Me .GroupHeader1.Height  =   Me .lblSubject.Height

        
Me .Detail.Height  =   Me .txtScore.Height

 

        
' Set columnCount

        
Me .Detail.ColumnCount  =   Me ._realColumnCount

 

        
' Set PrintWidth

        
Me .PrintWidth  =  ( Me .txtScore.Left  +   Me .txtScore.Width)  *   Me ._realColumnCount

        
' <--------Step (4)---------->

    
End Sub

 

    
' <--------Step (5)---------->

    
Public   ReadOnly   Property  ReportWidth()  As   Single

        
Get

            
Return   Me .txtScore.Width

        
End   Get

    
End Property

 

    
' <--------Step (6)---------->

    
Private  _realColumnCount  As  Int32  =   1

    
Public   Property  RealColumnCount()  As  Int32

        
Get

            
Return  _realColumnCount

        
End   Get

        
Set ( ByVal  value  As  Int32)

            
Me ._realColumnCount  =  value

        
End   Set

    
End Property

' <--------Step (6)---------->
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值