最近公司一直使用iText开发PDF报表,使用一段时间之后发现iText这个类库虽然是庞大无比,但作为程序猿我们不需要知道所有的类和方法,我们只需要知道如何使用即可。
所以这篇文章就是告诉大家如何快速的使用iTextSharp(iText .net版本)进行开发。
快速开发之前,我们先了解以下4个类:
class | 所代表的含义 |
Paragraph | 报表中的文本 |
Image | 报表中的图片 |
PdfPTable | 表格 |
PdfPCell | 单元格 |
知道这4个类之后就是开发的步骤了:
1. 往单元格PdfPCell类中添加内容。
2.将单元格PdfPCell添加到PdfPTable。
3.将表格PdfPTable添加到Document。
在以上的步骤中最重要的就是第一步也就是往PdfPCell中添加内容,而PdfPCell中的内容又可以分为以下三种情况:
文本 | Paragraph |
图片 | Image |
表格 | PdfPTable |
接下来我们就直奔主题,看是如何往PdfPCell添加内容。因为报表需要数据,所以我就从百度分辨率统计获取了一些数据,下面是这个网址的截图:
文本由Paragraph来表示,在添加之前还要注意一下字体的问题,因为我们用的是中文字体,如果用默认英文字体渲染则会乱码,所以我们要先定义中文字体:
BaseFont BF_Light = BaseFont.CreateFont(@"C:\Windows\Fonts\simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
字体定义完之后下面就添加文本:
//要设置字体和大小 p = new Paragraph(fields[i], new Font(BF_Light, 13)); cell = new PdfPCell(p); //设置cell属性 //cell.Border = Rectangle.NO_BORDER; if (rowNum == 0) { cell.BackgroundColor = BaseColor.GRAY; } if (i == mainColumn - 1) { cell.HorizontalAlignment = Element.ALIGN_RIGHT; } //添加单元格 table.AddCell(cell);
其实添加很简单,就是最上面两行代码,而对PdfPCell属性设置的代码一般会比较多,因为我们一般要设置其背景色,水平对其,还有边框Border等。
在大家了解怎么往PdfPCell添加完文本之后,添加图片和表格就简单很多了,就是将Image和PdfPTable作为PdfPCell的构造器参数传入即可:
//图片 Image image = Image.GetInstance(imagePath); cell = new PdfPCell(image, true); table.AddCell(cell); //表格 PdfPTable baseTable = GetBaseTable(); cell = new PdfPCell(baseTable); table.AddCell(cell);
以下就是效果图:
通过以上PdfPCell的操作,大家就可以实现一些比较常见的PDF报表,现在我们更进一步实现一下的效果:
这里就必须用到画图,画图用的就是PdfContentByte类,这个就类似于画板,我们可以直接在上面画直线和文本:
//画线 canvas.SaveState(); canvas.SetLineWidth(2f); canvas.MoveTo(100, 100); canvas.LineTo(200, 200); canvas.Stroke(); canvas.RestoreState(); //文本 ColumnText.ShowTextAligned(canvas, Element.ALIGN_RIGHT, new Phrase("JulyLuo测试", new Font(BF_Light, 10)), 100, 20, 0);
这里要注意的是,无论是画线还是文本我们都需要坐标,而且在画线的时候,要将具体的代码放在SaveState和RestoreState中间,这样就不会导致画图状态的紊乱。
如果我们希望将上图画在一个单元格中,但我们知道画图需要坐标,而在PdfPCell中是坐标没有暴露出来,所以这里我们需要iTextSharp中的接口:IPdfPCellEvent
public void CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases)
这个接口的意思就是在单元格添加到文档之后暴露的方法。很明显,通过postion参数我们可以获取坐标,canvases参数可以获取画板。
所以要画图就创建一个实现接口IPdfPCellEvent的类,然后在CellLayout方法中画线和文本:
public void CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) { PdfContentByte cb = canvases[PdfPTable.BACKGROUNDCANVAS]; PdfContentByte cbline = canvases[PdfPTable.LINECANVAS]; cbline.SaveState(); cb.SaveState(); ………… cb.SetLineWidth(0.4f); cbline.SetLineWidth(0.4f); //y 轴 cb.MoveTo(leftX, bottomY); cb.LineTo(leftX, topY); cb.Stroke(); //y 轴突出的短横线 float yAxiseTextLinetWidth = 3f; float yAxisTextSpaceAdjust = 2.5f; for (float y = yScaleNum; y < yMax; y += yScaleNum) { float yPoint = bottomY + (yScale * y); cb.MoveTo(leftX, yPoint); cb.LineTo(leftX - yAxiseTextLinetWidth, yPoint); cb.Stroke(); } //y 轴文本 for (float y = yScaleNum; y < yMax; y += yScaleNum) { float yPoint = bottomY + (yScale * y); ColumnText.ShowTextAligned(cb, Element.ALIGN_RIGHT, new Phrase(string.Format("{0}%", y), new Font(BF_Light, 5)), leftX - yAxiseTextLinetWidth, yPoint - yAxisTextSpaceAdjust, 0); } //x 轴 cb.MoveTo(leftX, bottomY); cb.LineTo(righX, bottomY); cb.Stroke(); ……… cb.Stroke(); cb.RestoreState(); cbline.RestoreState(); }
最后将这个类和对应的PdfPCell关联起来:
//画图的类,和cell关联 ResolutionChart chart = new ResolutionChart(fileName, yMax, yScale); cell.CellEvent = chart;
以下就是效果图: