首页 > 编程 > C# > 正文

用C#制作PDF文件全攻略

2023-05-17 11:41:58
字体:
来源:转载
供稿:网友

PDF文件在当前的办公环境中应用非常广泛,但是关于使用C#制作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 arginBottom);

第一个构造函数以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)。所以通过下面的办法得到实例已经足够了:

dfWriter.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的图片,如下图:

  u 阅读器参数:

  你可以通过下面的办法为PDF文件指定一些阅读器 (如Adobe Reader) 参数:

  public void setViewerPreferences(int preferences)

  在示例代码0108中,指定了下面一些参数:

  writerA.setViewerPreferences(PdfWriter.PageLayoutTwoColumnLeft);

  writerB.setViewerPreferences(PdfWriter.HideMenubar | PdfWriter.HideToolbar);

  writerC.setViewerPreferences(PdfWriter.PageLayoutTwoColumnLeft | PdfWriter.PageModeFullScreen | PdfWriter.NonFullScreenPageModeUseThumbs);

  正如你所看到的,参数可以使用以下一些常量:

  l 文件被打开时,页面布局用到下面的其中一个 :

  PdfWriter.PageLayoutSinglePage – 同时只显示一个页面

  PdfWriter.PageLayoutOneColumn –单列显示

  PdfWriter.PageLayoutTwoColumnLeft –双列显示,奇数页在左

  PdfWriter.PageLayoutTwoColumnRight -双列显示,奇数页在右

  l 文件打开时,页面模式用到下面其中之一:

  PdfWriter.PageModeUseNone – 既不显示大钢也不显示缩略图

  PdfWriter.PageModeUseOutlines – 显示大纲

  PdfWriter.PageModeUseThumbs – 显示缩略图

  PdfWriter.PageModeFullScreen – 全屏模式,没有菜单、windows控件或者其他任何windows可见控件

  l PdfWriter.HideToolbar – 当文档激活时,是否隐藏阅读程序(如Adobe Reader)的工具条

  l PdfWriter.HideMenubar -当文档激活时,是否隐藏阅读程序的菜单.

  l PdfWriter.HideWindowUI -当文档激活时,是否隐藏阅读程序的界面元素,如滚动条、导航条等,而仅仅保留文档显示

  l PdfWriter.FitWindow – 是否调整文档窗口尺寸以适合显示第一页。

  l PdfWriter.CenterWindow – 是否将文档窗口放到屏幕中央

  l 在全屏模式下,指定如何显示界面元素(选择一个)

  PdfWriter.NonFullScreenPageModeUseNone -既不显示大钢也不显示缩略图

  PdfWriter.NonFullScreenPageModeUseOutlines – 显示大钢

  PdfWriter.NonFullScreenPageModeUseThumbs – 显示缩略图

  说明:你只能在类PdfWriter中调用这些方法。

  u 加密

  打开文档之前还要做的一件事情就是加密(如果你希望该文档加密),要达到这个目的,你可以使用下面的方法:

  public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions);

  strength 是下面两个常量之一:

  PdfWriter.STRENGTH40BITS: 40 位

  PdfWriter.STRENGTH128BITS: 128位 (Acrobat Reader 5.0及以上版本支持)

  UserPassword和ownerPassword 可以为空或零长度, 这种情况下, ownerPassword 将被随机的字符串代替

  Permissions 为下列常量之一:

  PdfWriter.AllowPrinting

  PdfWriter.AllowModifyContents

  PdfWriter.AllowCopy

  PdfWriter.AllowModifyAnnotations

  PdfWriter.AllowFillIn

  PdfWriter.AllowScreenReaders

  PdfWriter.AllowAssembly

  PdfWriter.AllowDegradedPrinting

  该功能参见示例代码0109和示例代码0110。

  writer.setEncryption(PdfWriter.STRENGTH40BITS, null, null, PdfWriter.AllowCopy);

  示例代码0109产生的文件能够被打开而无须密码,但用户不能打印、修改本文档。

  writer.setEncryption(PdfWriter.STRENGTH128BITS, "userpass", "ownerpass", PdfWriter.AllowCopy | PdfWriter.AllowPrinting);

  打你试图打开示例代码0110产生的文件时,将要求输入密码('userpass'),因为添加了AllowPrinting参数,你可以打印该文档而不会发生任何问题。

  第四步 添加内容

  在解释第一步到第三步的不同示例中,你可能已经遇到了一些对象如Phrase, Paragraph等 在接下来的几章中,所有这些问题都将得到详细解释。

  有时你可能想一个writer故意忽略document产生的行为,如示例代码0111:

  当我们创建了两个writer: writerA 和 writerB:

  PdfWriter writerA = PdfWriter.getInstance(document, new FileStream("Chap0111a.pdf", FileMode.Create));

  PdfWriter writerB = PdfWriter.getInstance(document, new FileStream("Chap0111b.pdf", FileMode.Create));

  我们可以创建两个有细微差别的文档:

  writerA.Pause();

  document.add(new Paragraph("This paragraph will only be added to Chap0111b.pdf, not to Chap0111a.pdf"));

  writerA.resume();

  你可以比较文件: Chap0111a.pdf和Chap0111b.pdf的区别

  第五步,关闭 document

  关闭 document 非常重要, 因为它将关闭正在运行的Writer并将内容写入文件,该方法在最后被调用,你应该总是要关闭文档。

  高级话题:阅读PDF文件

  该部分内容介绍了iText只能产生PDF格式的文件而不能解析PDF格式文件,不再翻译。

  第二章 块、短句和段落

  块

  块(Chunk)是能被添加到文档的文本的最小单位,块可以用于构建其他基础元素如短句、段落、锚点等,块是一个有确定字体的字符串,要添加块到文档中时,其他所有布局变量均要被定义。下面一行中,我们创建了一个内容为“hello World”、红色、斜体、COURIER字体、尺寸20的一个块:

  Chunk chunk = new Chunk("Hello world", FontFactory.getFont(FontFactory.COURIER, 20, Font.ITALIC, new Color(255, 0, 0)));

  u 典型字体1:

  在本指南中,除了第九章外(你可以在这里学会使用其他字体),我们将始终使用典型字体1,这些是不同的典型字体1:

  · Courier (该字体定宽)

  · Helvetica

  · Times Roman

  · Symbol

  · ZapfDingbats

  u 下划线/删除线

  如果你希望一些块有下划线或删除线,你可以通过改变字体风ge简单做到:

  Chunk chunk1 = new Chunk("This text is underlined", FontFactory.getFont(FontFactory.HELVETICA, 12, Font.UNDERLINE));

  Chunk chunk2 = new Chunk("This font is of type ITALIC | STRIKETHRU", FontFactory.getFont(FontFactory.HELVETICA, 12, Font.ITALIC | Font.STRIKETHRU));

  u 上标/下标

  在块中有几个方法可以调用,其中大部分将在接下来的章节中介绍,本章中只介绍一个方法 setTextRise(float f). 你可以使用该方法在上标或下标中写块。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表