1.1 生成Document
Document是我们要生成的PDF文件所有元素的容器,因此要生成一个PDF文档,必须首先定义一个Document对象。
Document有三种构造函数:
public Document();
public Document(Rectangle pageSize);
public Document(Rectangle pageSize, float marginLeft, float marginRight, float marginTop, float marginBottom);
第一种方法没有定义任何参数,生成的文档将自动采用A4大小的纸张;第二种方法,用户可以定义纸张的大小;而第三种方法中,用户不仅可以定义纸张大小,而且还能定义页面的左右上下边距。
我们通过下面的语句定义一个Document对象,页面大小为A4,四周边距均为50。
Document document = new Document(PageSize.A4, 50, 50, 50, 50);
如果页面需要采用横排模式,只要修改第一个参数就行:
Document doc = new Document(PageSize.A4.rotate(),50,50,50,50);
1.2 指定Document类型为PDF
定义了Document对象后,紧接着需要指定Document对象的类型。因为使用iText库不仅支持PDF文档的创建,还可以支持Html、RTF、Xml、Word等多种文档类型,我们要生成PDF文档格式,需要调用如下的方法:
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream("c:\\ITextTest.pdf"));
如果你想创建的不是PDF文档,则可以根据你想创建的文档类型选择创建HtmlWriter、RtfWriter、XmlWriter、RtfWriter2(注:word文档)对象,具体支持的文档类型可以查看iText的API文档。
你可以设置生成的PDF文档外观,比如是否显示菜单栏、工具栏等,设置方法如下:
writer.setViewerPreferences(PdfWriter.HideMenubar);
writer.setViewerPreferences(PdfWriter.HideToolbar);
writer.setViewerPreferences(PdfWriter.HideMenubar
| PdfWriter.HideToolbar);
第一条语句隐藏了菜单栏,第二条语句隐藏了工具栏,第三条语句则可以同时实现菜单栏和工具栏的隐藏。
1.3往Document中写入内容
到此为止我们已经成功创建了一个PDF文档,现在可以往里写入数据了。
为了写入数据,我们首先要做的事将当前文档打开:
document.open();
常用的构成PDF文件的元素有Chunk、Paragraph、Phrase、List、Image、Table等,下面我们对它们进行简单的介绍。
1.4 Chunk
Chunk是可以往Document中添加的最小元素,你可以将其直接添加到Document中,document.add(new Chunk("ZipCode"));
你可以为Chunk对象指定颜色,字体,但是一个Chunk对象只能有一种颜色和字体,也就是说Chunk就是一个“原子”对象,你无法让一个Chunk对象中的不同字符拥有不同的属性。
Chunk对象一个有趣的功能就是可以为其下划线、上划线、删除线。
Chunk title = new Chunk("Title", titleFont);
title.setUnderline(Color.BLACK, 2.0f, 0.0f, 24.0f, 0.0f, PdfContentByte.LINE_CAP_BUTT); title.setUnderline(Color.BLACK, 2.0f, 0.0f, -12.0f, 0.0f, PdfContentByte.LINE_CAP_BUTT);
通过调用setUnderline()方法并设置参数,你可以将线段添加在Chunk对象的任意位置,还可以设置线段的颜色、粗细和形状(圆头线、平头线等)。
除了直接将Chunk对象加入文档中以外,你也可以将其作为更高级的PDF元素的一部分,比如:
Paragraph p = new Paragraph();
Chunk chunk = new Chunk("总经理");
p.add(chunk);
1.5 Paragraph
Paragraph顾名思义就是段落的意思,就好像Word中的一个段落,你可以定义它的段前间距,段后间距、段落对齐方式、左右缩进:
p.setAlignment(Element.ALIGN_JUSTIFIED);
p.setIndentationLeft(15f);
p.setIndentationRight(15f);
p.setSpacingBefore(15f);
p.setSpacingAfter(5f);
第一条语句定义了段落p的对齐方式,第二条语句定义了p的左侧缩进距离,第三条语句定义了p的右侧缩进距离,第四条语句定义了p的段前间距,第五条语句定义了p的段后间距,可以根据实际需要定义相应的值。
定义好一个Paragraph对象之后,将其加入文档中。
document.add(p);
1.6 Phrase
Phrase实现的功能与Paragraph相似,假如想要往文档中添加一个段落是,我们还是觉得使用Paragraph对象比较合适。
Phrase有许多种构造方式,通常我们只需要new Phrase(String string)或者new Phrase(String string, Font font)就可以创建一个Phrase对象了。但是还有类似Phrase(float leading, String string) 这样的构造函数。参数leading设置的是Phrase对象的行间距,当Phrase内容超过一行时,这个参数的作用就会展现出来。通常leading都应该是一个正值,不过如果你把它设置为一个负值的话,也会发现有趣的事情发生。
1.7 List
List类实现的效果类似于Word中的“项目符号和编号”,你可以通过下面的方法创建一个List对象:
List l = new List(true, false, 10);
l.add(new ListItem("First item of list"));
l.add(new ListItem("Second item of list"));
new List(true, false, 10)函数的第一个参数指明了你创建的是否是一个有编号的列表,true表示创建的是一个有编号的列表;第二个参数表示是否采用字母进行编号,true为字母,false为数字;第三个参数是列表的缩进量。
列表有列表项组成,ListItem就是List的列表项,创建完列表项之后通过add()方法就可以将其加入列表中。
你也可以直接将一个字符串加入List列表:
l.add("Third item of list");
你也可以创建一个新的List对象,将它加入到当前List对象中:
List sublist = new List(false, true, 10);
sublist.add("First subitem of third item");
sublist.add("Second subitem of third item");
l.add(sublist);
最后将List对象加入到文档中。
document.add(l);
1.8 Table和PdfPTable
要在PDF文件中创建表格,iText为我们提供了两个类,Table和PdfPTable。两种方法各有优点,总的来说Table类型的表格实现起来相对比较简单,但如果需要实现的表格比较复杂,有时就必须使用PdfPTable类。
首先简单介绍一下使用Table类生成表格的方法:
Table t = new Table(3, 2);
t.setBorderColor(Color.white);
t.setPadding(5);
t.setSpacing(5);
t.setBorderWidth(1);
第一行程序创建了一个3x2的表格,其后的程序分别设置了表格的边框颜色、单元格内文本间距、单元格间距、边框宽度。如果用户不希望显示表格边框,只需要将边框颜色设置成与背景色一致就行。由于默认的文档背景色为白色,因此我们把表格的边框颜色也设置为白色。
表格是有一个个单元格组成的。单元格的创建方法如下:
Cell c1 = new Cell("Header1");
t.addCell(c1);
这样我们就在表格的第一行第一列中写入了内容“Header1”。使用同样的方法我们可以继续往表格中加入内容。你会发现我们并没有指定单元格在表格中的位置,那么程序为怎样将我们加入的单元格加到哪里呢?程序默认的加入单元格顺序是从第一行第一列开始,以行的顺序从左往右一次加入单元格,等第一行放满之后再从第二行第一列开始,依次从左往右填充表格。
如果你不想按照程序默认的顺序往表格中写入内容,也可以调用addCell(Cell aCell, int row, int column)或addCell(Cell aCell, Point aLocation)方法,都可以将内容直接放入你指定的表格位置。
可以将一个表格加入另一个表格中,即表格的嵌套,实现的方式是insertTable(Table table)。
Table subTable = new Table(2, 2);
subTable.addCell("1.3.1");
subTable.addCell("1.3.2");
subTable.addCell("1.3.3");
t.insertTable(subTable);
PdfPTable类生成表格是这样实现的:
PdfPTable table = new PdfPTable(3);
这样就实现了一个3列的表格。你也可以预先指定每一列的宽度,使用如下的方法实现一个表格:
float[] widths = {15f, 25f, 60f};
PdfPTable table = new PdfPTable(widths);
上面的方法定义了一个3列的表格,每列所占的宽度分别为15%、25%、60%。通常生成的表格默认以80%的比例显示在页面上,你需要调用PdfPTable的setWidthPercentage(float widthPercentage)方法设置表格宽度,如果将参数设置成100,表格将占满整个页面宽度。
也可以设定表格的绝对宽度:table.setTotalWidth(300),这样就将表格的宽度设定在了300px。可是假如表格的内容超过了300px,表格的宽度会自动加长。如果要将表格锁定在300px,还需要添加table.setLockedWidth(true)的设定。
在创建PdfPTable对象的时候只需要指定列数,而不用指定行数,因为行数是可以自动添加的。表格创建完成以后,接着就需要往里面插入单元格元素。PdfPTable对象添加单元格的发放是addCell(Object object)。Object对象可以是PdfPCell、String、Phrase、Image,也可以是是PdfPTable对象本身,即在表格中嵌套一个表格。
为了实现某些特殊的表格形式,需要合并单元格。PdfPCell类提供了setColspan(int colspan)方法用于合并横向单元格,参数colspan指定要合并的单元格数。但是PdfPCell类中没有setRowspan()方法,也就是说你不能合并纵向单元格。不过你可以使用嵌套表格的方法达到类似的效果,就是使用table.addCell(PdfPTable table)将一个表格加入到单元格中。
通常的表格都需要一个表头,你表头中你可以定义表格的每一列所代表的含义,如同下面的这个被保险人清单表,其中第一行的内容就是我们需要的表头:
表头的内容也是通过table.addCell()方法添加到表格中的,完成之后你需要调用table.setHeaderRows(1)方法告诉程序这一行是你的表头。当表内容很大,一页无法显示时,程序会自动将表格进行分页,这时候让程序知道什么是表头就非常必要了,程序会在每一页的表格头部都加上表头。
出于某种需要,你可能必须将表格固定在页面的某一个位置,PdfPTable也为我们提供了这种方法:table.writeSelectedRows(int rowStart, int rowEnd, float xPos, float yPos, PdfContentByte canvas)。你可以参考API文档了解每个参数的含义。
1.9 添加页眉页脚
对于多页文档来说,页码标志是不可少的,这就涉及到了页眉页脚的添加方法。
Document容器里的页眉页脚类叫着HeaderFooter,创建HeaderFooter的方法有两个:
HeaderFooter(Phrase before, boolean numbered);
HeaderFooter(Phrase before, Phrase after);
HeaderFooter类可以替你计算当前页的页码并写入页眉或页脚中,方法一中的参数numbered就是让你选择是否显示页码,before和after参数指的是你要在页码前后显示的内容。加入你希望在将页码显示成“第i页”的形式,通过new HeaderFooter(“第”,”页”)方法就能实现。
通过setAlignment(int alignment)方法你可以设定页眉页脚是左对齐、右对齐还是居中显示。
默认的HeaderFooter对象会在显示一个边框,你可以通过setBorder()方法将其隐藏或选择显示某一侧的边框。
最终你需要告诉程序是将HeaderFooter对象显示为页眉还是页脚,对应的方法是document.setHeader()和document.setFooter()。
下面是实现页眉页脚的一个例子。
HeaderFooter footer = new HeaderFooter(new Phrase(" 第", FontFooter), new Phrase(" 页", FontFooter));
footer.setBorder(Rectangle.NO_BORDER);
footer.setAlignment(Element.ALIGN_BOTTOM);
document.setFooter(footer);
当生成PDF文档之后,也许你会发现在文档的页眉页脚只从第二页才开始开始,第一页中并没有你期望的页眉页脚。这是因为你程序添加的位置不对,为了在文档的第一页也能产生页眉页脚,你必须把上面的这段程序放在document.open()代码之前。
1.10 关闭Document
通过以上步骤,你基本可以实现一个想要的PDF文档了。你最后要做的就是调用document.close()方法将文档关闭。当然,由于JAVA的异常机制,别忘了把以上的程序放在try…catch()…之中以捕获可能发生的程序异常。
2.1 合并多个PDF文件
开发中有时需要将几个现成的PDF文档合并成一个文档,我们只需要使用PdfCopyFields就能实现。假设我们有两个名为source1.pdf、source2.pdf的文件,我们的目标是将它们合并成一个叫concatenated.pdf的文件。
方法是先用PdfReader对象得到源PDF文件:
PdfReader reader1 = new PdfReader("source1.pdf");
PdfReader reader2 = new PdfReader("source2.pdf");
这样我们的程序就得到了想要合并的文件内容,然后我们再定义一个PdfCopyFields对象:
PdfCopyFields copy = new PdfCopyFields(new FileOutputStream("concatenated.pdf"));
指定生成的文件为concatenated.pdf。然后将读入的内容写入该对象:
copy.addDocument(reader1);
copy.addDocument(reader2);
关闭PdfCopyFields对象:
copy.close();
你会发现,一个新的PDF文件就这样生成了,它包含了source1.pdf和source2.pdf两个文件的内容。