












完整的一张成绩一览帐票
环境:
vs2005+ActiveReportsNet2
本节代码下载:https://files.cnblogs.com/batoosai/SimpleExample10.rar
学习了前面的一些基础,我们来实际开发一张帐票吧。
1,帐票式样

2,帐票说明:
1,抽出条件:
1-1班级:必選,多選
1-2科目:必選, 多選
2,用紙サイズ: A4 横
3,改頁条件:班级
4,印刷順序:行:生徒出席番号升排序
列:科目順位
4,如果某学生某subject没有成绩的话,也要显示该数据(只是把格子留空)
分析下帐票,我们应该用3个子模版(如下图,其中Sub3不需要取数,老师手动填)

3,好,我们项目一般的架构如下:

在我们的示例中,方便起见,就用简单的3层架构吧,当中的web service去掉。创建Project如图:

1)表示层:Form,ARTemplate
2)业务逻辑层:BR
3)数据层:DA
4,数据库如下:

具体数据表的数据:
1)Class
|
Class |
|||
|
ClassID |
ClassName |
TeacherName |
DisplayOrder |
|
1 |
A班 |
Tony Gong |
1 |
|
2 |
B班 |
Tony Wang |
2 |
|
3 |
C班 |
Tony Li |
3 |
2)Student
|
Student |
|||
|
StudentID |
ClassID |
No |
Name |
|
11 |
1 |
1 |
Tony |
|
12 |
1 |
2 |
Zhu |
|
13 |
1 |
3 |
Li |
|
14 |
1 |
4 |
Zhang |
|
15 |
1 |
5 |
Zha |
|
16 |
1 |
6 |
Sun |
|
21 |
2 |
1 |
Wang |
|
22 |
2 |
2 |
Gong |
|
23 |
2 |
3 |
Tian |
|
24 |
2 |
4 |
Su |
|
25 |
2 |
5 |
Xiao |
|
31 |
3 |
1 |
Xu |
|
32 |
3 |
2 |
Liu |
|
33 |
3 |
3 |
Tom |
|
34 |
3 |
4 |
Mary |
3)Subject
|
Subject |
||
|
SubjectID |
SubjectName |
DisplayOrder |
|
1 |
古典 |
1 |
|
2 |
現代文 |
2 |
|
3 |
語文 |
3 |
4)Score
|
Score |
||||
|
ScoreID |
StudentID |
SubjectID |
Score |
GradeOrder |
|
1 |
11 |
1 |
70 |
11 |
|
2 |
11 |
2 |
75 |
23 |
|
3 |
11 |
3 |
55 |
1 |
|
4 |
12 |
1 |
6 |
15 |
|
5 |
12 |
2 |
77 |
6 |
|
6 |
13 |
1 |
8 |
6 |
|
7 |
13 |
2 |
77 |
7 |
|
8 |
13 |
3 |
66 |
8 |
|
9 |
14 |
1 |
55 |
9 |
|
10 |
14 |
3 |
44 |
10 |
|
11 |
15 |
2 |
32 |
11 |
|
12 |
16 |
3 |
100 |
12 |
|
13 |
21 |
1 |
11 |
13 |
|
14 |
21 |
2 |
14 |
14 |
|
15 |
21 |
3 |
15 |
1 |
|
16 |
22 |
1 |
16 |
2 |
|
17 |
22 |
2 |
76 |
3 |
|
18 |
22 |
3 |
18 |
4 |
|
19 |
23 |
1 |
99 |
5 |
|
20 |
23 |
3 |
89 |
6 |
|
21 |
24 |
1 |
21 |
7 |
|
22 |
25 |
1 |
44 |
8 |
|
23 |
31 |
1 |
23 |
9 |
|
24 |
31 |
2 |
24 |
10 |
|
25 |
32 |
1 |
25 |
1 |
|
26 |
32 |
3 |
26 |
2 |
|
27 |
33 |
1 |
27 |
3 |
|
28 |
34 |
1 |
28 |
4 |
|
29 |
34 |
2 |
29 |
5 |
|
30 |
34 |
3 |
30 |
6 |
5,ok,开工,先add 如下文件

其中Form中
frmScore让用户选择抽出条件
frmShowAR用来显示report
6,在form上放2个多选的条件控件,Class和Subject。
实际项目中,这2个控件的内容应该取数据表里的值。我这里方便起见,直接把值写死在控件上。

btnPreview的click事件如下:
Private Sub btnPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPreview.ClickIf Me.listClass.SelectedIndex = -1 OrElse Me.listSubject.SelectedIndex = -1 ThenReturnEnd If'Get the Parameter
Dim classID As String = ""Dim subjectID As String = ""For index As Int32 = 0 To Me.listClass.SelectedIndices.Count - 1
classID
&= Me.listClass.SelectedIndices(index) + 1 & ","NextFor index As Int32 = 0 To Me.listSubject.SelectedIndices.Count - 1subjectID
&= Me.listSubject.SelectedIndices(index) + 1 & ","NextclassID
= classID.TrimEnd(Convert.ToChar(","))subjectID
= subjectID.TrimEnd(Convert.ToChar(","))'Send parameters to the BR and get the dataset.frm.Show()
End Sub7,br层,由于业务太简单了,代码很简单。
Public Function GetData(ByVal classID As String, ByVal subjectID As String) As DataSetTry' 創建DA
Dim objDA As New DA.daScore()Dim ds As DataSet = objDA.GetData(classID, subjectID)' 返回値
Return dsCatch ex As Exception' 抛出異常
Throw exEnd TryEnd Function
8, DA层,根据参数执行sql语句,返回结果Dataset
DA的任务,是根据参数,作select语句,得出2张table,放到ds中return。
假设Class选了”B,C”,Subject选了”古典,现代文”
其中table1(用于Sub1和主模版)数据应该如下:(9条记录)
|
Query1 |
|||||||
|
Class.ClassID |
ClassName |
TeacherName |
DisplayOrder |
StudentID |
Student.ClassID |
No |
Name |
|
2 |
B班 |
Tony Wang |
2 |
21 |
2 |
1 |
Wang |
|
2 |
B班 |
Tony Wang |
2 |
22 |
2 |
2 |
Gong |
|
2 |
B班 |
Tony Wang |
2 |
23 |
2 |
3 |
Tian |
|
2 |
B班 |
Tony Wang |
2 |
24 |
2 |
4 |
Su |
|
2 |
B班 |
Tony Wang |
2 |
25 |
2 |
5 |
Xiao |
|
3 |
C班 |
Tony Li |
3 |
31 |
3 |
1 |
Xu |
|
3 |
C班 |
Tony Li |
3 |
32 |
3 |
2 |
Liu |
|
3 |
C班 |
Tony Li |
3 |
33 |
3 |
3 |
Tom |
|
3 |
C班 |
Tony Li |
3 |
34 |
3 |
4 |
Mary |
table2(用于Sub2)数据应该这样做:
9条生徒 * 2门科目,然后left join Score的内容,最终得到18条记录(假如某人某科没成绩的话,该字段也会显示出来,只是留空而已)。

PS:由于Access的Left join 俺实在是搞不懂,没法做left join,所以只能把Score的纪录填满,然后用普通查询。
再PS:Access的参数化查询我也搞不太清楚,所以代码中直接把”@classid”等替换成字符串了。
最后的PS:假如是mssql的话,sub2的查询语句大概如下:
Select * from student,class
cross join Subject
left join score
on score.subjectID=Subject.SubjectID
and score.StudentID=student.StudentID
Where s.ClassID=c.ClassID
And c.ClassID in (@ClassID)

Sub3就不需要查寻了。
9,frmShowAR接收到数据源,并显示帐票
Public Class frmShowARSub New(ByVal ds As DataSet)Me.finalDS = ds' 此调用是 Windows 窗体设计器所必需的。
InitializeComponent()' 在 InitializeComponent() 调用之后添加任何初始化。
End SubPrivate finalDS As DataSetPrivate Sub frmShowAR_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.LoadDim rpt As New ARTemplate.rptScore
rpt.DataSource
= finalDSrpt.DataMember
= finalDS.Tables(0).TableName'A4 Landscaperpt.PageSettings.Orientation
= DataDynamics.ActiveReports.Document.PageOrientation.Landscaperpt.Run()
Me.Viewer1.Document = rpt.DocumentEnd SubEnd Class10,主模版和子模版主要属性及代码(完整的请看下载的代码)
1),主模版

