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

转载 2004年08月27日 12:37:00
方案扩充:

  那么如何打印一些特殊形态的图表,前文中已经提到,采用本方案可以非常方便的定义出自己所需要的标签,在理论上可以打印出任何样式的特殊图表。因此本文打算详细介绍一下增加自己定义的标签扩充打印格式的具体过程。

  先假设我们的客户看了打印效果后基本上满意,但是还有觉得一点不足,如果需要打印一些图表怎么办?例如折线图、K线图、饼状图、柱状图等等。使用我们现有的标签就不行了,所以我们首先要扩充我们的标签库,让它的表达能力更加强。在这里,我将只打算让我们的打印控件学会画简单的折线图,希望读者能举一反三,创造出其它各种各样的打印效果。

  最基本的折线图是由X坐标轴、Y坐标轴和一系列点连接成的线构成的,因此,我定义了以下几种标签:

  1. linechart:跟table,text标签一样,为样式根标签。

   属性:无

  2. coordinate:坐标。

   属性:无

  3. xcoordinate:X轴坐标线

   属性:

   # x:起点X坐标值

   # y:起点Y坐标值

   # length:长度值

   # stroke:粗细

   # color:颜色

   # arrow:是否有箭头

  4. ycoordinate:Y轴坐标线

   属性:同xcoordinate。

  5.scale:刻度线

   标签内容:显示在刻度边的文字

   属性:

   # length:距离起点长度值

   # height:刻度线高度

   # width:刻度线宽度

   # color:颜色

   # fontsize:字体大小

  6.chart:图表根

   属性:无

  7.lines:线段

   属性值:

   # stroke:粗细

   # color:颜色

  8. point:点

   属性值:

   # x:X坐标值

   # y:Y坐标值

   # radius:半径

   # color:颜色

  其结构图如下所示:

jt-030214-1-xmlwebprint8.jpg


  下面是一段用刚才定义的标签制作的XML折线图示例:

<linechart>

<coordinate>

<xcoordinate x="200" y="600" length="800" stroke="2" color="Black" arrow="true">

<scale length="100" height="10" width="1" color="Black" fontsize="9">100</scale>

<scale length="200" height="10" width="1" color="Black" fontsize="9">200</scale>

<scale length="300" height="10" width="1" color="Black" fontsize="9">300</scale>

<scale length="400" height="10" width="1" color="Black" fontsize="9">400</scale>

<scale length="500" height="10" width="1" color="Black" fontsize="9">500</scale>

<scale length="600" height="10" width="1" color="Black" fontsize="9">600</scale>

<scale length="700" height="10" width="1" color="Black" fontsize="9">700</scale>

</xcoordinate>

<ycoordinate x="200" y="600" length="-400" stroke="2" color="Black" arrow="true">

<scale length="-100" height="10" width="1" color="Black" fontsize="9">100</scale>

<scale length="-200" height="10" width="1" color="Black" fontsize="9">200</scale>

<scale length="-300" height="10" width="1" color="Black" fontsize="9">300</scale>

</ycoordinate>

</coordinate>

<chart>

<lines stroke="1" color="Blue">

<point x="200" y="600" radius="5" color="Black"/>

<point x="300" y="300" radius="5" color="Black"/>

<point x="400" y="400" radius="5" color="Black"/>

<point x="500" y="500" radius="5" color="Black"/>

<point x="600" y="300" radius="5" color="Black"/>

<point x="700" y="300" radius="5" color="Black"/>

<point x="800" y="600" radius="5" color="Black"/>

<point x="900" y="500" radius="5" color="Black"/>

</lines>

<lines stroke="1" color="Red">

<point x="200" y="400" radius="5" color="Black"/>

<point x="300" y="500" radius="5" color="Black"/>

<point x="400" y="600" radius="5" color="Black"/>

<point x="500" y="300" radius="5" color="Black"/>

<point x="600" y="400" radius="5" color="Black"/>

<point x="700" y="400" radius="5" color="Black"/>

<point x="800" y="500" radius="5" color="Black"/>

<point x="900" y="300" radius="5" color="Black"/>

</lines>

</chart>

</linechart>

  完成了标签的定义,下一步就要来修改我们的程序,让他能"读懂"这些标签。

  首先,我们先给工程增加一个LineChart的新类,跟Table,Text类一样,它也是继承自PrintElement类,同样重载了Draw虚方法。代码如下:

