reportviewer动态加载报表的实现以及动态控制报表,套打,存折打印模式等的一些探讨,欢迎批评指正!

 
需求如下 :
1. 可以在一个界面中列出多张报表 , 根据用户的选择 , 浏览指定的报表 , 用户可以随意选择 , 切换新报表,也即是报表可以被替换的。
2 . 可以实现对所选择的报表 , 替换它的数据源 , 或者往数据源增加或删除行 ( 如果数据源绑定的是自定义对象集合 , 则可以往集合插入或移除对象 ) ,也即是报表的数据是可以被替换的。
3 如何让最终用户控制报表,我的意思是:可以让用户在默认报表的情况下,更改下列宽行高,隐藏排序列,设置页眉页脚或者表标题,等等。应用了这些功能后,在报表浏览器看到新的结果。
4套打报表,连续打印,存折打印模式.
5.有界面和无界面的打印.
实现思路如下 :
1, 如何让一个报表浏览器适应多张报表 ?
在网上找了很多资料 , 在这方面的介绍很少,看了一个博客朋友的文章 http://blog.csdn.net/qiujiahao/archive/2007/08/09/1733415.aspx, 是通过动态加载报表浏览器 (ReportViewer) 的方式来实现动态切换报表 , 不过,感觉很奇怪 , 换个 URL, 难道 IE 浏览器就把原先的 IE 关了再开新的 IE 来浏览网页吗 ? 但是 , 它的变通思路还是值得借鉴的。这里是该博友文章的要点
ControlCollection coll = ReportViewer1.Parent.Controls;
        
int oldIndex = coll.IndexOf(ReportViewer1);
        ReportViewer newViewer = 
new ReportViewer();
        coll.AddAt(oldIndex, newViewer);  
注意 , 如果是 VB 代码 , 此处没有 AddAt 方法 , 需要你为添加进去的对象指定好索引后再 Add 进去
        coll.Remove(ReportViewer1);
上面的意思是把新的报表浏览器 reportviewer 替换旧的报表浏览器
这不是本文的要点,好了 . 先撇开这个不谈 , 我们知道 , 报表浏览器的工作原理是这样的
·         数据源
  可以是传统数据库,也可以是XML表格,当然,也可以是自定义的对象
Data Adapter 及 Connection 等
  用来连接传统的数据库
DataSet
  用来存储数据,同时可以直接操作XML文件
BindingSource
  利用DateSet来填充BindingSource,这一步数据中转逻辑上有点多余,但是必不可少
ReportDataSource
  利用BindingSource来填充ReportDataSource,......-_-!!