GroupHeader1:DataFied=”ClassID”
NewPage=”Before”
txtClassNo: DataField=”ClassName”
txtTeacher: DataField=”TeacherName”
代码:
Report_start中布局代码
Private Sub rpt1_ReportStart(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ReportStart'<--------Step (1)---------->
'Set contols' width
'me.lblClass.Width=xxx
'
'
'<--------Step (1)---------->
'<--------Step (2)---------->
'Arrange Controls.
Me.lblYear.Left = 0.5Me.lblYear.Top = 0.5Me.txtClassNo.Left = Me.lblYear.LeftMe.txtClassNo.Top = Me.lblYear.Top + Me.lblYear.HeightMe.Label3.Left = Me.txtClassNo.Left + Me.txtClassNo.Width * 2Me.Label3.Top = Me.txtClassNo.TopMe.txtTeacher.Left = Me.Label3.Left + Me.Label3.WidthMe.txtTeacher.Top = Me.Label3.Top'<--------Step (2)---------->
'<--------Step (3)---------->
Dim sub1 As New sub1Me.subReport1.Width = sub1.ReportWidthDim sub2 As New sub2With CType(Me.DataSource, DataSet)Me.subReport2.Width = sub2.ReportWidth * CInt(.Tables(1).Rows.Count / .Tables(0).Rows.Count)End WithDim sub3 As New sub3Me.subReport3.Width = sub3.reportWidth'<--------Step (3)---------->
'<--------Step (4)---------->
Me.subReport1.Left = Me.txtClassNo.LeftMe.subReport1.Top = Me.txtClassNo.Top + Me.txtClassNo.HeightMe.subReport2.Left = Me.subReport1.Left + Me.subReport1.WidthMe.subReport2.Top = Me.subReport1.TopMe.subReport3.Left = Me.subReport2.Left + Me.subReport2.WidthMe.subReport3.Top = Me.subReport1.Top'<--------Step (4)---------->
'<--------Step (5)---------->
'Set all sections & PrintWidth
Me.PageHeader.Height = Me.TextBox2.HeightMe.Detail.Height = 0'<--------Step (5)---------->
'<--------Step (6)---------->
'Set PrintWidth
Dim realWidth As Single = Me.subReport3.Left + Me.subReport3.WidthDim defaultWidth As SingleIf PageSettings.Orientation = PageOrientation.Portrait Then
defaultWidth
= PageSettings.PaperWidth - PageSettings.Margins.Left - PageSettings.Margins.RightElsedefaultWidth
= PageSettings.PaperHeight - PageSettings.Margins.Left - PageSettings.Margins.RightEnd IfIf realWidth > defaultWidth ThenMe.PrintWidth = realWidthElseMe.PrintWidth = defaultWidthEnd If'<--------Step (6)---------->Detail_Format里的生成子模版的代码:
Private Sub GroupHeader1_Format(ByVal sender As Object, ByVal e As System.EventArgs) Handles GroupHeader1.Format'subReport1
Dim sub1 As New sub1Me.subReport1.Report = sub1'為子報表設置数据源
Dim dvStudent As DataView = New DataView(CType(Me.DataSource, DataSet).Tables(0), "ClassID='" & Me.Fields("ClassID").Value.ToString & "'", "", DataViewRowState.CurrentRows)Me.subReport1.Report.DataSource = dvStudent'subReport2
Dim sub2 As New sub2Me.subReport2.Report = sub2'為子報表設置数据源
Dim dvScore As DataView = New DataView(CType(Me.DataSource, DataSet).Tables(1), "ClassID='" & Me.Fields("ClassID").Value.ToString & "'", "", DataViewRowState.CurrentRows)With CType(Me.subReport2.Report, sub2)
.DataSource
= dvScore'Set subReport's ColumnCount2),Sub1

txtID:DataField=”No”
txtName:DataField=”Name”
3),Sub2

GroupHeader1:DataField=” SubjectID”
NewPage=”Before”
lblSubject:DataField=”SubjectName”
txtScore:Datafield=”Score”
txtOrder:Datafield=”gradeOrder”
4),Sub3

11,最终效果,比较粗糙,大家自己改进吧。

此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。