一个可能最复杂的FastReport报表,大家一起来解决!!!

msony 2008-04-06 03:45:57
这是我使用FastReprot五六年来遇到的最难的一个报表!欢迎大家来讨论!!
我有一个学校报刊订阅的数据表,主要是用来记录每个班级每个学生订阅不同报刊情况,如下:
班级名称 报刊名称 订阅期限 金额 数量 学生姓名 学校名称
601 中国卡通(故事版) 半年 36 1 伊晰 新建区小学
601 天天数学 半年 24 1 黄胜旺 新建区小学
601 天天语文 半年 29 1 王婧 新建区小学
601 小记者 半年 30 1 邵韵 新建区小学
601 小记者 半年 30 1 李佳欣 新建区小学
601 少年文摘 半年 48 1 王娟 新建区小学
601 少年文摘 半年 48 1 严小青 新建区小学
601 少年文摘 半年 48 1 路瑶 新建区小学
601 我们爱科学(中高年级) 半年 50 1 黄河森 新建区小学
601 我们爱科学(中高年级) 半年 50 1 吕邦衍 新建区小学
601 读书与作文 半年 27 1 伊晰 新建区小学
601 读书与作文 半年 27 1 王俐 新建区小学
601 读书与作文 半年 27 1 邵韵 新建区小学
601 趣味科学 半年 40 1 吕邦衍 新建区小学
602 天天数学 半年 24 1 徐盈 新建区小学
602 天天语文 半年 29 1 徐盈 新建区小学
602 小记者 半年 30 1 蔡浩能 新建区小学
602 红树林 半年 36 1 吴子贤 新建区小学
602 读书与作文 半年 27 1 杨禀 新建区小学
教导处 儿童文学 半年 66 1 陈主任 新建区小学
教导处 儿童文学 半年 66 1 叶主任 新建区小学
教导处 少年文摘 半年 48 1 叶主任 新建区小学
教导处 我们爱科学(中高年级) 半年 50 1 陈主任 新建区小学

现在需要制作成如下报表,我画了一份样式,大家请看:


队报队刊统计表
学校:新建区小学 班级:602 老师: 电话: ------------------------------------------------------------------------------------------------------------------------------------------
报 刊 名 称 订阅期限 订阅价格 学 生 姓 名 报刊合计
天天数学 半年 24 | 徐盈 | 张三 |李四 | 五五| 赵六 | 徐七|沈十| |
天天数学 半年 24 | 黄力 | 吴 | | | | | | | |
天天语文 半年 29 徐盈 小记者 半年 30 蔡浩能 红树林 半年 36 吴子贤
读书与作文 半年 27 杨禀 ------------------------------------------------------------------------------------------------------------------------------------------
合计: 5 金额: 146
-------------------------------------------------------------------------------------------------------------------------------------
队报队刊统计表

学校:新建区小学 班级:教导处 老师: 电话: ------------------------------------------------------------------------------------------------------------------------------------------
报 刊 名 称 订阅期限 订阅价格 学 生 姓 名 报刊合计
儿童文学 半年 66 陈主任 陈主任 陈主任
少年文摘 半年 48 叶主任 叶主任 叶主任
我们爱科学(中高年级)半年 50 陈主任 陈主任 陈主任 ------------------------------------------------------------------------------------------------------------------------------------------
合计: 4 金额: 230
-------------------------------------------------------------------------------------------------------------------------------------
总计: 119 金额: 4618

不知道大家看明白没有,其实这就是一个分组报表,但是它有一系列这这样的问题如下,
1、就是每一个学生显示的方式它是横向(如果是竖排可能好办些),但是就是要横向显示。
2、而且要求是智能一点的,就是当横向满了七个显示不下去时,就可自动另起一行,继续显示!
3、一般使用纸张大小后,每页打印的时候不要将一个班级在二页中显示,就是说能将每一个班级的表格放在一页中显示,不要分成二页。

...全文
222 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
GDTOPONE 2008-04-06
  • 打赏
  • 举报
回复
用DELPHI方式的实现:
1.新建一个表,表名(TBB),数据结构如下:
ly 文本型(用来记录由学校名称加上班级名称组成的内容)
报型名称
订阅期限
金额(即报刊的价钱)
学生姓名
报刊合计(即有多少人订了这个报刊)
2.delphi中用三个adoquery控件,设置如下:

adoquery1的SQL.TEXT是:select [学校名称],[班级名称],[报刊名称],[订阅期限],[金额] from tb GROUP BY [学校名称],[班级名称],[报刊名称],[订阅期限],[金额]

