Chr☆s Kwok 的技术笔记

.NET, C#, WPF, WCF, WF, .NetCore & LINQ ... I know how it works because I know why it works ...

博客园 首页 新随笔 订阅 管理

1、 对Table中的详细内容,以不同的背景色间隔开相邻的两行:
A:选择Table的Detail行,选择属性中的BackgroundColor,值选择表达式,输入:=iif(RowNumber(Nothing) Mod 2, "White", "Beige")。组内设置不同底色则将Nothing改为相应的组名,如“Table1_Group1”,这是遇到偶数行设置背景色Beige,注意表达式RowNumber(Nothing) Mod 2省略了判定符">0"(默认=0为Flale, 否则为True);
B:另外方案:可以设置单元格属性BordStyle -> Bottom为表达式 =IIF((RowNumber(Nothing) Mod 6 = 5) OR (RowNumber(Nothing) Mod 6 = 0), "Solid", "None"),这是对于有两个列组的数据行,每隔3行设置边框底线为Solid,否则为None(默认边框都为None);

2、仅在组的外边框设置线颜色的方法(纵向合并单元格):
A:设置BorderStyle -> Bottom表达式为:=iif(RowNumber("Table1_Group1") = CountRows("Table1_Group1") , "White", "Beige");

3、报表的行组和列组设计(行组可以做分类/小计显示; 列组可以进行分栏显示,如示例中的两栏,每栏内3列):
(1)定义行组和子行组



(2)定义列组

(3)单元格边框样式设计

(4)展现效果

4、报表常常需要用到参数起始日期和结束日期,并且需要将起始日期默认为本月第一天,结束日期默认为本月最后一天:
参数OccurDateFrom的默认值设置为表达式=DateAdd("d", 1-Day(Today), Today);参数OccurDateTo的默认值设置为表达式=DateAdd("d", -1, DateSerial(IIf(Month(Today)=12,Year(Today)+1,Year(Today)), IIf(Month(Today)=12,1,Month(Today)+1), 1))就能满足需求咯;

5、在同一张报表上显示数据报表和图表(如直方图),并且根据“显示直方图”参数切换:
新增参数IsShowChart(Boolean型),默认值=false;然后将报表(Table1)和图表(Chart1)的Location设置为一样;
Table1的Visibility.Hidden设置为表达式=Parameters!IsShowChart.Value;Chart1的Visibility.Hidden设置为表达式=Not Parameters!IsShowChart.Value就可以实现根据参数切换报表和图表了;

6、设置每页显示Table表头或表尾:
A:选择Table Header或Table Footer,将属性中的RepeatOnNewpage设为True;

7、在每页都显示放入的图片或标题头等信息:
A:只须在Table Header中加行数,把你要显示的内容放到单元格中,然后再按第 5 点方式设置后就可以了;