ReportViewer
利用ReportDataSource填充的 数据 及 指定给它的RDLC报表文件来显示报表
好了,了解了上面的原理后,我们就可以开始让我们的报表浏览器工作起来了。
报表浏览器 --- 指定报表定义文件和报表定义文件所绑定的数据源 , (数据源可以是数据集或者自定义对象 ,
1 其中报表定义文件的指定方法 :Me.ReportViewer1.LocalReport.ReportEmbeddedResource = "rpDemo.OldReport.rdlc", 在这里 , 我是将报表定义文件 OldReport.rdlc 嵌入到项目中的,如果你的报表定义文件存在于项目之外 , 则可以使用 Me.ReportViewer1.LocalReport.ReportPath 来指定报表定义文件( . 其中 "rpDemo. OldReport.rdlc 前面的 rpDemo 是项目名 .
2 其中报表定义文件所需要的数据源指定方式如下 :
代码是在 winform 中写的。
  Private bdds As BindingSource ‘全局变量,绑定源,在窗体初始化的时候被创建,绑定源就像个中间对象,连接着报表浏览器和报表的数据源,使得报表浏览器能显示报表的数据。
Privat e ds As demolist ‘ 这个 ds 是提供给绑定源的,而绑定源提供给报表源,报表源提供给报表浏览器的 localreport 属性下的 datasources 属性。将 ds 设置为全局变量,以便可以在子程序中更改 DS 的数据。来测试报表适应数据源的改变。
Sub New()
        ' 此调用是 Windows 窗体设计器所必需的。
        InitializeComponent()
        ' InitializeComponent() 调用之后添加任何初始化。
        If Me.components Is Nothing  Then Me.components = New System.ComponentModel.Container       
bdds = New BindingSource(Me.components)   ‘ 创建绑定源对象的时候需要指定容器,以便于绑定源跟该容器下的报表浏览器绑定起来。
    End Sub
 
然后创建 ReportDataSource 对象 , 并将它的名字指定为报表定义文件中绑定的数据源 , 将它的值指定为 bdds 绑定源
Dim reportds As New Microsoft.Reporting.WinForms.ReportDataSource("rpDemo_demo", bdds)  '        第一个参数指定的是我们在制作报表的时候为报表提供的数据源,第二个参数是绑定源对象,这样绑定源跟报表数据源就产生关联了。
ds = New demolist  
        bdds.DataSource = ds  ‘将数据实例提供给绑定源,我这里的数据实例是个对象集而不是数据集
        Me.ReportViewer1.LocalReport.DataSources.Add(reportds)
’最后一步,将报表数据源将到报表中
 
3 好了。一个报表浏览器就配置好了定义文件和数据源了
Me .ReportViewer1.RefreshReport() ‘这样就可以呈现报表了。
(4)  Me.ReportViewer1.Reset() ‘假如你从一个下拉框中选择新的报表定义文件后就执行这句代码,可以将报表浏览器的配置清空,然后重新配置报表浏览器呈现新的报表,代码如下。
Me .ReportViewer1.LocalReport.ReportEmbeddedResource = "rpDemo. NewReport .rdlc"  注意,这里指定新的报表定义文件了
 
        Dim reportds As New Microsoft.Reporting.WinForms.ReportDataSource("rpDemo_demo2", bdds)  ‘这里的两个参数也变了。因为要显示新的报表,就重新指定了新的报表定义文件,报表定义文件变了,所以第一个参数指定的报表数据源当然也跟着变了。而第二个参数指定的是绑定源,我们不需要更改,只是提供给绑定源的数据实例要变而已。demo2list而不再是demolist
        bdds.DataSource = New demo2list
        Me.ReportViewer1.LocalReport.DataSources.Add(reportds)
        Me.ReportViewer1.RefreshReport()
2 如何更改报表的数据源
更改数据的方法也很简单,由于我们使用了绑定源对象,所以对于数据源的更改,报表浏览器是不需要理会的,这就是绑定源的好处了。绑定源对报表数据源负责。
ds.Add(New demo("xyz", "asd", "ddd"))  ‘往我们的demolist集合中插入一个对象
        Me.ReportViewer1.RefreshReport()   ‘新插入的对象被显示了
 
3 需求3 动态控制报表(可以让用户稍微调整报表的样式)
思路有三个
A.      报表对象是否公开了这些方法呢?这是最先想到的 ReportViewer.localReport.在这里,localreport下的有关控制报表项的方法都是只读的。行不通
B.      写一个动态生成报表定义文件的程序,由于报表定义文件是基于XML格式的,所以只要了解他的结构,就可以做到,不过,当你想生成的报表格式比较复杂的时候,对于你这个自定义报表生成器的要求就高很多了,并不建议这么做,有个老兄对这个报表定义文件的解析有很多的了解,可以参考他的博客http://blog.csdn.net/flygoldfish/archive/2005/12/16/554035.aspx
C.      将报表定义文件使用XMLDOCUMNET这样的类,在内存中对该文件的XML元素做更改,然后将更改后的定义文件重新加载到报表浏览器,这样的方法比较好,参考此博友的文章
E.       
由于我未在这方面做测试,希望有需求的朋友如果做出来的话,在我的博客留个言,大家交流一下。其原理就是更改报表定义文件的XML元素来达到更改报表项的目的。
 
4 需求4套打的实现.和单据连续打印的问题
套打就是像打印发票一样,纸张是印刷好了特定的格式了,而报表只负责打印数据,实现的思路主要是在使用Reporting services的报表设计器制作报表的时候,对控件的位置指定表达式,这样,在程序中编码,计算出该控件应该所在的位置,计算元素可以从报表对象中取得.
对于连续打印的问题,请记得先在最外部使用一个列表控件,把表格控件放在列表控件里面,这样即可实现一份格式,不同的数据行,打印的时候就可以打出多份报表(如员工资料报表)由于我还没做完,等我做出后再发布.
5需求,界面打印不需要提了,reportviewer控件有打印的功能,非界面打印,可以用到localreport和printdocument的printpage事件,在这个事件中进行处理,主要用到localreport.Render方法,MSDN帮助有这个例子,可以在帮助中搜索localreport找到,这里不多说了。
总结:
需求1的实现对于报表浏览器来说,第一是报表定义文件变了,第二是报表定义文件所要求的数据源也变了。对于第一个变化,需要重新指定报表定义文件即可,对于第二个变化,我们需要指定新的报表数据源,然后将绑定源所依赖的数据实例也替换成报表数据源所需要的。别忘了替换报表之前先调用报表浏览器的 Reset 方法,将旧报表的设置清掉。
至于需求2,其实正是因为绑定源的存在,所以只需要操作数据实例即可。
至于需求3,我觉得其实可以将报表文件导出EXCEL文件给最终用户,毕竟在EXCEL中去调整会方便很多。另外,使用报表模型项目,将现成的报表生成器配合报表模型,最终用户也是可以自己设计报表的。使用程序更改报表定义文件的方法,工作量会大很多,只能实现有限的动态控制而已了。
需求四的套打,也存在这样的需求,像打印存折那样打印,也即是旧记录不打而只打新记录,我的思路是对要打印的行的颜色设置表达式,在提供的数据中包含一个字段控制是否已经打印,已经打印过的则让该行颜色为白色,这样旧记录既会占位,也不打印,即可只打印新的记录了。当然,使用控件的位置表达式,会更灵活,但编程就需要计算位置了。
相关参考:以下的URL包含一些打印报表中遇到的问题,可以在这些博客做些参考。http://www.cnblogs.com/dlwang2002/archive/2007/02/14/410499.html
想做一个报表设计器的朋友,可以参考下速达的http://www.superdata.com.cn/down/Down_Tryout.aspx
其中的5000工业版和7000工业版都有打印样式设计的界面可以参考。
有这方面需求的朋友,不妨将你开发的经验分享下,或者在我的博客留下你的博客地址,大家互相进步。
想对Reporting Services有进一步了解的朋友也可以在这里提些问题,我能帮忙的都尽量帮,有好的资料可以在这里发布下,谢谢!
 
 
 
 
 
 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值