该文主要介绍如何借助iTextSharp在C# 2.0中制作PDF文件,本文的架构大致按照iTextSharp的操作文档进行翻译,如果需要查看原文,请点击一下链接:http://itextsharp.sourceforge.net/tutorial/
一、 iTextSharp的介绍和下载
(1)用户可以浏览官网进行查看:http://itextsharp.sourceforge.net/index.html
iText# (iTextSharp) is a port of the iText open source java library written entirely in C# for the .NET platform. iText# is a library that allows you to generate PDF files on the fly. It is implemented as an assembly.
(2)以下链接用于下载:http://sourceforge.net/project/platformdownload.php?group_id=72954
下载后为一个解压缩文件,用户直接解压后得到一个dll动态链接库,在创建的项目中直接引入即可使用(本文的所有代码均在VS 2005环境下测试通过)
2.1 示例代码分析
创建一个PDF文档大致包括五个步骤,代码如下:
- using System;
- using System.Collections.Generic;
- using System.Text;
- using iTextSharp.text;
- using iTextSharp.text.pdf;
- using System.IO;
-
- namespace MakePDF
- {
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("Chapter 1 example 1: Hello World");
-
-
- Document document = new Document();
-
- try
- {
-
-
-
- PdfWriter.GetInstance(document, new FileStream("Chap0101.pdf", FileMode.Create));
-
-
-
- document.Open();
-
-
- document.Add(new Paragraph("Hello World PDF"));
-
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
-
- document.Close();
-
- Console.Read();
-
- }
- }
- }
该段代码的效果是可以在当前工作目录下,生成一个名字叫做Chap0101.pdf的PDF文档
2.2 第一步:创建Document对象
(1) Document对象
iTextSharp.text.Document有三个构造函数,分别为:
- public Document();
- public Document(Rectangle pageSize);
- public Document(Rectangle pageSize,
- int marginLeft,
- int marginRight,
- int marginTop,
- int marginBottom);
第一个构造函数调用第二个构造函数,参数为PageSize.A4
第二个构造函数调用第三个构造函数,其中每个边距默认值为36
(2) Page Size
你可以创建自己的用于特定颜色的Rectangle对象,并将其作为pageSize。我们对前面的代码进行修改,即创建一个长的、窄的、背景颜色为淡黄色的PDF文档。代码如下:
- using System;
- using System.Collections.Generic;
- using System.Text;
- using iTextSharp.text;
- using iTextSharp.text.pdf;
- using System.IO;
-
- namespace MakePDF
- {
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("Chapter 1 example 1: Hello World");
-
-
- Rectangle pageSize = new Rectangle(144, 720);
- pageSize.BackgroundColor = new Color(0xFF, 0xFF, 0xDE);
- Document document = new Document(pageSize);
-
-
- try
- {
-
-
-
-
-
- PdfWriter.GetInstance(document, new FileStream("Chap0101.pdf", FileMode.Create));
-
-
-
- document.Open();
-
-
- document.Add(new Paragraph("Hello World PDF"));
-
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
-
- document.Close();
-
- Console.Read();
-
- }
- }
- }
大多pageSizes都是采用了PORTRAIT格式,如果你想在LANDSCAPE应用它们,你必须使用rotate(),代码如下:
- Document document = new Document(PageSize.A4.rotate());
(3) Margins
在创建document的过程中,你也可以定义左、右、上、下边距,代码如下所示:
- Document document = new Document(PageSize.A5, 36, 72, 108, 180);
注意:如果你修改pageSize,会在下一个页面创建时产生影响;如果你修改margins,则会在当前页面立即产生影响。
2.3 创建Write对象
一旦成功创建了document,我们必须创建一个或者多个实例用于监听document,所有的writers继承于iTextSharp.text.DocWriter类。即你可以iTextSharp.text.pdf.PdfWriter使用来生成PDF文档,而如果需要生成Tex文档你必须使用iTextSharp.text.TeX.TeXWriter。
你可以使用以下的方式创建实例:
- PdfWriter writer = PdfWriter.getInstance(document, new FileStream("Chap01xx.pdf"));
在使用过程中,你几乎不会使用到writer对象(除了你想创建高级的PDF文件或者你想使用一些特定的函数,比如ViewerPreferences或者Encryption),所以获取这类实例就足够了。
该函数的第一个参数即第一步所创建的document对象;
第二个参数为不同类型的Stream对象,目前我们都只使用System.IO.FileStream,后来我们会使用到System.IO.MemoryStream.
2.4 元数据以及打开document
在你添加实际数据(即内容)是,你可能想加入某些关系到document的元数据,其方法如下:
- 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)
你可以选择自己的Title,Subject,Keywords,Author以及Creator,但是添加制作者的函数必须一直使用,以及添加创建时间的方法添加的当前系统的时间(事实上,这两个方法是被自动调用的),你可以用客户的姓名作为Header,但是这对于PdfWrite没有任何影响。
2.5 添加内容
1、在前面的三个步骤中,你遇到了诸如:Phrase,Paragraph…的对象,在以后的章节会详细的给予介绍。有些时候,你可能希望writer可以忽略document中的行为,相关的代码可以查看
2、如果你想创建两个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();
2.6 关闭document
关闭document相当重要,因为它会影响和关闭writer写的输出流,close方法为finalize方法,但是你不能依靠它,你必须手工对其进行关闭。
3.1 Chunk
Chunk是能够添加到document文本中最小的重要部分。Chunk能够为其他的元素诸如Phrase以及Paragrph等构建块,一个Chunk就是一个附有指定字体的字符串,在添加chunk的文本的对象中,所有其他的版面设计参数都应该定义。
下面的代码表示我们创建内容为"Hello world"格式为(red, italic COURIER font of size 20)的Chunk:
- Chunk chunk = new Chunk("Hello world", FontFactory.getFont(FontFactory.COURIER, 20, Font.ITALIC, new Color(255, 0, 0)));
3.2 Phrases
Phrases是一系列拥有特定的作为额外参数的leading(=两行之间的空间)的Chunk
Phrases拥有一个主字体,但是其他的chunks可以拥有不同于这个主字体的其余字体,你可以从多种构造函数中创建Phrases对象。代码如下:
- using System;
- using System.IO;
-
- using iTextSharp.text;
- using iTextSharp.text.pdf;
-
- public class Chap0202
- {
-
- public static void Main()
- {
-
- Console.WriteLine("Chapter 2 example 2: Phrases");
-
-
- Document document = new Document();
-
- try
- {
-
-
-
-
- PdfWriter.GetInstance(document, new FileStream("Chap0202.pdf", FileMode.Create));
-
-
- document.Open();
-
-
- Phrase phrase0 = new Phrase();
- Phrase phrase1 = new Phrase("(1) this is a phrase/n");
-
- Phrase phrase2 = new Phrase(24, "(2) this is a phrase with leading 24. You can only see the difference if the line is long enough. Do you see it? There is more space between this line and the previous one./n");
-
-
- Phrase phrase3 = new Phrase("(3) this is a phrase with a red, normal font Courier, size 20. As you can see the leading is automatically changed./n", FontFactory.GetFont(FontFactory.COURIER, 20, Font.NORMAL, new Color(255, 0, 0)));
- Phrase phrase4 = new Phrase(new Chunk("(4) this is a phrase/n"));
- Phrase phrase5 = new Phrase(18, new Chunk("(5) this is a phrase in Helvetica, bold, red and size 16 with a given leading of 18 points./n", FontFactory.GetFont(FontFactory.HELVETICA, 16, Font.BOLD, new Color(255, 0, 0))));
-
- Phrase phrase6 = new Phrase("(6)");
- Chunk chunk = new Chunk(" This is a font: ");
- phrase6.Add(chunk);
- phrase6.Add(new Chunk("Helvetica", FontFactory.GetFont(FontFactory.HELVETICA, 12)));
- phrase6.Add(chunk);
- phrase6.Add(new Chunk("Times New Roman", FontFactory.GetFont(FontFactory.TIMES_ROMAN, 12)));
- phrase6.Add(chunk);
- phrase6.Add(new Chunk("Courier", FontFactory.GetFont(FontFactory.COURIER, 12)));
- phrase6.Add(chunk);
- phrase6.Add(new Chunk("Symbol", FontFactory.GetFont(FontFactory.SYMBOL, 12)));
- phrase6.Add(chunk);
- phrase6.Add(new Chunk("ZapfDingBats", FontFactory.GetFont(FontFactory.ZAPFDINGBATS, 12)));
- Phrase phrase7 = new Phrase("(7) if you don't Add a newline yourself, all phrases are glued to eachother!");
-
- document.Add(phrase1);
- document.Add(phrase2);
- document.Add(phrase3);
- document.Add(phrase4);
- document.Add(phrase5);
- document.Add(phrase6);
- document.Add(phrase7);
-
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
-
- document.Close();
-
- Console.WriteLine("End");
- Console.Read();
- }
- }
3.3 Phragraph
Phragraph是一系列的chunk或者phrase.跟phrase类似,Phragraph也有特定的leading,用户也可以定义特定的缩排。每个加到document的Phragraph都会自动生成新的一行。Phragraph的构造函数包括如下几种:
- Paragraph p1 = new Paragraph(new Chunk("This is my first paragraph.", FontFactory.getFont(FontFactory.HELVETICA, 12)));
- Paragraph p2 = new Paragraph(new Phrase("This is my second paragraph.", FontFactory.getFont(FontFactory.HELVETICA, 12)));
- Paragraph p3 = new Paragraph("This is my third paragraph.", FontFactory.getFont(FontFactory.HELVETICA, 12));
所有的paragraph对象还可以利用add()添加paragraph对象。代码如下:
- p1.add("you can add strings, "); p1.add(new Chunk("you can add chunks ")); p1.add(new Phrase("or you can add phrases."));
注意:每一个paragraph只能且需有一个leading,如果你想添加其他字体的phrase或者chunk,原先的leading依旧有效,你可以利用方法setLeading修改leading,但是这样会造成所有paragraph的内容都会拥有新的leading.测试代码如下:
- using System;
- using System.IO;
- using iTextSharp.text.pdf;
- {
-
- public static void Main()
- {
-
- Console.WriteLine("Chapter 2 example 5: Paragraphs");
-
-
- Document document = new Document();
-
- try
- {
-
-
-
-
- PdfWriter.GetInstance(document, new FileStream("Chap0205.pdf", FileMode.Create));
-
-
- document.Open();
-
-
- Paragraph p1 = new Paragraph(new Chunk("This is my first paragraph. ",
- FontFactory.GetFont(FontFactory.HELVETICA, 10)));
- p1.Add("The leading of this paragraph is calculated automagically. ");
- p1.Add("The default leading is 1.5 times the fontsize. ");
- p1.Add(new Chunk("You can Add chunks "));
- p1.Add(new Phrase("or you can Add phrases. "));
- p1.Add(new Phrase("Unless you change the leading with the method setLeading, the leading doesn't change if you Add text with another leading. This can lead to some problems.", FontFactory.GetFont(FontFactory.HELVETICA, 18)));
- document.Add(p1);
- Paragraph p2 = new Paragraph(new Phrase("This is my second paragraph. ",
- FontFactory.GetFont(FontFactory.HELVETICA, 12)));
- p2.Add("As you can see, it started on a new line.");
- document.Add(p2);
- Paragraph p3 = new Paragraph("This is my third paragraph.",
- FontFactory.GetFont(FontFactory.HELVETICA, 12));
- document.Add(p3);
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
-
- document.Close();
-
- Console.WriteLine("End");
- Console.Read();
- }
- }
以下的代码我们应用方法setKeepTogether(true)来保证paragraph在一个page上,这个并不经常发生。
- using System;
- using System.IO;
- using iTextSharp.text.pdf;
- {
-
- public static void Main()
- {
-
- Console.WriteLine("Chapter 2 example 6: keeping a paragraph together");
-
-
- Document document = new Document(PageSize.A6);
-
- try
- {
-
-
-
-
- PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("Chap0206.pdf", FileMode.Create));
-
-
- document.Open();
-
-
- Paragraph p;
- p = new Paragraph("GALLIA est omnis divisa in partes tres, quarum unam incolunt Belgae, aliam Aquitani, tertiam qui ipsorum lingua Celtae, nostra Galli appellantur. Hi omnes lingua, institutis, legibus inter se differunt. Gallos ab Aquitanis Garumna flumen, a Belgis Matrona et Sequana dividit. Horum omnium fortissimi sunt Belgae, propterea quod a cultu atque humanitate provinciae longissime absunt, minimeque ad eos mercatores saepe commeant atque ea quae ad effeminandos animos pertinent important, proximique sunt Germanis, qui trans Rhenum incolunt, quibuscum continenter bellum gerunt. Qua de causa Helvetii quoque reliquos Gallos virtute praecedunt, quod fere cotidianis proeliis cum Germanis contendunt, cum aut suis finibus eos prohibent aut ipsi in eorum finibus bellum gerunt.", FontFactory.GetFont(FontFactory.HELVETICA, 12));
- p.KeepTogether = true;
- document.Add(p);
- p = new Paragraph("[Eorum una, pars, quam Gallos obtinere dictum est, initium capit a flumine Rhodano, continetur Garumna flumine, Oceano, finibus Belgarum, attingit etiam ab Sequanis et Helvetiis flumen Rhenum, vergit ad septentriones. Belgae ab extremis Galliae finibus oriuntur, pertinent ad inferiorem partem fluminis Rheni, spectant in septentrionem et orientem solem. Aquitania a Garumna flumine ad Pyrenaeos montes et eam partem Oceani quae est ad Hispaniam pertinet; spectat inter occasum solis et septentriones.]", FontFactory.GetFont(FontFactory.HELVETICA, 12));
- p.KeepTogether = true;
- document.Add(p);
- p = new Paragraph("Apud Helvetios longe nobilissimus fuit et ditissimus Orgetorix. Is M. Messala, [et P.] M. Pisone consulibus regni cupiditate inductus coniurationem nobilitatis fecit et civitati persuasit ut de finibus suis cum omnibus copiis exirent: perfacile esse, cum virtute omnibus praestarent, totius Galliae imperio potiri. Id hoc facilius iis persuasit, quod undique loci natura Helvetii continentur: una ex parte flumine Rheno latissimo atque altissimo, qui agrum Helvetium a Germanis dividit; altera ex parte monte Iura altissimo, qui est inter Sequanos et Helvetios; tertia lacu Lemanno et flumine Rhodano, qui provinciam nostram ab Helvetiis dividit. His rebus fiebat ut et minus late vagarentur et minus facile finitimis bellum inferre possent; qua ex parte homines bellandi cupidi magno dolore adficiebantur. Pro multitudine autem hominum et pro gloria belli atque fortitudinis angustos se fines habere arbitrabantur, qui in longitudinem milia passuum CCXL, in latitudinem CLXXX patebant.", FontFactory.GetFont(FontFactory.HELVETICA, 12));
- p.KeepTogether = true;
- document.Add(p);
- p = new Paragraph("His rebus Adducti et auctoritate Orgetorigis permoti constituerunt ea quae ad proficiscendum pertinerent comparare, iumentorum et carrorum quam maximum numerum coemere, sementes quam maximas facere, ut in itinere copia frumenti suppeteret, cum proximis civitatibus pacem et amicitiam confirmare. Ad eas res conficiendas biennium sibi satis esse duxerunt; in tertium annum profectionem lege confirmant. Ad eas res conficiendas Orgetorix deligitur. Is sibi legationem ad civitates suscipit. In eo itinere persuadet Castico, Catamantaloedis filio, Sequano, cuius pater regnum in Sequanis multos annos obtinuerat et a senatu populi Romani amicus appellatus erat, ut regnum in civitate sua occuparet, quod pater ante habuerit; itemque Dumnorigi Haeduo, fratri Diviciaci, qui eo tempore principatum in civitate obtinebat ac maxime plebi acceptus erat, ut idem conaretur persuadet eique filiam suam in matrimonium dat. Perfacile factu esse illis probat conata perficere, propterea quod ipse suae civitatis imperium obtenturus esset: non esse dubium quin totius Galliae plurimum Helvetii possent; se suis copiis suoque exercitu illis regna conciliaturum confirmat. Hac oratione Adducti inter se fidem et ius iurandum dant et regno occupato per tres potentissimos ac firmissimos populos totius Galliae sese potiri posse sperant.", FontFactory.GetFont(FontFactory.HELVETICA, 12));
- p.KeepTogether = true;
- document.Add(p);
- p = new Paragraph("Ea res est Helvetiis per indicium enuntiata. Moribus suis Orgetoricem ex vinculis causam dicere coegerunt; damnatum poenam sequi oportebat, ut igni cremaretur. Die constituta causae dictionis Orgetorix ad iudicium omnem suam familiam, ad hominum milia decem, undique coegit, et omnes clientes obaeratosque suos, quorum magnum numerum habebat, eodem conduxit; per eos ne causam diceret se eripuit. Cum civitas ob eam rem incitata armis ius suum exequi conaretur multitudinemque hominum ex agris magistratus cogerent, Orgetorix mortuus est; neque abest suspicio, ut Helvetii arbitrantur, quin ipse sibi mortem consciverit.", FontFactory.GetFont(FontFactory.HELVETICA, 12));
- p.KeepTogether = true;
- document.Add(p);
-
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
-
- document.Close();
-
- Console.Read();
- }
- }
四、Anchor(锚)、List(列表)和Annotation(注释)
4.1 Anchor
我们都知道HTML中的超文本链接,只要你点击指定的文字,你就可以跳转到网络中的其他页面,这种功能在PDF中同样存在,在后面的章节会详细的介绍PDF中的链接Chapter 11,。但是这是iText的另外一种高级编程,我们这里只是介绍简单的iText.
如果你想添加外部的link到document中(比如用URL链接到网页中的另外一个document),你可以简单的使用Anchor对象,该对象继承于Phrase对象,它们具有相同的使用方法,但是它还有两个额外的方法:setName和setReference,具体的使用代码如下:
- Anchor anchor = new Anchor("website", FontFactory.getFont(FontFactory.HELVETICA, 12, Font.UNDERLINE, new Color(0, 0, 255)));
- anchor.Reference = "http://itextsharp.sourceforge.net";
如果你想添加内部的链接,你需要为链接选择独特的名字,这就像在HTML中为锚所使用的名字,当你为这个目标设定索引时,你需要在前面添加一个#符号,具体代码如下:
- Anchor anchor1 = new Anchor("This is an internal link");
- anchor1.Name = "link1";
- Anchor anchor2 = new Anchor("Click here to jump to the internal link");
- anchor.Reference = "#link1";
4.2 List
利用List和ListItem类,你就可以为PDF文件添加列表了,如果你想拥有有序(ordered)列表或者无序列表(unordered)你都可以使用这两个类。
(1) ordered列表
- List list = new List(true, 20);
- list.Add(new ListItem("First line"));
- list.Add(new ListItem("The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?"));
- list.Add(new ListItem("Third line"));
结果为:
(2) 无序列表
- List overview = new List(false, 10);
- overview.Add(new ListItem("This is an item"));
- overview.Add("This is another item");
结果为:
你可以用setListSymbol方法改变列表标识符,代码如下所示:
- list2.ListSymbol = new Chunk("/u2022", FontFactory.getFont(FontFactory.HELVETICA, 20));
- list3.ListSymbol = new Chunk(Image.getInstance("myBullet.gif"), 0, 0);
还有一些方法用于改变列表的缩排:setIndentationLeft 和 setIndentationRight.
而列表符的缩排可以在构造函数中给予设定,参考代码如下:
- using System;
- using System.IO;
- using iTextSharp.text.pdf;
-
- public static void Main() {
-
- Console.WriteLine("Chapter 3 example 2: Lists");
-
-
- Document document = new Document();
-
- try {
-
-
-
-
- PdfWriter.getInstance(document, new FileStream("Chap0302.pdf", FileMode.Create));
-
-
- document.Open();
-
-
-
- List list = new List(true, 20);
- list.Add(new ListItem("First line"));
- list.Add(new ListItem("The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?"));
- list.Add(new ListItem("Third line"));
- document.Add(list);
-
- document.Add(new Paragraph("some books I really like:"));
- ListItem listItem;
- list = new List(true, 15);
- listItem = new ListItem("When Harlie was one", FontFactory.getFont(FontFactory.TIMES_NEW_ROMAN, 12));
- listItem.Add(new Chunk(" by David Gerrold", FontFactory.getFont(FontFactory.TIMES_NEW_ROMAN, 11, Font.ITALIC)));
- list.Add(listItem);
- listItem = new ListItem("The World according to Garp", FontFactory.getFont(FontFactory.TIMES_NEW_ROMAN, 12));
- listItem.Add(new Chunk(" by John Irving", FontFactory.getFont(FontFactory.TIMES_NEW_ROMAN, 11, Font.ITALIC)));
- list.Add(listItem);
- listItem = new ListItem("Decamerone", FontFactory.getFont(FontFactory.TIMES_NEW_ROMAN, 12));
- listItem.Add(new Chunk(" by Giovanni Boccaccio", FontFactory.getFont(FontFactory.TIMES_NEW_ROMAN, 11, Font.ITALIC)));
- list.Add(listItem);
- document.Add(list);
-
- Paragraph paragraph = new Paragraph("some movies I really like:");
- list = new List(false, 10);
- list.Add("Wild At Heart");
- list.Add("Casablanca");
- list.Add("When Harry met Sally");
- list.Add("True Romance");
- list.Add("Le mari de la coiffeuse");
- paragraph.Add(list);
- document.Add(paragraph);
-
- document.Add(new Paragraph("Some authors I really like:"));
- list = new List(false, 20);
- list.ListSymbol = new Chunk("/u2022", FontFactory.getFont(FontFactory.HELVETICA, 20, Font.BOLD));
- listItem = new ListItem("Isaac Asimov");
- list.Add(listItem);
- List sublist;
- sublist = new List(true, 10);
- sublist.ListSymbol = new Chunk("", FontFactory.getFont(FontFactory.HELVETICA, 8));
- sublist.Add("The Foundation Trilogy");
- sublist.Add("The Complete Robot");
- sublist.Add("Caves of Steel");
- sublist.Add("The Naked Sun");
- list.Add(sublist);
- listItem = new ListItem("John Irving");
- list.Add(listItem);
- sublist = new List(true, 10);
- sublist.ListSymbol = new Chunk("", FontFactory.getFont(FontFactory.HELVETICA, 8));
- sublist.Add("The World according to Garp");
- sublist.Add("Hotel New Hampshire");
- sublist.Add("A prayer for Owen Meany");
- sublist.Add("Widow for a year");
- list.Add(sublist);
- listItem = new ListItem("Kurt Vonnegut");
- list.Add(listItem);
- sublist = new List(true, 10);
- sublist.ListSymbol = new Chunk("", FontFactory.getFont(FontFactory.HELVETICA, 8));
- sublist.Add("Slaughterhouse 5");
- sublist.Add("Welcome to the Monkey House");
- sublist.Add("The great pianola");
- sublist.Add("Galapagos");
- list.Add(sublist);
- document.Add(list);
- }
- catch(DocumentException de) {
- Console.Error.WriteLine(de.Message);
- }
- catch(IOException ioe) {
- Console.Error.WriteLine(ioe.Message);
- }
-
-
- document.Close();
- }
- }
4.3 Annotation
在iText中支持不同类型的注释:
(1) Text:你可以向document添加一些小块的文本,但是这些文本并不属于内容的一部分,Annotation有一个标题和一些内容,具体代码如下:
- Annotation a = new Annotation(
- "authors",
- "Maybe it's because I wanted to be an author myself that I wrote iText.");
(2) External links(外部链接):你可以指定一个可被点击的矩形或者字符串(称为URL)或者URL对象,具体代码如下:
- Annotation annot = new Annotation(100f, 700f, 200f, 800f, new URL("http://www.lowagie.com"));
- Annotation annot = new Annotation(100f, 700f, 200f, 800f, "http://www.lowagie.com");
(3) External PDF file(外部PDF文件):你可以设定一个可点击的矩形和字符串(文件名称)和目的文件或者页码:
- Annotation annot = new Annotation(100f, 700f, 200f, 800f, "other.pdf", "mark");
- Annotation annot = new Annotation(100f, 700f, 200f, 800f, "other.pdf", 2);
(4) Named action(指定的行为):你必须制定一个可点击的矩形和一个指定的行为:
- Annotation annot = new Annotation(100f, 700f, 200f, 800f, PdfAction.FIRSTPAGE);
(5) Application(应用):你必须制定一个可点击的矩形和一个应用程序
- Annotation annot = new Annotation(300f, 700f, 400f, 800f, "C://winnt/notepad.exe", null, null, null);
5、HeaderFooters,Chapters,Sections和Graphic对象(原文:http://itextsharp.sourceforge.net/tutorial/ch04.html)
5.1 HeaderFooter
HeaderFooter对象是一个能够为document的每个页面添加footer和header的对象,这些页眉和页脚都包含着标准的短语和当前的页码(如果有需要)。如果你需要更加复杂的页眉和页脚(有表格或者有page X of Y),您需要阅读12章节Chapter 12:
下面的核心代码表示我们第一个添加一个包含页码但是么有任何边界的页眉。
- HeaderFooter footer = new HeaderFooter(new Phrase("This is page: "), true);
- footer.Border = Rectangle.NO_BORDER;
- document.Footer = footer;
具体代码如下:
- using System;
- using System.IO;
- using iTextSharp.text.pdf;
- {
-
- public static void Main()
- {
-
- Console.WriteLine("Chapter 4 example 1: Headers en Footers");
- Document document = new Document();
-
- try
- {
-
- PdfWriter.GetInstance(document, new FileStream("Chap0401.pdf", FileMode.Create));
-
-
- HeaderFooter footer = new HeaderFooter(new Phrase("This is page: "), true);
- footer.Border = Rectangle.NO_BORDER;
- document.Footer = footer;
-
-
- document.Open();
-
-
- HeaderFooter header = new HeaderFooter(new Phrase("This is a header"), false);
- document.Header = header;
-
-
-
-
- document.Add(new Paragraph("Hello World"));
-
- document.NewPage();
-
-
-
- document.Add(new Paragraph("Hello Earth"));
-
- document.ResetHeader();
-
- document.NewPage();
-
-
-
- document.Add(new Paragraph("Hello Sun"));
- document.Add(new Paragraph("Remark: the header has vanished!"));
-
- document.ResetPageCount();
-
- document.NewPage();
-
-
-
- document.Add(new Paragraph("Hello Moon"));
- document.Add(new Paragraph("Remark: the pagenumber has been reset!"));
-
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
-
- document.Close();
-
- Console.Read();
- }
- }
我们也可以用一下的构造函数:
- HeaderFooter footer = new HeaderFooter(new Phrase("This is page "), new Phrase("."));
如果你设置HeadFooter对象没有改变边界,页眉或者页脚会在文本的上下有一条线。
- HeaderFooter header = new HeaderFooter(new Phrase("This is a header without a page number"), false);
- document.Header = header;
5.2 Chapters和Section
十一章(Chapter 11 本文的12节)描述了如何创建大纲树,如果你只是需要附有一些章节或者子段的简单的树,你可以利用Chapter和Section类来自动创建,核心代码如下:
- Paragraph cTitle = new Paragraph("This is chapter 1", chapterFont);
- Chapter chapter = new Chapter(cTitle, 1);
- Paragraph sTitle = new Paragraph("This is section 1 in chapter 1", sectionFont);
- Section section = chapter.addSection(sTitle, 1);
下面的代码,我们添加一系列的章节和子章节,运行程序后,你可以查看到PDF文件拥有完整的大纲树,这个大纲树被默认打开,如果你想使得有一部大纲关闭,你可以把BookmarkOpen属性设置为false.
- using System;
- using System.IO;
- using iTextSharp.text.pdf;
- {
-
- public static void Main()
- {
-
- Console.WriteLine("Chapter 4 example 2: Chapters and Sections");
- Document document = new Document(PageSize.A4, 50, 50, 50, 50);
- try
- {
-
- PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("Chap0402.pdf", FileMode.Create));
-
- document.Open();
-
-
- Font chapterFont = FontFactory.GetFont(FontFactory.HELVETICA, 24, Font.NORMAL, new Color(255, 0, 0));
- Font sectionFont = FontFactory.GetFont(FontFactory.HELVETICA, 20, Font.NORMAL, new Color(0, 0, 255));
- Font subsectionFont = FontFactory.GetFont(FontFactory.HELVETICA, 18, Font.BOLD, new Color(0, 64, 64));
-
- Paragraph blahblah = new Paragraph("blah blah blah blah blah blah blaah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah");
- Paragraph blahblahblah = new Paragraph("blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blaah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah");
-
- for (int i = 1; i < 8; i++)
- {
- Paragraph cTitle = new Paragraph("This is chapter " + i, chapterFont);
- Chapter chapter = new Chapter(cTitle, i);
-
- if (i == 4)
- {
- blahblahblah.Alignment = Element.ALIGN_JUSTIFIED;
- blahblah.Alignment = Element.ALIGN_JUSTIFIED;
- chapter.Add(blahblah);
- }
- if (i == 5)
- {
- blahblahblah.Alignment = Element.ALIGN_CENTER;
- blahblah.Alignment = Element.ALIGN_RIGHT;
- chapter.Add(blahblah);
- }
-
- if (i == 6)
- {
- blahblah.Alignment = Element.ALIGN_JUSTIFIED;
- }
-
- for (int j = 1; j < 4; j++)
- {
- Paragraph sTitle = new Paragraph("This is section " + j + " in chapter " + i, sectionFont);
- Section section = chapter.AddSection(sTitle, 1);
-
- if (j == 3 && i > 1)
- {
- section.Add(blahblah);
- }
-
- for (int k = 1; k < 4; k++)
- {
- Paragraph subTitle = new Paragraph("This is subsection " + k + " of section " + j, subsectionFont);
- Section subsection = section.AddSection(subTitle, 3);
- if (k == 1 && j == 3)
- {
- subsection.Add(blahblahblah);
- }
- subsection.Add(blahblah);
- }
- if (j == 2 && i > 2)
- {
- section.Add(blahblahblah);
- }
- }
- document.Add(chapter);
- }
- }
- catch (Exception de)
- {
- Console.Error.WriteLine(de.StackTrace);
- }
-
- document.Close();
-
- Console.Read();
- }
- }
5.3 Graphic
如果你想添加诸如线段、圆、几何图形等,你可以查看本文的第11章或者查看原文(Chapter 10),但如果你只是需要有限的功能,你可以直接使用Graphic对象。核心代码如下:
- Graphic grx = new Graphic();
-
- grx.rectangle(100, 700, 100, 100);
-
- grx.moveTo(100, 700);
- grx.lineTo(200, 800);
-
- grx.stroke();
- document.Add(grx);
详细代码如下(在目前测试过程中,Ghaphic类不能使用,目前还不知道什么原因)
- using System;
- using System.IO;
- using iTextSharp.text.pdf;
- using iTextSharp.text.factories;
- {
-
- public static void Main()
- {
-
- Console.WriteLine("Chapter 4 example 4: Simple Graphic");
-
-
- Document document = new Document();
-
- try
- {
-
-
-
-
-
- PdfWriter.GetInstance(document, new FileStream("Chap0404.pdf", FileMode.Create));
-
-
- document.Open();
-
-
- Graphic grx = new Graphic();
-
-
- grx.rectangle(100, 700, 100, 100);
-
- grx.moveTo(100, 700);
- grx.lineTo(200, 800);
-
- grx.stroke();
- document.Add(grx);
-
-
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
-
- document.Close();
-
- Console.Read();
- }
- }
提示:如果你仅仅只生成PDF(并非XML,HTML,RTF)文件,你最好可以用PdfPTable类取代Table类
6.1 一些简单的表格
Table(表格)就是一个包含Cells(单元格)的Rectangle(矩阵).并按照一些特定的矩阵进行排序。表格中的矩阵并一定要M*N,它还可以只包含比unit大的单元格或者hole,其核心代码如下:
- public Table(int columns, int rows) throws BadElementException;
下面的代码我们创建一个非常简单的表格:
- using System;
- using System.IO;
- using iTextSharp.text.pdf;
- {
-
- public static void Main()
- {
- Console.WriteLine("Chapter 5 example 1: my first table");
-
- Document document = new Document();
- try
- {
-
-
-
- PdfWriter.GetInstance(document, new FileStream("Chap0501.pdf", FileMode.Create));
-
- document.Open();
-
- Table aTable = new Table(2, 2);
- aTable.AddCell("0.0");
- aTable.AddCell("0.1");
- aTable.AddCell("1.0");
- aTable.AddCell("1.1");
- aTable.AddCell("1.2");
- document.Add(aTable);
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
- document.Close();
-
- Console.Read();
- }
-
- }
以上代码创建了一个含有2行2列的表格,单元格自动添加,开始于第一行的第一列,然后第二列,当一个行满了以后,下一个单元格就在下一行的第一列添加。如下图所示:
以下代码为在表格指定的位置进行添加单元格,在测试本代码,您必须添加引用System.Drawing.dll库文件来访问Point对象,我们在该代码创建一个4X4的表格,然后在随机的位置添加单元格。
核心代码如下:
- Table aTable = new Table(4,4);
- aTable.AutoFillEmptyCells = true;
- aTable.addCell("2.2", new Point(2,2));
- aTable.addCell("3.3", new Point(3,3));
- aTable.addCell("2.1", new Point(2,1));
- aTable.addCell("1.3", new Point(1,3));
详细代码如下:
- using System;
- using System.IO;
- using iTextSharp.text.pdf;
- {
-
- public static void Main()
- {
- Console.WriteLine("Chapter 5 example 2: adding cells at a specific position");
-
- Document document = new Document();
- try
- {
-
-
-
- PdfWriter.GetInstance(document, new FileStream("Chap0502.pdf", FileMode.Create));
-
- document.Open();
-
- Table aTable;
-
- aTable = new Table(4, 4);
- aTable.AutoFillEmptyCells = true;
- aTable.AddCell("2.2", new Point(2, 2));
- aTable.AddCell("3.3", new Point(3, 3));
- aTable.AddCell("2.1", new Point(2, 1));
- aTable.AddCell("1.3", new Point(1, 3));
- document.Add(aTable);
- document.NewPage();
-
- aTable = new Table(4, 4);
- aTable.AddCell("2.2", new Point(2, 2));
- aTable.AddCell("3.3", new Point(3, 3));
- aTable.AddCell("2.1", new Point(2, 1));
- aTable.AddCell("1.3", new Point(1, 3));
- document.Add(aTable);
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
- document.Close();
-
- Console.Read();
- }
-
- }
从以上代码可以看出,我们必须设置属性AutoFillEmptyCells属性为true,如果你忘记设置该属性(就像本代码生成的第二个表格),这样就不会有额外的单元格添加当然不包括任何单元格的行也会被忽略。在本例中,第一行没有显示,就是因为它是空的。
通常情况下,我们会用数据库查询结果来填满表格,在许多例子中,我们并不知道我们究竟需要多少行,这里有个构造函数可以解决这个问题,如下:
- public Table(int columns);
如果有需要,iText会自动添加行,在下面的例子,我们初始化了一个4X4的表格,当我们在6行和7行添加单元格的时候,iText自动将行数升至为7.具体代码如下所示:
- using System;
- using System.IO;
- using iTextSharp.text.pdf;
- {
-
- public static void Main()
- {
- Console.WriteLine("Chapter 5 example 3: rows added automatically");
-
- Document document = new Document();
- try
- {
-
-
-
- PdfWriter.GetInstance(document, new FileStream("Chap0503.pdf", FileMode.Create));
-
- document.Open();
-
- Table aTable = new Table(4, 4);
- aTable.AutoFillEmptyCells = true;
- aTable.AddCell("2.2", new Point(2, 2));
- aTable.AddCell("3.3", new Point(3, 3));
- aTable.AddCell("2.1", new Point(2, 1));
- aTable.AddCell("1.3", new Point(1, 3));
- aTable.AddCell("5.2", new Point(5, 2));
- aTable.AddCell("6.1", new Point(6, 1));
- aTable.AddCell("5.0", new Point(5, 0));
- document.Add(aTable);
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
- document.Close();
- Console.Read();
- }
- }
同样,添加列数也是可能的,但是有一定的难度,它不会进行自动的添加,你需要使用addColumns方法以及为列的宽度进行设置,在下面的代码可以看出。
- using System;
- using System.IO;
- using iTextSharp.text.pdf;
- {
-
- public static void Main()
- {
- Console.WriteLine("Chapter 5 example 4: adding columns");
-
- Document document = new Document();
- try
- {
-
-
-
- PdfWriter.GetInstance(document, new FileStream("Chap0504.pdf", FileMode.Create));
-
- document.Open();
-
- Table aTable = new Table(2, 2);
- aTable.AutoFillEmptyCells = true;
- aTable.AddCell("0.0");
- aTable.AddCell("0.1");
- aTable.AddCell("1.0");
- aTable.AddCell("1.1");
- aTable.AddColumns(2);
- float[] f = { 1f, 1f, 1f, 1f };
- aTable.Widths = f;
- aTable.AddCell("2.2", new Point(2, 2));
- aTable.AddCell("3.3", new Point(3, 3));
- aTable.AddCell("2.1", new Point(2, 1));
- aTable.AddCell("1.3", new Point(1, 3));
- aTable.AddCell("5.2", new Point(5, 2));
- aTable.AddCell("6.1", new Point(6, 1));
- aTable.AddCell("5.0", new Point(5, 0));
- document.Add(aTable);
-
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
- document.Close();
-
- Console.Read();
- }
- }
6.2 一些表格参数
以上创建的一些表格看起来效果都不怎么好,我们可以通过设置一些表格参数来改变表格的外观。Table类和Cell类都是继承于Rectangle类,所以我们可以利用一些rectangle的典型的方法,如下面代码:
- using System;
- using System.IO;
- using iTextSharp.text.pdf;
- {
- public static void Main()
- {
- Console.WriteLine("Chapter 5 example 5: colspan, rowspan, padding, spacing, colors");
-
- Document document = new Document();
- try
- {
-
-
-
- PdfWriter.GetInstance(document, new FileStream("Chap0505.pdf", FileMode.Create));
-
- document.Open();
-
- Table table = new Table(3);
- table.BorderWidth = 1;
- table.BorderColor = new Color(0, 0, 255);
- table.Padding = 5;
- table.Spacing = 5;
- Cell cell = new Cell("header");
- cell.Header = true;
- cell.Colspan = 3;
- table.AddCell(cell);
- cell = new Cell("example cell with colspan 1 and rowspan 2");
- cell.Rowspan = 2;
- cell.BorderColor = new Color(255, 0, 0);
- table.AddCell(cell);
- table.AddCell("1.1");
- table.AddCell("2.1");
- table.AddCell("1.2");
- table.AddCell("2.2");
- table.AddCell("cell test1");
- cell = new Cell("big cell");
- cell.Rowspan = 2;
- cell.Colspan = 2;
- cell.BackgroundColor = new Color(0xC0, 0xC0, 0xC0);
- table.AddCell(cell);
- table.AddCell("cell test2");
- document.Add(table);
- }
- catch (DocumentException de)
- {
- Console.Error.WriteLine(de.Message);
- }
- catch (IOException ioe)
- {
- Console.Error.WriteLine(ioe.Message);
- }
-
- document.Close();
-
- Console.Read();
- }
- }