adoquery2的SQL.TEXT是:select [学校名称],[班级名称],[报刊名称],[订阅期限],[金额],[学生姓名] from
tb where [学校名称]=:a
and [班级名称]=:b
and [报刊名称]=:c
and [订阅期限]=:d
and [金额]=:e
GROUP BY [学校名称],[班级名称],[报刊名称],[订阅期限],[金额],[学生姓名]

adoquery3的SQL.TEXT是:select * from tbb

3.delphi 的代码:


procedure TForm1.Button1Click(Sender: TObject);
var
str:string;
sname:widestring;
begin
with adoquery1 do begin
if not Active then Active:=true;
if not IsEmpty then begin {有资料的情况下}
adoquery3.Open;
while not eof do begin
with adoquery2 do begin
Close;
with Parameters do begin
ParamValues['a']:=adoquery1.FieldValues['学校名称'];
ParamValues['b']:=adoquery1.FieldValues['班级名称'];
ParamValues['c']:=adoquery1.FieldValues['报刊名称'];
ParamValues['d']:=adoquery1.FieldValues['订阅期限'];
ParamValues['e']:=adoquery1.FieldValues['金额'];
end;
open;
if not isempty then begin
str:='学校:'+' '+FieldValues['学校名称']+' '+'班级:'+FieldValues['班级名称'];
while not eof do begin
sname:=sname+widestring(FieldValues['学生姓名'])+widestring(',');
next;
end;
First;
adoquery3.Append;
adoquery3.FieldValues['ly']:=str;
adoquery3.FieldValues['报刊名称']:=FieldValues['报刊名称'];
adoquery3.FieldValues['订阅期限']:=FieldValues['订阅期限'];
adoquery3.FieldValues['金额']:=FieldValues['金额'];
sname:=copy(sname,1,length(WideString(sname))-1);
adoquery3.FieldValues['学生姓名']:=sname;
adoquery3.FieldValues['报刊合计']:=RecordCount;
adoquery3.Post;
sname:='';
end;
close;
end;
next;
end;
end;
end;
end;


4:报表的数据源连接新表tbb.
建议报表中的姓名还要用表格形式,用如:邵韵,王俐,伊晰,一但人数太多时,表格太多一张纸显示不了这么多,而邵韵,王俐,伊晰这样可以折行显示.


msony 2008-04-06
  • 打赏
  • 举报
回复
很感谢你的回答,我理解你的意思,你是将SQL语句将表进行转换后再进行Fastreport 报表的制作,这样做报表时就不用考虑这么复杂了,但我用的Access数据表,有些语句无法使用!能改动些代码实现吗??
GDTOPONE 2008-04-06
  • 打赏
  • 举报
回复
不好意思,刚重新看了楼主的意思,以上的代码还能实现楼主的要求,更改以下代码可以实现了:
分为三步:
第一:在你的表中建一个字段名为:ly,期实就是用来记录:'学校:'+' '+[学校名称]+' '+'班级:'+[班级名称],作为FastReprot的依据
到时你在FastReprot里就用字段LY为分条件.


第二步:在SQL里建立一个自定义函数:

CREATE FUNCTION dbo.f_str(@id nvarchar(50),@lvname nvarchar(50),@vvname nvarchar(50))

RETURNS varchar(8000)

AS

BEGIN

DECLARE @r varchar(8000)

SET @r = ''

SELECT @r = @r + ',' + [学生姓名]

FROM tb------------------------------------注意你的表名及相关字段

WHERE ly=@id and [报刊名称]=@lvname and [班级名称]=@vvname

RETURN STUFF(@r, 1, 1, '')
END


第三:DELPHI入面的代码:

with adoquery1 do begin
close;
sql.Text:='update tb set ly=''学校:''+'' ''+[学校名称]+'' ''+''班级:''+[班级名称]';
ExecSQL;
close;
sql.Text:='select ly,[报刊名称],[订阅期限],[金额],dbo.f_str(ly,[报刊名称],[班级名称]) as ''学生姓名'',count(*) as ''报刊合计'' from tb GROUP BY ly,[报刊名称],[订阅期限],[金额],dbo.f_str(ly,[报刊名称],[班级名称])';
open;
end;


第四:adoquery1最后得到的数据集以下:

