利用XML实现通用WEB报表打印(4)

 最后,我们还需要一个解析器用来解析顶层的标签和生成相应的对象,它在此模式中的作用就是一个"工厂类",负责生产出用户需要的"产品"。代码如下:

using System;
using System.Xml;

namespace RemotePrint
{
public class Parser
{
public Parser()
{
}
public static PrintElement CreateElement(XmlNode element)
{
PrintElement printElement = null;
switch(element.Name)
{
case "text":
printElement = new Text(element);
break;
case "table":
printElement = new Table(element);
break;
default:
printElement = new PrintElement();
break;
}
return printElement;
}
}
}

  好了,核心的解析和标签的具体打印方法已经完成了,现在我们回到PrintControl中编写一些代码来测试我们的成果。

  首先,需要引用两个要用到的名称空间:

using System.Xml;

using System.Drawing.Printing;

  然后,在打印之前,需要根据XML文件中的pagesetting标签来设置一下打印机的页面,所以我们先写一个方法来设置打印机。在PrintControl类中增加一个私有的方法:

private void SettingPrinter(XmlNode ps)
{
file://打印方向(纵/横)
this.printDocument1.DefaultPageSettings.Landscape = bool.Parse(ps["landscape"].InnerText);
file://设置纸张类型
string papername = ps["paperkind"].InnerText;
bool fitpaper = false;
file://获取打印机支持的所有纸张类型
foreach(PaperSize size in this.printDocument1.PrinterSettings.PaperSizes)
{
if(papername == size.PaperName)//看该打印机是否有我们需要的纸张类型
{
this.printDocument1.DefaultPageSettings.PaperSize = size;
fitpaper = true;
}
}
if(!fitpaper)
{
file://假如没有我们需要的标准类型,则使用自定义的尺寸
this.printDocument1.DefaultPageSettings.PaperSize =
new PaperSize("Custom", int.Parse(ps["paperwidth"].InnerText),
int.Parse(ps["paperheight"].InnerText));
}
}

  接下来,我们类中添加一个XmlDocument的对象和一个静态变量计算页码:

private XmlDocument doc = new XmlDocument();

public static int Pages = 1;

  然后再控件的Load事件中为该对象加载XML报表数据,代码如下:

private void PrintControl_Load(object sender, System.EventArgs e)
{
try
{
file://装载报表XML数据
this.label1.Text = "正在加载报表数据,请稍侯...";
doc.Load("http://localhost/report.xml");
this.label1.Text = "报表数据加载完毕!";
this.button1.Enabled = this.button2.Enabled = this.button3.Enabled = true;
}
catch(Exception ex)
{
this.label1.Text = "出现错误:" + ex.Message;
}
}

  请注意,我们这里只是装入了一个本地的测试数据文件,其实,完全可以改成装载网络上任何地方的静态或者动态的XML文件,例如以上的doc.Load("http://localhost/report.xml")可以改写成:

doc.Load("http://www.anywhere.com/report.xml");

doc.Load("http://www.anywhere.com/report.asp");

doc.Load("http://www.anywhere.com/report.jsp?date=xxx");

  等等,只要装载的数据是符合我们规定的XML数据文档就可以。

  然后在控件的构造函数中加入打印事件的委托:

public PrintControl()

{

InitializeComponent();

this.printDocument1.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);

}

  该委托方法的代码如下:

private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
Graphics g = ev.Graphics;
bool HasMorePages = false;
PrintElement printElement = null;

foreach(XmlNode node in doc["root"]["reporttable"].ChildNodes)
{
printElement = Parser.CreateElement(node);//调用解析器生成相应的对象
try
{
HasMorePages = printElement.Draw(g);//是否需要分页
}
catch(Exception ex)
{
this.label1.Text = ex.Message;
}
}

file://在页底中间输出页码
Font font = new Font("黑体", 12.0f);
Brush brush = new SolidBrush(Color.Black);
g.DrawString("第 " + Pages.ToString() + " 页",
font,brush,ev.MarginBounds.Width / 2 + ev.MarginBounds.Left - 30,
ev.PageBounds.Height - 60);

if(HasMorePages)
{
Pages++;
}
ev.HasMorePages = HasMorePages;
}

  三个按纽的Click事件代码分别如下:

//页面设置
private void button1_Click(object sender, System.EventArgs e)
{
this.pageSetupDialog1.ShowDialog();
this.printDocument1.DefaultPageSettings = this.pageSetupDialog1.PageSettings;
}
file://打印预览
private void button2_Click(object sender, System.EventArgs e)
{
try
{
this.printPreviewDialog1.ShowDialog();
}
catch(Exception ex)
{
this.label1.Text = ex.Message;
}
}
file://打印
private void button3_Click(object sender, System.EventArgs e)
{
try
{
this.printDocument1.Print();
}
catch(Exception ex)
{
this.label1.Text = ex.Message;
}
}

  好了,我们的打印控件到这里就全部做完了,选择生成一个Release的版本,然后到工程目录下将生成的PrintControl.dll文件拷贝到IIS的虚拟根目录下,然后新建一个remoteprint.htm的HTML格式文件,在合适的地方加上:<object id="print" classid="http:RemotePrint.dll#RemotePrint.PrintControl" Width="100%" Height="60"> </object>,为了更加形象和美观,还可以将需要打印的数据做成网页形式放在上面,如果需要获取的XML是动态数据源,则可以采用asp等动态脚本来生成该网页表格,如果需要获取的XML是一个静态的文本,则可以采用XSLT直接将XML文件转换成网页表格。

  打开浏览器,输入:http://localhost/remoteprint.htm,如果您已经跟我一样,事先做好了一个XML报表数据文件的话,您就可以看到下图所示的效果

  

  请注意:该图示例中的所有数据均为笔者随意虚拟,网页中的表格数据和打印数据并非来自同一数据源,也没有刻意去对等,仅仅只是为了演示一下效果,因此网页显示报表跟打印预览中的报表有一些出入是正常的。在实际应用中可以让网页显示数据跟打印输出数据完全一致。

你可能感兴趣的:(一些好的技术资料,报表,xml,web,exception,object,file)