RSS 2.0 Feed

Saturday, July 12, 2008

       一般来说,我们把报表分为两类,一类是ad-hoc的报表,用于实时查询,客户可以输入特定的参数,得到他们感兴趣的报表,还有一类是scheduling的报表,用于自动生成,一般包括daliy,monthly,quarterly和yearly的报表,这种定制类的报表,可以在指定的时间,生成到指定的目录,他们生成的内容也会提前定制,参数不可更改。一般在报表的需求定义中,客户都会要求报表能够做到自动生成,这也就是我们所说的第二类报表,有时候,客户还会要求能够在自动生成的同时,实现自动打印。下面我们来谈谈如何实现报表的自动生成以及自动打印。

       首先来谈谈解决方案,由于RS提供web service式的调用,因此我们可以写一个remoting service或者windows service或者仅仅是一段程序,然后由job之类的调用,来实现报表的自动。在程序中,我们调用RS,来实现报表的生成。需要生成的报表列表,报表的参数(时间参数),导出文件的格式,我们定义在数据库里,解决方案简单的用图表来表现如下:

image

下面我们来谈具体的步骤

第一步:创建项目,添加web引用(C#项目),URL为http://localhost/ReportServer/ReportService.asmx

clip_image004

第二步,取参数以及定义其他的参数。

参数表的内容为:

ReportName PeriodType PromptName1 Prompttype1 Format

SupplierD D date datetime PDF

SupplierM M date datetime PDF

SupplierQ Q date datetime PDF

SupplierY Y date datetime PDF

ReportName为报表的名称,PeriodType为报表的类别,分别是日报,月报,季度报和年报,PromptName1和Prompttype1为参数的名字和类别,如果有需要,可以加更多的参数。Format为报表导出的格式。(为方便描述,下述代码中的参数都写死,实际操作中,会从数据库或者从注册表中读取。)

定义参数的代码为:

ParameterValue[] parameters = null;

parameters[1] = new ParameterValue();

parameters[1].Name = “date”;

parameters[1].Value =”01/01/2008”;

 

定义其他参数:

string devInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";

string encoding;

string mimeType;

Warning[] warnings = null;

string[] streamIDs = null;

DataSourceCredentials[] credentials = null;

ParameterValue[] used = null;

 

第三步,生成报表并得到报表的二进制流

ReportingService rep = new ReportingService();

rep.Credentials = rep.Credentials = System.Net.CredentialCache.DefaultCredentials;

byte[] ss = null;

得到报表:

ss = rep.Render(“SupplierD” , “PDF”, null, devInfo, parameters, credentials, null, out encoding, out mimeType, out used, out warnings, out streamIDs);

使用的方法是RS提供的

Render ( Report As string ,  Format As string ,  HistoryID As string ,  DeviceInfo As string ,  Parameters As ArrayOfParameterValue ,  Credentials As ArrayOfDataSourceCredentials ,  ShowHideToggle As string ) As base64Binary

 

第四步:将生成的报表保存到服务器

FileStream repFile = new FileStream(@“D:\Report\ SupplierD”, FileMode.Create);

repFile.Write(ss, 0, ss.Length);

repFile.Close();

 

第五步:自动打印生成的报表

System.Diagnostics.ProcessStartInfo startInfo = new ProcessStartInfo();

startInfo.Arguments = "/p /h " + @“D:\Report\ SupplierD”;

startInfo.FileName = @"C:\Program Files\Adobe\Reader 8.0\Reader\AcroRd32.exe"; ; //Replace this with the path of the Acrobat Reader executable file, i.e. AcroRd32.exe

startInfo.UseShellExecute = true;

System.Diagnostics.Process process = Process.Start(startInfo);

process.WaitForExit(10000);

if (process.HasExited == false)

{

process.Kill();

}

       这里的方法其实是打印已经生成的PDF文件,所以要求该机器必须装有Acrobat Reader。不选用直接打印二进制数据流,是因为这种打印方法无法设置横向打印(Landscape)或者是竖向打印(Portrait),而报表肯定是有横向有竖向的。不选用打印生成html文件的方式,是因为RS不支持导出HTML,只支持MHTML,而MHTML转成HTML太麻烦。

       最后,有几点需要注意的是,RS导出的报表必须是已经发布到Report server上的,调用render方法时,第一个参数Report As string必须和reportserver上的路径一致,比如报表的发布路径是Report/SupplierD,那么这个参数的值为”Report/SupplierD”。还有一个要注意的是如果制作报表时,参数设置成下拉框式(如下图),那么传入的值必须是这些值其中之一或者之几(看是否是Multi-value)。

clip_image006

留言请访问如下链接:

Reporting Service Tips 101(#4) - 使用RS实现报表的自动生成以及在程序中调用RS

posted @ | Feedback (2) | Filed Under [ Reporting Service Tips 101 ]

最近几天发现我始终不能在博客堂发布带有较多图片的Blog了,无论是Web发布还是Writer发布,都提示SQL错误:

发生服务器错误 0

String or binary data would be truncated.
The statement has been terminated.    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at SubSonic.SqlDataProvider.ExecuteQuery(QueryCommand qry)
   at SubSonic.StoredProcedure.Execute()
   at Joycode.Framework.Data.DatabaseObjectProvider.InsertEntry(Entry entry) in D:\Projects\Joycode\Joycode.Blog\Joycode.Framework\Data\DatabaseObjectProvider.cs:line 623
   at Joycode.Framework.Data.DatabaseObjectProvider.CreateEntry(Entry entry, Int32[] categoryIds) in D:\Projects\Joycode\Joycode.Blog\Joycode.Framework\Data\DatabaseObjectProvider.cs:line 576
   at Joycode.Framework.Entries.Create(Entry entry) in D:\Projects\Joycode\Joycode.Blog\Joycode.Framework\Entries.cs:line 259
   at Joycode.Framework.XmlRpc.MetaWeblog.newPost(String blogid, String username, String password, Post post, Boolean publish) in D:\Projects\Joycode\Joycode.Blog\Joycode.Framework\XmlRpc\MetaWeblog.cs:line 274

 

比如这三篇:

Reporting Service Tips 101(#5) - 在报表页面上添加交互式排序

Reporting Service Tips 101(#6) - RS中从一个报表jump到另外一个报表

Reporting Service Tips 101(#7) - 使用RS制作树状可折叠报表

在CnBlogs正常发布,但是博客堂全部失败。

posted @ | Feedback (2) |

接上一篇(Reporting Service Tips 101 - 关于使用Sum函数会遇到的问题(1)),谈谈使用sum可能会遇到的另外一个问题。

Dateset的数据如下:

Supplier      Revenue    status

A               5.00        0

A               6.00        1

A               7.00        0

需求是只用sum算出Supplier A在status为0时候的Revenue总和。单看这个需求,我们其实很容易用在报表中添加分组,或者直接在数据的上一层group来解决,但是在做很多复杂报表的时候,如果能够在计算公式里面去解决一些问题,整个报表的开发过程会简单得多。

报表如下:

clip_image001

计算公式为:=FormatNumber(Sum(Fields!Revenue.Value and Fields!status.Value=0),2)

结果如下:

clip_image002

可以看到,正是我们想要的结果。但是这种方法,在遇到很复杂的报表的时候,有时候会有问题,所以我们还可以用另外一种方法。

报表:

clip_image003

计算公式为:=FormatNumber(Sum(iif(Fields!status.Value=0,Fields!Revenue.Value,0)),2)

结果:

clip_image004

和上一种方法的结果一样,但是这种方法的好处是,基本上无论多复杂的报表,都不会有问题。

留言请访问如下链接:

Reporting Service Tips 101(#3) - 关于使用Sum函数会遇到的问题(2)

posted @ | Feedback (1) | Filed Under [ Reporting Service Tips 101 ]