/*

学校: 新建区小学 班级:601 读书与作文 半年 27.0 伊晰,王俐,邵韵 3
学校: 新建区小学 班级:601 趣味科学 半年 40.0 吕邦衍 1
学校: 新建区小学 班级:601 少年文摘 半年 48.0 王娟,严小青,路瑶 3
学校: 新建区小学 班级:601 天天数学 半年 24.0 黄胜旺 1
学校: 新建区小学 班级:601 天天语文 半年 29.0 王婧 1
学校: 新建区小学 班级:601 我们爱科学(中高年级) 半年 50.0 黄河森,吕邦衍 2
学校: 新建区小学 班级:601 小记者 半年 30.0 邵韵,李佳欣 2
学校: 新建区小学 班级:601 中国卡通(故事版) 半年 36.0 伊晰 1
学校: 新建区小学 班级:602 读书与作文 半年 27.0 杨禀 1
学校: 新建区小学 班级:602 红树林 半年 36.0 吴子贤 1
学校: 新建区小学 班级:602 天天数学 半年 24.0 徐盈 1
学校: 新建区小学 班级:602 天天语文 半年 29.0 徐盈 1
学校: 新建区小学 班级:602 小记者 半年 30.0 蔡浩能 1
学校: 新建区小学 班级:教导处儿童文学 半年 66.0 陈主任,叶主任 2
学校: 新建区小学 班级:教导处 少年文摘 半年 48.0 叶主任 1
学校: 新建区小学 班级:教导处 我们爱科学(中高年级) 半年 50.0 陈主任 1

*/




GDTOPONE 2008-04-06
  • 打赏
  • 举报
回复
以上的忘了在最后加一句排序,如果不排序FastReprot中分组就实现不了.

ORDER BY a.ly
GDTOPONE 2008-04-06
  • 打赏
  • 举报
回复
如果要统计出各人共订了几本书可以这样:

select a.ly as '学校加班级',a.l_name as '学生姓名',a.[报刊名称],a.[订阅期限],a.[金额],a.[数量],b.l_sum as '订刊数量' from
(select '学校:'+' '+[学校名称]+' '+'班级:'+[班级名称] as ly,
[报刊名称],[订阅期限],[金额],[数量],[学生姓名] as l_name from tb) a,
(select '学校:'+' '+[学校名称]+' '+'班级:'+[班级名称] as ly,
[学生姓名] l_name,sum(数量) l_sum from tb GROUP BY '学校:'+' '+[学校名称]+' '+'班级:'+[班级名称],[学生姓名]) b where a.ly=b.ly and a.l_name=b.l_name


---------结果


GDTOPONE 2008-04-06
  • 打赏
  • 举报
回复
主要是将:'学校:'+' '+[学校名称]+' '+'班级:'+[班级名称] as ly 合成一个字段,排好序,在FastReprot如何做分组报表,你应该会的了.
GDTOPONE 2008-04-06
  • 打赏
  • 举报
回复
学校: 新建区小学 班级:601 中国卡通(故事版) 半年 36.0 1 伊晰
学校: 新建区小学 班级:601 天天数学 半年 24.0 1 黄胜旺
学校: 新建区小学 班级:601 天天语文 半年 29.0 1 王婧
学校: 新建区小学 班级:601 小记者 半年 30.0 1 邵韵
学校: 新建区小学 班级:601 小记者 半年 30.0 1 李佳欣
学校: 新建区小学 班级:601 少年文摘 半年 48.0 1 王娟
学校: 新建区小学 班级:601 少年文摘 半年 48.0 1 严小青
学校: 新建区小学 班级:601 少年文摘 半年 48.0 1 路瑶
GDTOPONE 2008-04-06
  • 打赏
  • 举报
回复
真的用使用FastReprot五六年?

建立测试数据:

CREATE TABLE tb([班级名称] nvarchar(20),[报刊名称] nvarchar(50),[订阅期限] nvarchar(20),[金额] float,[数量]int,[学生姓名] nvarchar(10),[学校名称] nvarchar(50))

INSERT tb SELECT '601',N'中国卡通(故事版)','半年',36,1,'伊晰','新建区小学'

UNION ALL SELECT '601','天天数学','半年',24,1,'黄胜旺','新建区小学'

UNION ALL SELECT '601','天天语文','半年',29,1,'王婧','新建区小学'

UNION ALL SELECT '601','小记者', '半年', 30 ,1,'邵韵','新建区小学'

UNION ALL SELECT '601','小记者','半年',30 ,1,'李佳欣','新建区小学'

UNION ALL SELECT '601','少年文摘','半年',48 ,1,'王娟','新建区小学'

UNION ALL SELECT '601','少年文摘','半年',48,1,'严小青','新建区小学'

UNION ALL SELECT '601','少年文摘','半年',48,1,'路瑶','新建区小学'

UNION ALL SELECT '601','我们爱科学(中高年级)','半年',50,1,'黄河森','新建区小学'