8、报表插入图片的方法:
A:需要将插入的图像报表项的Source属性设置为extern,且将Value设置文件全路径(且以file://打头),譬如:file://E:/VSTS/SSRS/ReportServiceClient/Wave.jpg;并且需设置reportViewer1.LocalReport.EnableExternalImages = true;

B:对于动态获取图片则需要将Source属性设置为DataBase,Value=System.Convert.FromBase64String(Fields!BarCode.Value),上面示例是按数据源的属性BarCode(string类型),类属性代码见下面:

public string BarCode
{
get
{
BarcodeLib.Barcode b
= new BarcodeLib.Barcode();
b.IncludeLabel
= true;
Image img
= b.Encode(BarcodeLib.TYPE.CODE39, BillNo);
return Convert.ToBase64String(BitmapToBytes(img as Bitmap));
}
}
private byte[] BitmapToBytes(Bitmap Bitmap)
{
MemoryStream ms
= null;
try
{
ms
= new MemoryStream();
Bitmap.Save(ms, ImageFormat.Gif);
byte[] byteImage = new Byte[ms.Length];
byteImage
= ms.ToArray();
return byteImage;
}
catch (ArgumentNullException ex)
{
throw ex;
}
finally
{
ms.Close();
}
}


9、
获取参数列表的方法
首先添加web引用:http://server/reportserver/reportservice.asmx

        private RS2005.ReportParameter[] GetReportParameters(string url, string reportPath)
        {
            
//获取参数的方法之二(不能获取元数据)
            RS2005.ReportingService rService = new RS2005.ReportingService();//创建报表服务实例
            rService.Credentials = System.Net.CredentialCache.DefaultCredentials;//设置默认系统凭据

            rService.Url 
= url;
            
string historyID = null;
            
bool forRendering = true;
            RS2005.ParameterValue[] values 
= null;
            RS2005.DataSourceCredentials[] credentials 
= null;
            RS2005.ReportParameter[] parameters;
            parameters 
= rService.GetReportParameters(reportPath, historyID, forRendering, values, credentials);
            
return parameters;
        }


10、获取参数及其元数据(如参数的默认值表达式等):

private Dictionary<stringstring> GetReportParamtersDefaultValue(string url, string reportPath)
{
    Report report 
= null;
    RS2005.ReportingService rService 
= new RS2005.ReportingService();//创建报表服务实例
    rService.Credentials = System.Net.CredentialCache.DefaultCredentials;//设置默认系统凭据
    rService.Url = url;
    
byte[] bytes = rService.GetReportDefinition(reportPath);
    
if (bytes != null)
    {
        XmlSerializer serializer 
= new XmlSerializer(typeof(Report));
        
using (MemoryStream stream = new MemoryStream(bytes))
        {
            report 
= (Report)serializer.Deserialize(stream);
        }
    }
    List
<ItemsChoiceType37> reportItems = new List<ItemsChoiceType37>(report.ItemsElementName);
    
int index = reportItems.IndexOf(ItemsChoiceType37.ReportParameters);
    ReportParametersType parametersType 
= report.Items[index] as ReportParametersType;
    Dictionary
<stringstring> ps = new Dictionary<stringstring>();
    
foreach (ReportParameterType item in parametersType.ReportParameter)
    {
        ps.Add(item.Name, 
string.Empty);

        List
<ItemsChoiceType33> rptItems = new List<ItemsChoiceType33>(item.ItemsElementName);
        index 
= rptItems.IndexOf(ItemsChoiceType33.DefaultValue);
        DefaultValueType dvt 
= item.Items[index] as DefaultValueType;

        ValuesType vt 
= dvt.Items[0as ValuesType;
        ps[item.Name] 
= vt.Value[0];
    }
    
return ps;
}
 

11、遍历报表项的方法:
首先添加web引用:http://server/reportserver/reportservice.asmx

ReportingService rService = new ReportingService();//创建报表服务实例
rService.Credentials = System.Net.CredentialCache.DefaultCredentials;//默认系统凭据
CatalogItem[] catalogItems;
catalogItems 
= rService.ListChildren("/"true);//对根路径检索
foreach(CatalogItem item in catalogItems)
{
    
if(item.Type ==ItemTypeEnum.Folder)
  {
    
//遍历报表文件夹
  }
}
 
foreach(CatalogItem item in catalogItems)
{
  
if(item.Type ==ItemTypeEnum.Report)
  {
    
//遍历报表
  }
}

//搜索报表
ReportService.SearchCondition[] condition=new SearchCondition[1];
condition[
0]=new SearchCondition();
condition[
0].Name ="Name";
condition[
0].Value =this.TextBox1.Text ;
catalogItems
=rs.FindItems ("/",WebReportSample.ReportService .BooleanOperatorEnum .And ,condition);

//发布报表
byte[] reportData;
System.IO .FileStream fs
=System.IO .File.OpenRead ("c:\\Report1.rdl");
reportData
=new byte [fs.Length ];
fs.Read (reportData,
0,fs.Length );
rs.CreateReport (
"New Report","/",false,reportData,null);

//删除报表
rs.DeleteItem ("报表名称");


12、子报表部署问题:

由于主报表中跳转到子报表或嵌入子报表时仅设置子报表名称,所以部署时必须确保子报表与主报表的路径一致;

13、使用LocalReport.LoadSubreportDefinition 方法应注意的问题是如果主报表是通过ReportPath属性获取的则该方法将失效,原因是设置ReportPath的报表通过文件系统获取报表定义元数据时也一并加载了它需要的子报表定义元数据。可以看看MSDN的备注,换言之,使用该方法前必须使用LocalReport.LoadReportDefinition 方法,且不能设置ReportPath。
原文描述如下:The ReportViewer control requires the definitions for all subreports before it can process a report. If the local report was loaded from the file system by specifying the ReportPath property, the ReportViewer control automatically loads the subreports from the file system. In cases where the local report was not loaded from the file system, these methods may be used to load report definitions for subreports.

14、报表的无会话打印问题,报表定义文件没有设置“打印方向”的属性,实际上如果需要打印横向报表需要在创建PrintDocument时设置打印机参数,并且读取deviecInfo信息时需要将报表定义文件的PageWidth和PageHeight互换下,参考代码如下:

public class EmfPrintDocument : PrintDocument
{
    
private EmfPrintDocument(PrinterInfo printerInfo)
    {
        
base.PrinterSettings.PrinterName = printerInfo.PrinterName;
        
base.DefaultPageSettings.Landscape = printerInfo.Landscape;
        
base.PrinterSettings.DefaultPageSettings.Landscape = printerInfo.Landscape;
    }

        
public static EmfPrintDocument Create(PrinterInfo printerInfo)
        {
            
if (string.IsNullOrEmpty(printerInfo.PrinterName))
            {
                printerInfo.PrinterName 
= Printer.GetDeaultPrinterName();
            }
            
else
            {
                
bool founded = false;

                
foreach (string pname in PrinterSettings.InstalledPrinters)
                {
                    
if (pname.Equals(printerInfo.PrinterName, StringComparison.CurrentCultureIgnoreCase))
                    {
                        printerInfo.PrinterName 
= pname;
                        founded 
= true;
                        
break;
                    }
                }

                
if (!founded)
                {
                    
throw new NotSupportedException(string.Format("找不到打印机 {0}" + printerInfo.PrinterName));
                }
            }
            
return new EmfPrintDocument(printerInfo);
        }
}

ReportPrintService的代码:

查看代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Reporting.WinForms;
using System.IO;
using System.Drawing.Printing;
using System.Drawing.Imaging;
using System.Xml;
using System.Xml.Serialization;
using JetSun.Presentation;
using JetSun.Core.Library.Reports;
using JetSun.Infrastructure;

namespace JetSun.Core.Library.Reports
{
    internal class ReportPrintService : IDisposable
    {
        private static IList<Stream> _streams;
        private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
        {
            //Stream stream = new FileStream(Application.StartupPath + @"\" + name + "." + fileNameExtension, FileMode.Create);
            Stream stream = new MemoryStream();
            _streams.Add(stream);
            return stream;
        }

        private void Export(LocalReport report)
        {
            string deviceInfo = LoadDeviceInfo(report.ReportPath);
            Warning[] warnings;
            _streams = new List<Stream>();
            report.Render("Image", deviceInfo, CreateStream, out warnings);

            foreach (Stream stream in _streams)
                stream.Position = 0;
        }

        private List<ItemsChoiceType37> _reportItems;
        private string LoadDeviceInfo(string reportPath)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Report));
            _report = (Report)serializer.Deserialize(this.GenerateRdlc(reportPath));
            _reportItems = new List<ItemsChoiceType37>(_report.ItemsElementName);

            string deviceInfo =
              "<DeviceInfo>" +
              "  <OutputFormat>EMF</OutputFormat>" +
              "  <PageWidth>" + (_printerInfo.Landscape ? GetReportItem(ItemsChoiceType37.PageHeight) : GetReportItem(ItemsChoiceType37.PageWidth)) + "</PageWidth>" +
              "  <PageHeight>" + (_printerInfo.Landscape ? GetReportItem(ItemsChoiceType37.PageWidth) : GetReportItem(ItemsChoiceType37.PageHeight)) + "</PageHeight>" +
              "  <MarginTop>" + GetReportItem(ItemsChoiceType37.TopMargin) + "</MarginTop>" +
              "  <MarginLeft>" + GetReportItem(ItemsChoiceType37.LeftMargin) + "</MarginLeft>" +
              "  <MarginRight>" + GetReportItem(ItemsChoiceType37.RightMargin) + "</MarginRight>" +
              "  <MarginBottom>" + GetReportItem(ItemsChoiceType37.BottomMargin) + "</MarginBottom>" +
              "</DeviceInfo>";

            //_printDoc.PrinterSettings.PrinterName = _printerInfo.PrinterName;
            //_printDoc.DefaultPageSettings.Landscape = _printerInfo.Landscape;
            //_printDoc.PrinterSettings.DefaultPageSettings.Landscape = _printerInfo.Landscape;

            return deviceInfo;
        }

        private MemoryStream GenerateRdlc(string reportPath)
        {
            XmlDocument sourceDoc = new XmlDocument();
            sourceDoc.Load(reportPath);

            MemoryStream ms = new MemoryStream();
            XmlSerializer serializer = new XmlSerializer(typeof(XmlDocument));
            serializer.Serialize(ms, sourceDoc);
            ms.Position = 0;
            return ms;
        }

        private string GetReportItem(ItemsChoiceType37 element)
        {
            int ix = _reportItems.IndexOf(element);
            if (ix == -1) return "0.0cm";

            return _report.Items[ix].ToString();
        }

        private void PrintPage(object sender, PrintPageEventArgs ev)
        {
            Metafile pageImage = new Metafile(_streams[_currentPageIndex]);
            ev.Graphics.DrawImage(pageImage, ev.PageBounds);

            _currentPageIndex++;
            ev.HasMorePages = (_currentPageIndex < _streams.Count);
        }

        private int _currentPageIndex;
        private void DoPrint()
        {
            if (_streams == null || _streams.Count == 0)
                return;

            _currentPageIndex = 0;
            _printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
            _printDoc.Print();
        }

        private Report _report;
        private EmfPrintDocument _printDoc;
        private PrinterInfo _printerInfo;
        public void Print(LocalReport report, PrinterInfo printerInfo)
        {
            _printDoc = EmfPrintDocument.Create(printerInfo);
            _printerInfo = printerInfo;

            Export(report);

            DoPrint();
        }

        public void Dispose()
        {
            if (_streams != null)
            {
                foreach (Stream stream in _streams)
                    stream.Close();
                _streams = null;
            }
        }
    }
}

使用实例:

Code
using (ReportPrintService rps = new ReportPrintService())
{
    rps.Print(lp, printerInfo);
}

15、服务器报表的方法SetParameters() 需要注意的问题:
(1)多值参数的类型是StringCollection而不是一个用逗号间隔的串;
(2)传入的参数值如果在服务器报表的参数数据源中不存在该方法将报错(报表的所有参数赋默认值);
(3)ReportViewer控件使用过程中如果发现展现出来的报表背景色全部变成了黑色,则需要将承载该控件的WindowsFormsHost设置其Background属性设置为White;
(4)导出pdf时可能遇到导出的内容为????,需要修改下字体为“宋体”或其他基本字体;如果报表包含子报表则子报表无法导出内容

posted on 2009-09-17 00:10  Chr☆s  阅读(5240)  评论(0编辑  收藏  举报