Web程序,使用ReportSerivce报表对象模型编程发布报表
前一段时间在公司做了一个需要用到sql server2005 reportserivce服务的项目,我主要负责reportserivce的报表模块部分.为了方便报表的发布,所以做了报表的添加,删除管理页面.下面就记录一下我的做的添加表报功能页面:
下面最终做的添加管理页面:
![报表管理页面截图](https://i-blog.csdnimg.cn/blog_migrate/00a6edeff1c14080a06ef5e79a16e4b3.gif)
接着,说说具体的步骤:
首先定义一个报表项目ReportItem.cs类,用主要是方便后面好操作,方便修改导航树报表的url地址:
ReportItem.cs代码
/**/
/// <summary>
/// 报表项目类
/// </summary>
public
class
ReportItem
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
private string _chname;
private string _enname;
private bool _isSubReport;
public ReportItem(string ChineseName, string EnglishName)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_chname = ChineseName;
_enname = EnglishName;
_isSubReport = false;
}
public ReportItem(string ChineseName, string EnglishName, bool IsSubReport)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_chname = ChineseName;
_enname = EnglishName;
_isSubReport = IsSubReport;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 获取或设置中文报表名称
/// </summary>
public string ChineseName
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _chname; }
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _chname = value; }
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 获取或设置英文报表名称
/// </summary>
public string EnglishName
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _enname; }
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _enname = value; }
}
public bool IsSubReport
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _isSubReport; }
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _isSubReport = value; }
}
同时,我在待添加报表的目录中,写了Reports.xml文件,由于描述报表的一些属性,和上面的reportitem.cs类是对应的.
说明以下:
ChineseName主要用于显示在导航树中的名字
Englishname是用来保存报表的英文名字,因为在开发的时候,以及后面的url访问的时候,都是用的这个名字,所以我决定英文名字,以避免将来可能遇到的编码问题.
IsSubReport是否是子报表,主要是以为我有嵌套子报表的情况.
上面的ReportItem.cs的各个属性说明也和这个一样.
<?
xml version="1.0" encoding="gb2312"
?>
<
ReportItems
>
<
Item
>
<
ChineseName
>
商品基本信息
</
ChineseName
>
<
EnglishName
>
ReportGoods.rdl
</
EnglishName
>
<
IsSubReport
>
true
</
IsSubReport
>
</
Item
>
</
ReportItems
>
以下是C#源代码:
using
System;
using
System.Data;
using
System.Configuration;
using
System.Collections;
using
System.Web;
using
System.Web.Security;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.Web.UI.WebControls.WebParts;
using
System.Web.UI.HtmlControls;
using
System.Web.Services;
using
myWebReport.Web.rs;
using
System.Xml;
using
System.Collections.Generic;
namespace
myWebReport
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
public partial class AddReport : System.Web.UI.Page
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
protected void Page_Load(object sender, EventArgs e)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/Images/OutliningIndicators/InBlock.gif)
protected void btnAddReport_Click(object sender, EventArgs e)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (GetCheckReport().Count > 0)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
try
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/InBlock.gif)
this.lberror.Text = "";
this.lberror.Visible = false;
ReportingService rs = new ReportingService();
rs.Url = this.txtWebSevice.Text.Trim() + "/ReportServer/ReportService.asmx";
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
rs.CreateFolder(this.txtServerPath.Text, "/", null);
DataSourceDefinition dsd = new DataSourceDefinition();
dsd.CredentialRetrieval = CredentialRetrievalEnum.Store;
dsd.ConnectString = this.txtSQLConnectionString.Text.Trim();
dsd.Enabled = true;
dsd.EnabledSpecified = true;
dsd.Extension = "SQL";
dsd.ImpersonateUser = false;
dsd.ImpersonateUserSpecified = true;
dsd.Prompt = null;
dsd.UserName = this.txtUserName.Text;
dsd.Password = this.txtPassword.Text;
dsd.WindowsCredentials = false;
//创建数据源
rs.CreateDataSource(this.txtDataSourceName.Text, "/" + this.txtServerPath.Text, true, dsd, null);
//创建报表资源文件
CreateReportResource(this.txtLocalPath.Text, "/" + this.txtServerPath.Text, rs);
IList<ReportItem> rsfiles = GetCheckReport();
IList<ReportItem> sReports = new List<ReportItem>();
Warning[] w = null;
byte[] def = null;
string p = this.txtLocalPath.Text.Trim();
if (!p.EndsWith("\\"))
p += "\\";
foreach (ReportItem f in rsfiles)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (System.IO.File.Exists(p + f.EnglishName))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
string strPath = p + f.EnglishName;
System.IO.FileStream st = System.IO.File.OpenRead(strPath);
def = new byte[st.Length];
st.Read(def, 0, (int)st.Length);
st.Close();
//创建报表
w = rs.CreateReport(f.EnglishName, "/" + this.txtServerPath.Text, true, def, null);
sReports.Add(f);
}
}
ChangeDataSource("/" + txtServerPath.Text, txtDataSourceName.Text, rs);
if (sReports.Count > 0)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//修改导航树
ModifyNavigateTree(sReports, this.txtWebSevice.Text.Trim(), this.txtServerPath.Text.Trim());
}
this.lberror.Text = "报表发布成功!";
this.lberror.Visible = true;
}
catch (Exception ex)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.lberror.Text += ex.Message;
this.lberror.Visible = true;
}
}
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
创建报表资源#region 创建报表资源
private void CreateReportResource(string localCategory, string ParentFolder, ReportingService _rs)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
string[] imgs = System.IO.Directory.GetFiles(localCategory, "*.png");
byte[] byteImage = null;
foreach (string i in imgs)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
int posInt = i.LastIndexOf("\\");
System.IO.FileStream fs = System.IO.File.OpenRead(i);
byteImage = new byte[fs.Length];
fs.Read(byteImage, 0, (int)fs.Length);
fs.Close();
_rs.CreateResource(i.Substring(posInt + 1), ParentFolder, true, byteImage, "image/png", null);
//需要注意的是CreateResource方法的第一个参数,资源名称是要包含后缀的(如:picture.png")
//"image/png"这个是资源类型,因为我的资源是png图片所以是"image/png".
}
}
#endregion
#region修改报表数据源
//因为在做报表的时候和添加报表的时候数据源可能会不一样,所以这里特意写了方法来修改之前的报表数据源.
private void ChangeDataSource(string folderPath, string dataSourceName, ReportingService _rs)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/InBlock.gif)
DataSourceReference dsr = new DataSourceReference();
dsr.Reference = folderPath + "/" + dataSourceName;
CatalogItem[] items = _rs.ListChildren(folderPath, false);
foreach (CatalogItem item in items)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (item.Type == ItemTypeEnum.Report)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//获取报表数据源
DataSource[] dss = _rs.GetReportDataSources(item.Path);
foreach (DataSource d in dss)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
d.Item = dsr;
}
_rs.SetReportDataSources(item.Path, dss);
}
}
![](/Images/OutliningIndicators/InBlock.gif)
}
#endregion
protected void btnCatelog_Click(object sender, EventArgs e)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (!string.IsNullOrEmpty(this.txtLocalPath.Text))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
string[] rptFiles = System.IO.Directory.GetFiles(this.txtLocalPath.Text, "*.xml");
if (rptFiles.Length > 0)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
XmlDocument doc = new XmlDocument();
doc.Load(rptFiles[0]);
XmlNodeList xlist = doc.DocumentElement.ChildNodes;
this.rpterReports.DataSource = xlist;
this.rpterReports.DataBind();
}
}
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
获取选中的报表#region 获取选中的报表
private IList<ReportItem> GetCheckReport()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
IList<ReportItem> alist = new List<ReportItem>();
for (int i = 0; i < this.rpterReports.Items.Count; i++)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
HtmlInputCheckBox chk = this.rpterReports.Items[i].FindControl("chkRprt") as HtmlInputCheckBox;
Label lbChName = this.rpterReports.Items[i].FindControl("lbChName") as Label;
Label lbsub = this.rpterReports.Items[i].FindControl("lbsub") as Label;
if (chk != null && chk.Checked && lbChName != null && !string.IsNullOrEmpty(lbChName.Text) && lbsub != null)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
alist.Add(new ReportItem(lbChName.Text.Trim(), chk.Value.ToString(), Convert.ToBoolean(lbsub.Text)));
}
}
return alist;
![](/Images/OutliningIndicators/InBlock.gif)
}
#endregion
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
修改导航树#region 修改导航树
![](/Images/OutliningIndicators/InBlock.gif)
private void ModifyNavigateTree(IList<ReportItem> slist, string rpturl, string sFoloder)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
string strUrl = rpturl.Trim() + "/ReportServer/Pages/ReportViewer.aspx?%2f" + sFoloder + "%2f";
if (slist.Count > 0 && System.IO.File.Exists(Server.MapPath(@"SiteMap\treeData.xml")))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/InBlock.gif)
XmlDocument xdoc = new XmlDocument();
xdoc.Load(Server.MapPath(@"SiteMap\treeData.xml"));
XmlNode xnode = xdoc.DocumentElement.LastChild;
foreach (ReportItem i in slist)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (!i.IsSubReport)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
XmlElement newElement = xdoc.CreateElement("item");
newElement.SetAttribute("Text", i.ChineseName);
newElement.SetAttribute("IsReport", "report");
//这个地方要注意的是:&符号在xml文件的表示,之前我把&换成&结果修改xml文件保存后,发现报表的url地址还是不对.后面,换成@"&rs.."就可以了.
newElement.SetAttribute("Url", strUrl.Trim() + i.EnglishName.Trim() + @"&rs:Command=Render&ghsbh=");
xnode.AppendChild(newElement);
}
}
xdoc.Save(Server.MapPath(@"SiteMap\treeData.xml"));
}
}
#endregion
}
}
![](/Images/OutliningIndicators/None.gif)
总结以下需要主要的几个地方:
1.创建报表资源的时候,需要注意的是CreateResource方法的第一个参数,资源名称是要包含后缀的(如:picture.png"),否则,浏览的时候资源出来不,因为我的资源是png图片所以是"image/png".
2.因为我做的时候,在添加报表的时候,可以修改数据源,所以写了ChangeDataSource方法把每个报表的数据源设置成一样的
3.修改导航树的时候(如果有导航菜单xml文件),要注意的是:&符号在xml文件的表示,之前我把&换成&结果修改xml文件保存后,发现报表的url地址还是不对.后面,换成@"&rs.."就可以了.
4.如果有嵌套子报表的话,那么还修改母报表和子报表的rdl文件,否则嵌套的子报表出来.子报表也返回不到母报表了.
觉得有几个地方不是很好:
1,维护报表目录下的xml文件比较麻烦点,以后每添加报表都要有个相应的xml文件
2,“获取报表”按钮如果能做成,文件夹打开对话框那种形式,那操作性更好一些。
以上问题,我还没想到怎么做才好?