`

动态报表系统实现思路

阅读更多

最近参与到一个报表系统的建设,对于如何实现动态报表系统的,简单谈下自己实现思路,还请大家多指教。

 

开始之前简单描述下用户的需求:

1.报表模板在系统运行之前定义并设计好,生成可视化的html页面(包含表格数据和图形展示),保存到指定的存储目录下。

2.存储过程在指定的时间点启动,按照业务逻辑汇总报表数据,为报表提供数据源。

3.应用程序查询存储过程汇总的数据,并将数据插入到指定的报表模板中,生成用户需要的展示格式:pdf、excel、html等。

 

优势:

模板提前定义好,方便管理。

 

缺点:

可扩展性差,用户无法实现根据业务的需要修改报表的模板。

 

动态报表系统的类型:

1.用户可以修改报表模板

 

思路:

1.1html报表模板提前定义并存储好。

1.2提供一个html在线编辑工具,用户可以在线编辑定义好的模板,添加或者删除指标。

1.3报表模板的指标保存到数据库中。

1.4数据库端有job监控报表模板数据表,如果某一条数据发生变化,则根据变化规则修改相应的存储过程,实现数据汇总的动态修改。

 

2.用户可自由添加、删除报表模板

2.1提供一个html在线编辑工具,用户可以在线添加报表模板,并填写报表汇总的规则:例如几点几分开始汇总该报表的数据。

2.2报表模板数据保存到DB中。

2.3定时任务实时监控模板数据表,发现添加了一个报表模板数据,则根据数据规则动态生成存储过程和执行job。

2.4job启动存储过程,实现汇总数据。

 

第二种设计暂时有个细节尚未考虑清楚:存储过程和执行job的生成如何实现,感觉可以实现,但还有待进一步验证。

当然后面两种实现方式是我个人的一些想法,肯定不会用到当前的项目中的,因为客户没提这样的要求、时间有限等等。

 

仅供大家参考,欢迎有报表研发经验批评指正,谢谢。

 

 

 

 

 

 

分享到:
评论
23 楼 kkqqcom 2010-12-17  
wn_1985 写道
说到底,还是个组合查询的问题而已
现在很多报表工具都可以实现,比如:ireport+japserreport

另外,"用户可以修改报表模板",个人认为没有什么实际的意义
根据我的经验,项目运行的时候,大多数模板用户都已经能确定,而且不会更改,如果有新的需求,也不要在原来报表上进行改动,可以增加新的报表

用户可以修改模板是现在很多系统的“通用需求”
个人觉得,企业内的系统,excel就不错:
http://code.google.com/p/exreport/
22 楼 wn_1985 2010-12-17  
说到底,还是个组合查询的问题而已
现在很多报表工具都可以实现,比如:ireport+japserreport

另外,"用户可以修改报表模板",个人认为没有什么实际的意义
根据我的经验,项目运行的时候,大多数模板用户都已经能确定,而且不会更改,如果有新的需求,也不要在原来报表上进行改动,可以增加新的报表
21 楼 一路向前 2010-12-17  
嗯, 这个做法貌似比较死板, 还得另外去提供工具去处理html模板。
我目前也在做一个类似的工作, 主要是根据提供的数据源,采用xml配置的方式去进行生成jrxml模板,然后再进行数据装填工作。 从而实现动态生成报表的工作,用户不用每次有所改变报表都去修改模板,只需要修改xml配置文件即可
不过目前实现的复杂度还比较小,只能实现比较简单的报表排版。
20 楼 shiren1118 2010-10-12  
grandboy 写道
kimmking 写道
一个方案,dsoframer+excel

直接用excel作为模板



思路不错,但是我不赞成直接依赖ActiveX控件. 我现在用XML+XSLT来实现的Excel报表的功能. 当然也有些缺点,但是我还没有想到有更好的办法.


这个貌似不太好弄吧?国内ie问题太严重···
19 楼 grandboy 2010-10-11  
kimmking 写道
一个方案,dsoframer+excel

直接用excel作为模板



思路不错,但是我不赞成直接依赖ActiveX控件. 我现在用XML+XSLT来实现的Excel报表的功能. 当然也有些缺点,但是我还没有想到有更好的办法.
18 楼 newvirus 2010-10-11  
不错的思路 为什么不考虑AJAX和servlet的形式实现动态效果呢
17 楼 sidac 2010-10-11  
<!-- 消费POS报表设置 -->
<StatisticsSet>
	<!-- 报表设置(name 报表名称) -->
	<Statistics name="zyrmbshsdqktj">
		<!-- 报表标题 -->
		<title>自有人民币商户收单情况统计表</title>
		<!-- 报表列数 -->
		<colCount>18</colCount>
		<!--
			是否显示自定义列头
			1 显示自定义列头(自动从统计页面位置查找跟报表Name相同的.head文件做报表列头)
			0 根据列定义里维护的列标题显示列头
		-->
		<customColHead>
			<![CDATA[
				<tr>
					<th rowspan='2'>行别</th><th rowspan='2'>序号</th><th rowspan='2'>商户编号</th><th rowspan='2'>商户名称
					<th colspan='2'>本年累计消费</th><th colspan='2'>其中,本行卡</th><th colspan='2'>其中,他行卡</th><th colspan='2'>本月消费</th><th colspan='2'>其中,本行卡</th><th colspan='2'>其中,他行卡</th>
					<th rowspan='2'>本年累计收单收入</th><th rowspan='2'>本月收单收入</th>
					</tr><tr>
					<th>金额</th><th>笔数</th><th>金额</th><th>笔数</th><th>金额</th><th>笔数</th><th>金额</th><th>笔数</th><th>金额</th><th>笔数</th><th>金额</th><th>笔数</th>
				</tr>
			]]>
		</customColHead>
		<!-- 报表列定义 -->
		<columns>
			<!--
				列定义
				name 列名称
				title 列标题(当customColHead=1时可为空)
				type 列类型(0 数值 1 字符)
				statmode 统计方式(0 不统计 1 计数统计 2 加和统计)
				dec 小数位数(只有数值列需要)
			-->
			<column name="gxhmc" title="行别" type="1" statmode="0" dec="0"/>
			<column name="xh" title="序号" type="0" statmode="0" dec="0"/>
			<column name="shbh" title="商户编号" type="1" statmode="1" dec="0"/>
			<column name="shmc" title="商户名称" type="1" statmode="0" dec="0"/>
			<column name="bnxfje" title="本年累计消费金额" type="0" statmode="2" dec="2"/>
			<column name="bnxfbs" title="本年累计消费笔数" type="0" statmode="2" dec="0"/>
			<column name="bnbhxfje" title="本年本行卡累计消费金额" type="0" statmode="2" dec="2"/>
			<column name="bnbhxfbs" title="本年本行卡累计消费笔数" type="0" statmode="2" dec="0"/>
			<column name="bnthxfje" title="本年他行卡累计消费金额" type="0" statmode="2" dec="2"/>
			<column name="bnthxfbs" title="本年他行卡累计消费笔数" type="0" statmode="2" dec="0"/>
			<column name="byxfje" title="本月消费金额" type="0" statmode="2" dec="2"/>
			<column name="byxfbs" title="本月消费笔数" type="0" statmode="2" dec="0"/>
			<column name="bybhxfje" title="本月本行卡消费金额" type="0" statmode="2" dec="2"/>
			<column name="bybhxfbs" title="本月本行卡消费笔数" type="0" statmode="2" dec="0"/>
			<column name="bythxfje" title="本月他行卡消费金额" type="0" statmode="2" dec="2"/>
			<column name="bythxfbs" title="本月他行卡消费笔数" type="0" statmode="2" dec="0"/>
			<column name="bnsdsr" title="本年累计收单收入" type="0" statmode="2" dec="2"/>
			<column name="bysdsr" title="本月收单收入" type="0" statmode="2" dec="2"/>
		</columns>
		<!-- 提取数据的源表(逗号(,)分隔) -->
		<srcTable>
			pos_yfshjytjb, pos_yfshxxb
		</srcTable>
		<!-- 提取数据的SQL语句 -->
		<selectSQL>
			<![CDATA[
				select pos_yfshxxb.gxhmc, pos_yfshxxb.shbh, pos_yfshxxb.shmc, 
					pos_yfshjytjb.bnxfje, pos_yfshjytjb.bnxfbs, pos_yfshjytjb.bnbhxfje, pos_yfshjytjb.bnbhxfbs, pos_yfshjytjb.bnthxfje, pos_yfshjytjb.bnthxfbs,
					pos_yfshjytjb.byxfje, pos_yfshjytjb.byxfbs, pos_yfshjytjb.bybhxfje, pos_yfshjytjb.bybhxfbs, pos_yfshjytjb.bythxfje, pos_yfshjytjb.bythxfbs,
					nvl(pos_yfshjytjb.bnbhhksr, 0) + nvl(pos_yfshjytjb.bnbhbssr, 0) + nvl(pos_yfshjytjb.bnthhksr, 0) + nvl(pos_yfshjytjb.bnthbssr, 0) as bnsdsr, 
					nvl(pos_yfshjytjb.bybhhksr, 0) + nvl(pos_yfshjytjb.bybhbssr, 0) + nvl(pos_yfshjytjb.bythhksr, 0) + nvl(pos_yfshjytjb.bythbssr, 0) as bysdsr
				from pos_yfshjytjb, pos_yfshxxb
				where pos_yfshxxb.yf = pos_yfshjytjb.yf
					and pos_yfshxxb.shbh = pos_yfshjytjb.shbh
					[insert_condition_here]
				order by pos_yfshxxb.gxhdm, bnsdsr
			]]>
		</selectSQL>
		<!--
			查询条件
			replaceInSql 用条件语句替换掉SQL语句中的...
			startWith 条件语句以...做起始
			name 条件名称(jgdm 机构编码 shbh 商户编号 tjyf 统计月份 tjrq 统计日期)
			refFields 条件应用到的字段名称列表(逗号(,)分隔)
			fieldType 字段类型 0 数值 1 字符
			required 是否是必须的条件
		-->
		<conditions replaceInSql="[insert_condition_here]" startWith="and">
			<condition name="tjyf" refFields="pos_yfshjytjb.yf" fieldType="1" required="yes"/>
			<condition name="shbh" refFields="pos_yfshxxb.shbh" fieldType="1" required="no"/>
			<condition name="jgdm" refFields="pos_yfshxxb.gxhdm" fieldType="1" required="no"/>
		</conditions>
		<!--
			是否自定义显示报表
			可选值(yes/no)(true/false)(1/0)
			默认是"no",用系统默认的报表显示处理来显示报表
			如果设置为"yes",则用自定义处理显示报表
			这时需要设置
				refCol(分组参照列)
				detailStartCol(明细列表起始列)
				detailEndCol(明细列表截止列)
				detailColWidths(明细列表列宽设置,逗号[,]分隔)
			属性
		-->
		<customShow needCustomShow="0"></customShow>
		<!-- 显示序号的列号,0 为不显示序号 -->
		<serialColIndex>2</serialColIndex>
		<!-- 
			是否需要分组统计
			needClassify 分组统计标识 1 分组统计 0 不分组统计
			classifyCol 分组的列
		-->
		<classifiy needClassify="0" classifyCol="1"/>
		<!-- 是否需要对全表值进行统计 -->
		<valueStatistic>1</valueStatistic>
		<!-- 报表底 -->
		<foot/>
		<!-- 描述 -->
		<description>第1张报表</description>
	</Statistics>
</StatisticsSet>

以前做的自定义报表的设置,处理起来也不算太复杂,当然这个只能应对要求不算太高,表面不太复杂的报表,而且不支持上卷下钻(虽然支持起来也不复杂),权作参考,代码不太好看,就不贴了。
16 楼 hellostory 2010-10-11  
charles751 写道
hellostory 写道
最近也在做公司的一个报表查询系统,前台主要用Flash图表展示(使用FashionCharts),配合简单的表格。领导要求以后可以在前台任意添加修改报表。因此将报表的数据源等配置信息存放在数据表中,而前台Falsh展示配置使用XML文件,用户可以随时修改,如指定数据表的那个字段为X轴等


你的后台数据源是从数据库或文件中直接查询来的吧?


是从数据库中查询出来的。数据表中有一个字段存放查询SQL语句(如select CLASS,FieldA,FieldB from T1),而Flash的XML文件则指定查询结果集的哪个字段作为X轴上的一个系列等
<graph caption="材料采购分析图"
	xaxisname="类别"
	yxisName="金额"
	showValues='0'
	rotateNames='0'
	formatNumberScale='0'
	baseFontSize="12">
	<categories fieldName="CLASS" font="宋体" fontSize="14" fontColor="000000">
	</categories>
	<dataset fieldName="FieldA" seriesname="本月采购额"></dataset>
	<dataset fieldName="FieldB" seriesname="去年同期采购额"></dataset>
</graph>

其中属性“fieldName”表示引用结果集中的哪个字段的系列值。
用户查询时,系统将根据查询结果数据,结合上面的XML文件,填充为一份完整的XML数据文件,然后传递到前台页面Flash显示

完整的XML文件:
<graph caption='材料采购分析图' xaxisname="类别" yaxisname="金额" 
	rotateNames='0'					
	rotateYAxisName='0'
	formatNumberScale="0"
	baseFontSize="12">
	<categories fieldName="CLASS"  font="宋体" fontSize="14" fontColor="000000">
	  <category label="材料一" /> 
	  <category label="材料二" /> 
	  <category label="材料三" /> 
	  <category label="材料四" />
	</categories>
	<dataset fieldName="FieldA" seriesname="本月采购额">
		  <set value="100" /> 
		  <set value="200" /> 
		  <set value="300" /> 
		  <set value="220" /> 
	</dataset>
	<dataset fieldName="FieldB" seriesname="去年同期采购额">
		<set value="200" />
		<set value="150" />
		<set value="400" />
		<set value="200" />
	</dataset>
</graph>





15 楼 maodiesky 2010-10-11  
hellostory 写道
最近也在做公司的一个报表查询系统,前台主要用Flash图表展示(使用FashionCharts),配合简单的表格。领导要求以后可以在前台任意添加修改报表。因此将报表的数据源等配置信息存放在数据表中,而前台Falsh展示配置使用XML文件,用户可以随时修改,如指定数据表的那个字段为X轴等


fusioncharts
14 楼 charles751 2010-10-10  
hellostory 写道
最近也在做公司的一个报表查询系统,前台主要用Flash图表展示(使用FashionCharts),配合简单的表格。领导要求以后可以在前台任意添加修改报表。因此将报表的数据源等配置信息存放在数据表中,而前台Falsh展示配置使用XML文件,用户可以随时修改,如指定数据表的那个字段为X轴等


你的后台数据源是从数据库或文件中直接查询来的吧?
13 楼 hellostory 2010-10-10  
最近也在做公司的一个报表查询系统,前台主要用Flash图表展示(使用FashionCharts),配合简单的表格。领导要求以后可以在前台任意添加修改报表。因此将报表的数据源等配置信息存放在数据表中,而前台Falsh展示配置使用XML文件,用户可以随时修改,如指定数据表的那个字段为X轴等
12 楼 melin 2010-10-09  
charles751 写道
yangjitang100 写道
直接用报表工具吧

用户不想花钱,呵呵

使用birt。整合一下,很实用的


11 楼 maodiesky 2010-10-09  
你没有说清楚你的需求,比如你的报表的复杂度,你的数据的复杂度
前面的人都说到ETL了,你有这个需求吗?

开源的报表实现也比较多了。若你自己去开发套,会给自己带来很多风险,而最终影响到项目交付。

其实你说的东西,一般的报表思想都会夹杂点,不妨你可以对比下现有人气比较好的开源报表组件,比如jasperreport、jfreereport、还有一些以IE控件实现的报表控件。

10 楼 charles751 2010-10-09  
yangjitang100 写道
直接用报表工具吧

用户不想花钱,呵呵
9 楼 yangjitang100 2010-10-09  
直接用报表工具吧
8 楼 longlongriver 2010-10-09  
搞得太复杂了,JasperReport+iReport不行吗?
7 楼 charles751 2010-10-09  
shiren1118 写道
报表就是报表,不要把ETL混进来,不然你前期设计的太复杂,很难去完成


你说的没错。
我只是描述了一个思路,实现肯定不会按照最难实现的方案取执行,呵呵。
6 楼 shiren1118 2010-10-09  
kimmking 写道
shiren1118 写道
kimmking 写道
一个方案,dsoframer+excel

直接用excel作为模板




可有实例?上卷,下钻,多表头,多维能实现否?

http://setting.iteye.com/blog/206038



果然是不错,很有意思~~~等我抽空也弄一个~~


5 楼 charles751 2010-10-09  
kimmking 写道
一个方案,dsoframer+excel

直接用excel作为模板


这个想法不错,也符合实际要求,但是原型已经做出来了,不能再改了。
4 楼 kimmking 2010-10-09  
shiren1118 写道
kimmking 写道
一个方案,dsoframer+excel

直接用excel作为模板




可有实例?上卷,下钻,多表头,多维能实现否?

http://setting.iteye.com/blog/206038

相关推荐

Global site tag (gtag.js) - Google Analytics