UNION ALL SELECT '601','我们爱科学(中高年级)','半年',50,1,'吕邦衍','新建区小学'

UNION ALL SELECT '601','读书与作文','半年',27,1,'伊晰','新建区小学'

UNION ALL SELECT '601','读书与作文','半年',27,1,'王俐','新建区小学'

UNION ALL SELECT '601','读书与作文','半年',27,1,'邵韵','新建区小学'

UNION ALL SELECT '601','趣味科学','半年',40,1,'吕邦衍','新建区小学'

UNION ALL SELECT '602','天天数学','半年',24,1,'徐盈','新建区小学'

UNION ALL SELECT '602','天天语文','半年',29,1,'徐盈','新建区小学'

UNION ALL SELECT '602','小记者','半年',30 ,1,'蔡浩能','新建区小学'

UNION ALL SELECT '602','红树林','半年',36,1,'吴子贤','新建区小学'

UNION ALL SELECT '602','读书与作文','半年',27,1,'杨禀','新建区小学'

UNION ALL SELECT '教导处','儿童文学','半年',66,1,'陈主任','新建区小学'

UNION ALL SELECT '教导处','儿童文学','半年',66,1,'叶主任','新建区小学'

UNION ALL SELECT '教导处','少年文摘','半年',48,1,'叶主任','新建区小学'

UNION ALL SELECT '教导处','我们爱科学(中高年级)','半年',50,1,'陈主任','新建区小学'

----取结果
select '学校:'+' '+[学校名称]+' '+'班级:'+[班级名称] as ly,[报刊名称],[订阅期限],[金额],[数量],[学生姓名] from tb ORDER BY ly

msony 2008-04-06
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 try__again 的回复:]
第一个问题倒是可以用crosstab来解决,但是用crosstab免不了遇到问题2,就有点棘手

第三个问题看起来不是问题,分组报表应该是可以的,可以看下fr的demo
[/Quote]

你说的第三个问题 fr 的demo中有解决吗???我看Demo中的报表也没有解决这个问题呀,它也把一个组的内容分在二页中显示了呀!
dl110 2008-04-06
  • 打赏
  • 举报
回复
顶一下
try__again 2008-04-06
  • 打赏
  • 举报
回复
第一个问题倒是可以用crosstab来解决,但是用crosstab免不了遇到问题2,就有点棘手

第三个问题看起来不是问题,分组报表应该是可以的,可以看下fr的demo
软件功能   fastreport5 源码是一款可以帮助您在网页设计上插入报表的工具,可以结合Visual Basic 编辑工具使用,方便您在web上添加报表、打印报表   在打印期间,可以使用fastreport5 模板将各种来源的数据合并在一起以完成打印作业。 可以将多个数据源连结到一个对象中。 在大多数情况下,模板上的对象均使用单个数据源来确定源的内容。   然而,有时您可能希望将来自两个或多个数据源的信息放入一个web、编码器或文本对象中。 通过将其他数据源附加到对象,您可以使用fastreport5将它们结合起来,以便将它们作为一个字符串输出(这有时称为“字符串连结”)。   名称: 显示数据源的名称(如果指定了数据源)。   打开fastreport5更改数据源名称向导,用于指定所选数据源的唯一名称。 通过命名数据源,您可以将所选数据源的内容与其他数据源共享或参考 VB 脚本中的数据源。   FastReport也可在IB_Objects下工作。IB_Objects是用于Interbase数据库管理系统(DBMS)的功能强大且使用广泛的库。   类型: 显示所选数据源的数据源类型。   打开更改数据源类型向导,用于指定将在所选数据源中打印的数据源。 软件特色   开发WEB应用系统通常都会遇到报表打印问题。简单应用可利用IE的页面打印功能,利用HTML标签控制格式来实现。 但复杂的业务型应用系统,报表不仅是组成应用的重要部分,还常常是相当复杂的。很多应用系统都要求提供。自定义报表的功能——即客户可以自行设计、修改报表。   在C/S结构系统中,报表问题有很多成熟的解决方法。如DELPHI开发工具不仅自带有报表控件,还可以利用第三方控件来实现快速灵活的报表制作和打印,其中有名的控件是FR-Software & A.Tzyganenko 的FastReportFastReport提供了能与DELPHI无缝集成的从设计到打印的完整控件包,提供的设计界面友好灵活,对于开发可让用户自定义报表的C/S应用来说,是一种很好的解决方式。   FastReport是非常强大的报表控件,相比QuickReportReportBuilder更加灵活,又非常小巧,速度快。VCL版本支持Borland Delphi 2-6 and Borland C++Builder 1-6。CLX版本支持Delphi和Kylix。

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