用C#制作PDF文件全攻略

前 言

丽水市汽车运输集团有限公司信息中心 苟安廷
PDF 文件是目前比较流行的电子文档格式,在办公自动化( OA )等软件的开发中,经常要用到该格式,但介绍如何制作 PDF 格式文件的资料非常少,在网上搜来搜去,都转贴的是同一段“暴力”破解的方法,代码片断如下:

StreamWriter pPDF=new StreamWriter(filePath);

ArrayList xRefs=new ArrayList();

float yPos =0f;

long streamStart=0;

long streamEnd=0;

long streamLen =0;

string strPDFMessage=null;

//PDF 文档头信息

strPDFMessage="%PDF-1.1\n";

ConvertToByteAndAddtoStream(strPDFMessage);

xRefs.Add(mPDF.Length);

strPDFMessage="1 0 obj\n";

ConvertToByteAndAddtoStream(strPDFMessage);

strPDFMessage="<< /Length 2 0 R >>\n";

ConvertToByteAndAddtoStream(strPDFMessage);

strPDFMessage="stream\n";

ConvertToByteAndAddtoStream(strPDFMessage);

……

看了上面的制作办法,我眼镜都摔坏了三幅,如果用上面这样原始的办法能制作出满意的 PDF 文件,那一定是天才所为。后来,我从一个网站(网址: http://itextsharp.sourceforge.net/index.html )中看到了专门制作 PDF 文件的控件的介绍,暗喜之余,立马下载试验,果然非常轻松地制作出了想要的 PDF 文件,因为网站为英文,内容又多,读起来非常费力,在解决了自己的问题后,看到许多网友还在为 PDF 文件制作而郁闷,遂决定将该内容翻译为中文,由于本人英语水平一般,许多地方又晦涩难懂,故翻译质量不是很满意,敬请斧正,但大部分能看懂。本文的目的一是解决部分网友的燃眉之急,二是抛砖引玉,如果哪位仁兄愿意将该网站中的内容准确翻译出来,则是天下之大幸。

要用本文的方法生成 PDF 文件,需要两个控件: itextsharp.dll 和 ICSharpCode.SharpZipLib.dll ,由于示例代码实在太多,我将代码全部整理出来,放在另外一个文件“示例代码 .doc ”中,所有这些资源,我均放在了本人的 ftp 站点( ftp://202.107.251.26 )上的“ Pdf 文件制作全攻略”文件夹中(文件夹中另外两个 rar 压缩文件为两个控件的源代码,供大家学习研究使用),你可以到这里下载相应的资源,或者直接到原网站下载。

为便于调试和叙述,所有例子均为 DOS 控制台程序, windows 程序使用方法完全一样,按照下面的步骤创建一个可调试的项目:

1、 打开 VS2003 ;

2、 单击菜单“文件”→“新建”→“项目”,在项目类型中选择“ Visual C# 项目”,在模板中选择“控制台应用程序”,输入文件名称如“ MakePdf ”,指定好存放路径,然后点确定按钮;

3、 在“解决方案资源管理器”中右键单击“引用”,从弹出的菜单中选择“添加引用”,在“ .NET ”选项夹中选择“浏览”,添加前面提到的两个应用,如下图:

4、 在代码窗口顶部添加两个引用:

using iTextSharp.text;

using iTextSharp.text.pdf;

至此,准备工作完毕。

第一部分 iText 的简单应用

第一章 创建一个 Document

利用 iText 五步创建一个 PDF 文件: helloword 。

第一步,创建一个 iTextSharp.text.Document 对象的实例:

Document document = new Document();

第二步,为该 Document 创建一个 Writer 实例:

PdfWriter.getInstance(document, new FileStream("Chap0101.pdf", FileMode.Create));

第三步,打开当前 Document

document.Open();

第四步,为当前 Document 添加内容:

document.Add(new Paragraph("Hello World"));

第五步,关闭 Document

document.Close();

完整的代码见示例代码 0101 。

在例中,不难看出,制作一个 PDF 文件是非常简单的。

注:如果你将例中“ document.Add( new Paragraph("Hello World"));”中的字符串“Hello Word”换成中文,如“这是我的第一个PDF文件”,产生的结果一定让你大失所望,因为生成的PDF文件中并没有将中文显示出来,不要担心,在第9章中要专门讲解字体问题,中文显示也就迎刃而解了,如果不能正确显示中文,也就没有必要翻译本文了。

下面对这几步做详细介绍。

第一步 创建一个 Document 实例:

iTextSharp.text.Document-object 共有三个构造函数:

public Document();

public Document(Rectangle pageSize);

public Document(Rectangle pageSize,

int marginLeft,

int marginRight,

int marginTop,

int marginBottom);

第一个构造函数以 A4 页面作为参数调用第二个构造函数,第二个构造函数以每边 36 磅页边距为参数调用第三个构造函数

u ** 页面尺寸: **

你可以通过指定的颜色和大小创建你自己的页面,示例代码 0102 创建一个细长的浅黄色背景的页面:

Rectangle pageSize = new Rectangle(144, 720);

pageSize.BackgroundColor = new Color(0xFF, 0xFF, 0xDE);

Document document = new Document(pageSize);

通常,你不必创建这样的页面,而可以从下面页面尺寸中选择:

A0-A10, LEGAL, LETTER, HALFLETTER, _11x17, LEDGER, NOTE, B0-B5, ARCH_A-ARCH_E, FLSA 和 FLSE

大多数情况下使用纵向页面,如果希望使用横向页面,你只须使用 rotate() 函数:

Document document = new Document(PageSize.A4.rotate());

详细代码见示例代码 0103 。

u ** 页边距: **

当创建一个文件时,你还可以定义上、下、左、右页边距:

Document document = new Document(PageSize.A5, 36, 72, 108, 180);

在示例代码 0104 中你可以看到该文档有一个 0.5 英寸的左边距和 1 英寸的右边距,上边距为 1.5 英寸,下边距为 2.5 英寸。

说明:

当创建一个矩形或设置边距时,你可能希望知道该用什么度量单位:厘米、英寸或象素,事实上,默认的度量系统以排版单位磅为基础得出其他单位的近似值,如 1英寸=72磅,如果你想在A4页面的PDF中创建一个矩形,你需要计算以下数据:

21 厘米 / 2.54 = 8.2677 英寸

8.2677英寸* 72 = 595 磅

29.7 厘米 / 2.54 = 11.6929 英寸

11.6929英寸* 72 = 842 磅

默认边距为 36磅即半英寸。

如果你修改了页面尺寸,仅仅影响到下一页,如果你修改了页边距,则影响到全部,故慎用。

关于页面的初始值,请参考第三步。

第二步 创建 Writer 实例

一旦创建了 document ,我们可以创建该文档的多个 Writer 的实例,所有这些 Writer 实例均继承自抽象类“ iTextSharp.text.DocWriter ”。

同时还有另外一种情况,你可以用 iTextSharp.text.pdf.PdfWriter 产生文档 PDF 文件,如果你想创建一个 TeX 文档,你可以使用 iTextSharp.text.TeX.TeXWriter 包。

Writer 类的构造函数是私有的,你只能通过下面的方法创建一个实例:

public static xxxWriter getInstance(Document document, Stream os); ( xxx 是 Pdf 或 Xml)

你可以通过下面的方法创建一个实例:

PdfWriter writer = PdfWriter.getInstance(document, new FileStream("Chap01xx.pdf"));

但是你几乎永远不会用到 Writer 实例(除非你想创建高级 PDF 或者希望用一些非常特殊的函数,如 ViewerPreferences 或 Encryption )。所以通过下面的办法得到实例已经足够了: PdfWriter.getInstance(document, new FileStream("Chap01xx.pdf"));

在第一步中创建一个文档时,第一个参数意义不大,第二个参数可以是任何一种流,到目前为止我们一直使用 System.IO.FileStream 将 Document 写入文件中,示例代码 0105 用到了 System.IO.MemoryStream (这不是一个独立的例子,你必须在 Servlet Engine 中测试这些代码。

第三步 打开 Document

u ** 摘要 **

在你写入任何实际数据之前,你可能希望通过以下几种方法写入一些关于本文档的摘要:

public boolean addTitle(String title)

public boolean addSubject(String subject)

public boolean addKeywords(String keywords)

public boolean addAuthor(String author)

public boolean addCreator(String creator)

public boolean addProducer()

public boolean addCreationDate()

public boolean addHeader(String name, String content)

你可以选择自己的标题、主题、关键字、作者、创建程序,但以下产品信息将始终被添加: iTextSharp ( 或者 iTextSharp 的引用 ) 和创建时间(实际上这两种方法是自动调用的)。

你还可以将自定义的名称添加为“报头信息”,但是这对于 PdfWriter 没有任何作用,如果看看实例代码 0101 产生的 pdf 文件的“文档属性”,我们可以看到仅仅有 PDF 创建程序和产品日期,而示例代码 0106 的“文档属性”框中有更多的信息。

打开 document 前要做的事:

你只能在 Open 方法调用之前添加摘要,这是 iText 开发工具提供的一个选择。

在 HTML 中,报头信息被放在文档前面报头标识中间,调用 Open 方法将导致报头信息写入流,因而在 Document 被打开后无法更改这些数据。

PDF 报头信息不包括摘要,看起来有类似于:

%PDF-1.2

该行显示生成的文档是一个版本为 1.2 的 PDF 格式的文件,在 PDF 中,摘要保存在 PdfInfo 对象中,当文档关闭时已经写入 PdfWriter 中了,因此,没有关于为什么不能修改库来满足任何时候添加或更改摘要的技术原因

u ** 页面初始化 **

Open 方法在不同的 Witer 中同时会产生初始化事件,举例来说,如果你需要一个水印或者页眉页角对象出现在文档第一页的开始处,你需要在打开文档前添加这些,同样的用于设置该文档其他页水印、页眉、页角、页数和尺寸。

当调用下列方法:

public bool setPageSize(Rectangle pageSize)

public bool Add(Watermark watermark)

public void removeWatermark()

setting Header property

public void resetHeader()

setting Footer property

public void resetFooter()

public void resetPageCount()

setting PageCount property

产生的结果只能在下一个新页中看到(当在本页调用初始化方法时),代码见示例代码 0107 ,你必须要准备一张名为 watermark.jpg 的图片,如下图:

<v:shape id=_x0000_i1028 s

Published At
Categories with Web编程
Tagged with
comments powered by Disqus