using System;
using System.Xml;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace RemotePrint
{
public class LineChart : PrintElement
{
private XmlNode chart;
public LineChart(XmlNode Chart)
{
chart = Chart;
}
public override bool Draw(Graphics g)
{
DrawCoordinate(g, chart["coordinate"]);//画坐标轴
DrawChart(g, chart["chart"]);
return false;
}
private void DrawCoordinate(Graphics g, XmlNode coo)
{
DrawXCoor(g, coo["xcoordinate"]);//画X坐标
DrawYCoor(g, coo["ycoordinate"]);//画Y坐标
}
private void DrawXCoor(Graphics g, XmlNode xcoo)
{
int x = int.Parse(xcoo.Attributes["x"].InnerText);
int y = int.Parse(xcoo.Attributes["y"].InnerText);
int length = int.Parse(xcoo.Attributes["length"].InnerText);
bool arrow = bool.Parse(xcoo.Attributes["arrow"].InnerText);
int stroke = int.Parse(xcoo.Attributes["stroke"].InnerText);
Color color = Color.FromName(xcoo.Attributes["color"].InnerText);
Pen pen = new Pen(color, (float)stroke);
if(arrow)//是否有箭头
{
AdjustableArrowCap Arrow = new AdjustableArrowCap(
(float)(stroke * 1.5 + 1.5),
(float)(stroke * 1.5 + 2), true);
pen.CustomEndCap = Arrow;
}
g.DrawLine(pen, x, y, x + length, y);//画坐标
file://画刻度
foreach(XmlNode scale in xcoo.ChildNodes)
{
int len = int.Parse(scale.Attributes["length"].InnerText);
int height = int.Parse(scale.Attributes["height"].InnerText);
int width = int.Parse(scale.Attributes["width"].InnerText);
int fontsize = int.Parse(scale.Attributes["fontsize"].InnerText);
Color clr = Color.FromName(scale.Attributes["color"].InnerText);
string name = scale.InnerText;

Pen p = new Pen(clr, (float)width);
g.DrawLine(p, x + len, y, x + len, y - height);
Font font = new Font("Arial", (float)fontsize);
g.DrawString(
name, font, new SolidBrush(clr),
(float)(x + len - 10), (float)(y + 10));
}
}
private void DrawYCoor(Graphics g, XmlNode ycoo)
{
int x = int.Parse(ycoo.Attributes["x"].InnerText);
int y = int.Parse(ycoo.Attributes["y"].InnerText);
int length = int.Parse(ycoo.Attributes["length"].InnerText);
bool arrow = bool.Parse(ycoo.Attributes["arrow"].InnerText);
int stroke = int.Parse(ycoo.Attributes["stroke"].InnerText);
Color color = Color.FromName(ycoo.Attributes["color"].InnerText);
Pen pen = new Pen(color, (float)stroke);
if(arrow)//是否有箭头
{
AdjustableArrowCap Arrow = new AdjustableArrowCap(
(float)(stroke * 1.5 + 2),
(float)(stroke * 1.5 + 3),
true);
pen.CustomEndCap = Arrow;
}
g.DrawLine(pen, x, y, x, y + length);//画坐标
file://画刻度
foreach(XmlNode scale in ycoo.ChildNodes)
{
int len = int.Parse(scale.Attributes["length"].InnerText);
int height = int.Parse(scale.Attributes["height"].InnerText);
int width = int.Parse(scale.Attributes["width"].InnerText);
int fontsize = int.Parse(scale.Attributes["fontsize"].InnerText);
Color clr = Color.FromName(scale.Attributes["color"].InnerText);
string name = scale.InnerText;
Pen p = new Pen(clr, (float)width);
g.DrawLine(p, x, y + len, x + height, y + len);
Font font = new Font("Arial", (float)fontsize);
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Far;
RectangleF rect = new RectangleF(
(float)(x - 100),
(float)(y + len - 25),
90f,
50f);
sf.LineAlignment = StringAlignment.Center;
g.DrawString(name, font, new SolidBrush(clr), rect, sf);
}
}
private void DrawChart(Graphics g, XmlNode chart)
{
foreach(XmlNode lines in chart.ChildNodes)
{
DrawLines(g, lines);
}
}
private void DrawLines(Graphics g, XmlNode lines)
{
int Stroke = int.Parse(lines.Attributes["stroke"].InnerText);
Point[] points = new Point[lines.ChildNodes.Count];
Color linecolor = Color.FromName(lines.Attributes["color"].InnerText);
for(int i = 0; i < lines.ChildNodes.Count; i++)
{
XmlNode node = lines.ChildNodes[i];
points[i] = new Point(
int.Parse(node.Attributes["x"].InnerText),
int.Parse(node.Attributes["y"].InnerText));
int Radius = int.Parse(node.Attributes["radius"].InnerText);
Color pointcolor = Color.FromName(node.Attributes["color"].InnerText);
if(Radius != 0)//画点
{
g.FillEllipse(new SolidBrush(pointcolor),
points[i].X - Radius,
points[i].Y - Radius,
Radius * 2,
Radius * 2);
}
}
Pen pen = new Pen(linecolor);
g.DrawLines(pen, points);//画线
}
}
}

  然后,为Parser类的CreateElement方法增加一个小case,代码如下:

switch(element.Name)
{
case "text":
printElement = new Text(element);
break;
case "table":
printElement = new Table(element);
break;
case "linechart"://新增加的linechart
printElement = new LineChart(element);
break;
default:
printElement = new PrintElement();
break;
}

  将原来的XML文件中的table标签和其子标签都替换成刚才写的那段linechart,然后编译程序,运行后效果如下所示:

jt-030214-1-xmlwebprint9.jpg

  现在,我们的打印控件就能打印折线图了,由于我们采用了Abstract Factory的设计模式,将报表的打印和格式的解析分开,使得本程序有着非常方便的扩充能力,如果需要再增加一种新形式的图表,那么需要定义出标签,写一个解析类,再到Paser中为这个类增加一个case就搞定了,PrintControl内部的代码一行都不需要改写。

Java报表工具打印方案对比

本文试图对市面上流行的纯java实现的web报表工具,jasperreport 、 stylereport 、杰表、润乾报表、快逸、finererport为例,分析各报表工具采用的web打印技术的...
  • rdhj5566
  • rdhj5566
  • 2017年04月26日 19:07
  • 1402

几种web报表打印方案的比较

文章转自:http://www.cnblogs.com/webreport/archive/2007/06/28/798998.html web报表打印通常是系统的辅助部分,但是又必须解决,否则...
  • qq_21909121
  • qq_21909121
  • 2016年08月03日 09:53
  • 1720

使用POI实现报表打印功能

这篇文章主要分享的是使用apache的poi来实现数据导出到excel的功能,这里提供三种解决方案。你可以使用最原始最简单的一步步添加样式或者数据,你也可以通过一个模板来进行模板化。POI支持微软的O...
  • sdksdk0
  • sdksdk0
  • 2016年11月29日 15:34
  • 3288

利用XML实现通用WEB报表打印

  • 2005年11月15日 15:25
  • 264KB
  • 下载

利用XML实现通用WEB报表打印

专栏作品 利用XML实现通用WEB报表打印http://www.microsoft.com/china/community/Column/65.mspx 卢彦 方案适用性 . 1...
  • ilvu999
  • ilvu999
  • 2012年02月15日 11:58
  • 373

续:利用XML实现通用WEB报表打印(实现篇) 卢彦

引言:在《利》刊出后,有大量的读者发E-Mail给我表示对该方案非常感兴趣,同时还询问具体如何实现报表格式的解析和打印细节并索取该程序的源代码。读者的热情让我始料未及,虽然我一一对来信进行解答和发送了...
  • liuyunfan
  • liuyunfan
  • 2011年04月09日 21:01
  • 679

基于MVC4+EF5+EasyUI技术实现通用权限管理系统(EpPlus、HignCharts、Reportviewer报表)

.NET实战开发通用权限管理系统(B/S、MVC版、完整模块) 基于MVC4+EF5+EasyUI技术实现通用权限管理系统(EpPlus、HignCharts、Reportviewer报表) 适合...
  • xiarilove
  • xiarilove
  • 2014年11月03日 11:27
  • 1787

基于XML的Web报表生成系统的研究与实现

  • 2008年09月11日 13:01
  • 1.89MB
  • 下载

Web报表的XML+JavaScript解决方案

  • 2007年09月14日 21:23
  • 103KB
  • 下载

Java实现Web报表打印功能.

  • 2007年05月30日 17:04
  • 81KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:利用XML实现通用WEB报表打印(5)
举报原因:
原因补充:

(最多只允许输入30个字)