一、Itext简介
1、API地址:javadoc/index.html
如 D:/MyJAR/原JAR包/PDF/itext-5.5.3/itextpdf-5.5.3-javadoc/index.html
2、功能:a Free Java-PDF
3、中文支持:iTextAsian.jar,现在高版本Itext不支持语言包。
4、使用的版本:iTextpdf-5.0.0.jar, iTextAsian-2.0.jar
二、Itext API
(一)PDF文档生成的5步
-
/** -
* 5步生成一个PDF -
*/ -
public void createPdf() throws Exception { -
// 1-创建文本对象 Document -
Document document = new Document(PageSize.A4, 500, 150, 50, 50); -
// 2-初始化 pdf输出对象 PdfWriter -
PdfWriter.getInstance(document, out); -
// 3-打开 Document -
document.open(); -
// 4-往 Document 添加内容 -
document.add(new Paragraph("Hello! PDF!!!")); -
// 5-关闭 Document -
document.close(); -
} -
</span>
(二)文档对象:Document、Rectangle、PageSize
1、 Document — PDF对象
1)构造方法:
①、Document(Rectangle pageSize, float marginLeft, float marginRight, float marginTop,
float marginBottom):分别指pdf页面大小和内容距离文档边的距离。
②、默认 Document()为:A4,36,36,36,36
2)属性:
①、基本属性:版本(PdfVersionImp)、标题(Title)、作者(Author)、主题(Subject)、关键字(Keywords)、创建者(Creator)等等
②、其他属性:页面空白(Margins和marginLeft各个方位)
3)方法:
①、 add()-添加内容,newPage()-下一页, addDocListener-监听器
② 、getPageNumber()-第几页 ,getPageSize-页面大小 ,
top|left|right|bottom-页面预定义位置,置页眉页脚或者页码时有用,内部调用Rectangle的属性
setJavaScript_onLoad(添加js)等等
-
// 2-2 横向打印 -
document = new Document(PageSize.A4.rotate());// 横向打印 -
document = new Document(tRectangle.rotate());// 横向打印 -
try { -
// 解析器 -
PdfWriter writer= PdfWriter.getInstance(document, new FileOutputStream("pdf/pdfText.pdf")); -
// 3-为pdf添加属性信息 -
document.addAuthor("作者"); -
document.addTitle("标题"); -
document.addSubject("主题"); -
document.addKeywords("关键字"); -
//页边空白 -
document.setMargins(10, 20, 30, 40); -
document.open(); -
// 4-PDF添加内容 -
document.add(new Paragraph("Hello world")); -
// 5-添加Page -
document.newPage(); -
// writer.setPageEmpty(false);//显示空内容的页 -
writer.setPageEmpty(true);//不会显示空内容的页 -
document.newPage(); -
document.add(new Paragraph("New page")); -
logger.debug("PDF创建结束....");
2、 Rectangle— 页面对象
1)构造方法:
Rectangle(final float llx, final float lly, final float urx, final float ury)
Rectangle(PageSize.A4) -PageSize 封装常用的 Rectangle
2)属性
①、NO_BORDER-无边框(单元格),left|top|right|bottom
3)方法
①、rotate()-横向打印
②、setBackgroundColor()-背景色,
setBorder()-边框,
setBorderColor()-边框颜色
-
// 1-创建一个pdf文档,document -
Document document = null; -
document = new Document();// 默认PageSize.A4, 36, 36, 36, 36 -
document = new Document(PageSize.A4);// 等效于上面的 -
document = new Document(PageSize.A4, 50, 50, 50, 50);// PageSize封装了大量常用的Rectangle数据 -
// 2-Rectangle(pdf页面)创建Document -
// 一般是四个参数表示:左下角的坐标和右上角的坐标 -
Rectangle tRectangle = null; -
tRectangle = PageSize.A4;// PageSize封装了大量常用的Rectangle数据 -
tRectangle = new Rectangle(800, 600);// 长宽 -
tRectangle = new Rectangle(0, 0, 800, 600);// 等于上面 -
// 2-1 其他页面属性:不能和PageSize封装的静态一起使用 -
tRectangle.setBackgroundColor(BaseColor.BLACK);// 背景色 -
tRectangle.setBorder(1220);// 边框 -
tRectangle.setBorderColor(BaseColor.BLUE); -
tRectangle.setBorderWidth(244.2f); -
document = new Document(tRectangle);</span>
3、综合案例代码:
-
<span style="font-family:SimSun;"> /** -
* 页面大小,页面背景色,页边空白,Title,Author,Subject,Keywords -
* -
* @throws DocumentException -
*/ -
public void myPDF() throws DocumentException { -
// 1- 页面的属性 -
Rectangle tRectangle = new Rectangle(PageSize.A4); // 页面大小 -
// tRectangle = new Rectangle(0, 0, 800, 600); -
tRectangle.setBackgroundColor(BaseColor.ORANGE); // 页面背景色 -
tRectangle.setBorder(1220);// 边框 -
tRectangle.setBorderColor(BaseColor.BLUE);// 边框颜色 -
tRectangle.setBorderWidth(244.2f);// 边框宽度 -
Document doc = new Document(tRectangle);// 定义文档 -
doc = new Document(tRectangle.rotate());// 横向打印 -
PdfWriter writer = PdfWriter.getInstance(doc, out);// 书写器 -
// PDF版本(默认1.4) -
writer.setPdfVersion(PdfWriter.PDF_VERSION_1_2); -
// 2-PDF文档属性 -
doc.addTitle("Title@sample");// 标题 -
doc.addAuthor("Author@rensanning");// 作者 -
doc.addSubject("Subject@iText sample");// 主题 -
doc.addKeywords("Keywords@iText");// 关键字 -
doc.addCreator("Creator@iText");// 谁创建的 -
// 3-综合属性: -
doc.setMargins(10, 20, 30, 40);// 页边空白 -
doc.open();// 打开文档 -
doc.add(new Paragraph("Hello World"));// 添加内容 -
// 4-添加下一页 -
doc.newPage(); -
writer.setPageEmpty(true);// fasle-显示空内容的页;true-不会显示 -
doc.newPage(); -
doc.add(new Paragraph("New page")); -
doc.close(); -
} -
</span>
(三)内容对象:
1、中文支持:
1)BaseFont-确认支持中文
2)Font-字体的设置,如颜色,字体,大小等
3)固定用法如下:
-
<span style="font-family:SimSun;"> /** -
* 支持中文 -
* -
* @return -
*/ -
public Font getChineseFont() { -
BaseFont bfChinese; -
Font fontChinese = null; -
try { -
bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); -
// fontChinese = new Font(bfChinese, 12, Font.NORMAL); -
fontChinese = new Font(bfChinese, 12, Font.NORMAL, BaseColor.BLUE); -
} catch (DocumentException e) { -
e.printStackTrace(); -
} catch (IOException e) { -
e.printStackTrace(); -
} -
return fontChinese; -
} -
} -
</span>
2、Element接口
1)内容对象基本都实现这个接口。如Chunk、 Phrase、 Paragraph
2)一些有用的方位参数:
ALIGN_LEFT, ALIGN_CENTER、 ALIGN_RIGHT, ALIGN_JUSTIFIED 。
如设置居中对齐:setAlignment(Element.ALIGN_CENTER)
3、 Chunk
1)块对象: a String, a Font, and some attributes
2)方法:Chunk.NEWLINE-换行,
setUnderline(0.2f, -2f)- 下划线
setTextRise(6)-上浮
-
<span style="font-family:SimSun;">// 1-Chunk块对象: a String, a Font, and some attributes -
document.add(new Chunk("中文输出: ", getChineseFont())); -
Chunk tChunk2 = new Chunk("输出的内容", getChineseFont()); -
tChunk2.setBackground(BaseColor.CYAN, 1f, 0.5f, 1f, 1.5f); // 设置背景色 -
tChunk2.setTextRise(6); // 上浮 -
tChunk2.setUnderline(0.2f, -2f); // 下划线 -
document.add(tChunk2); -
document.add(Chunk.NEWLINE); // 新建一行 -
// document.add(new Phrase("Phrase page :")); //会上浮,不知道原因??</span>
4、 Phrase
1)Phrase短语对象: a List of Chunks with leading
2)方法:add(Element)-添加方法,add(Chunk.NEWLINE)-内部换行
setLeading(14f)-行间距
-
<span style="font-family:SimSun;"> // 2-Phrase短语对象: a List of Chunks with leading -
document.add(new Phrase("Phrase page :")); -
Phrase tPhrase = new Phrase(); -
Chunk name = new Chunk("China"); -
name.setUnderline(0.2f, -2f); -
tPhrase.add(name); -
tPhrase.add(Chunk.NEWLINE);// 放在容器中好用 -
tPhrase.add(new Chunk("换行了 :", getChineseFont())); -
tPhrase.add(new Chunk("chinese")); -
tPhrase.setLeading(14f);// 行间距 -
document.add(tPhrase); -
// 这边就好用,上面是Chunk,就不好用 -
// 放在段落或短语中又好用 -
document.add(Chunk.NEWLINE); -
Phrase director2 = new Phrase(); -
Chunk name2 = new Chunk("换行了---Japan", getChineseFont()); -
name2.setUnderline(0.2f, -2f); -
director2.add(name2); -
director2.add(new Chunk(",")); -
director2.add(new Chunk(" ")); -
director2.add(new Chunk("japanese上浮下", getChineseFont()).setTextRise(3f)); -
director2.setLeading(24); -
document.add(director2);</span>
5、 Paragraph—(新段落另起一行)
1)段落对象: a Phrase with extra properties and a newline
2)方法:
add(Element)-添加; setLeading(20f)-行间距,一个Paragraph只有一个行间距;
setIndentationLeft()-左缩进, setIndentationRight-右缩进, setFirstLineIndent-首行缩进;
setSpacingBefore-设置上空白, setSpacingAfter(10f)-设置段落下空;
setAlignment(Element.ALIGN_CENTER)-居中对齐;
-
<span style="font-family:SimSun;">// 3-Paragraph段落对象: a Phrase with extra properties and a newline -
document.add(new Paragraph("Paragraph page")); -
Paragraph info = new Paragraph(); -
info.add(new Chunk("China ")); -
info.add(new Chunk("chinese")); -
info.add(Chunk.NEWLINE); // 好用的 -
info.add(new Phrase("Japan ")); -
info.add(new Phrase("japanese")); -
info.setSpacingAfter(10f);// 设置段落下空白 -
document.add(info); -
// 段落是比较好用的 -
Paragraph tParagraph = new Paragraph("段落是文章中最基本的单位。内容上它具有一个相对完整的意思;在文章中,段具有换行的标。段是由句子或句群组成的,在文章中用于体现作者的思路发展或全篇文章的层次。有的段落只有一个句子,称为独句段,独句段一般是文章的开头段、结尾段、" -
+ "过渡段强调段等特殊的段落。多数段落包括不止一个句子或句群,叫多句段。中文段落开头前一般空两个格。", getChineseFont()); -
tParagraph.setAlignment(Element.ALIGN_JUSTIFIED);// 对齐方式 -
tParagraph.setIndentationLeft(12);// 左缩进 -
tParagraph.setIndentationRight(12);// 右缩进 -
tParagraph.setFirstLineIndent(24);// 首行缩进 -
tParagraph.setLeading(20f);// 行间距 -
tParagraph.setSpacingBefore(5f);// 设置上空白 -
tParagraph.setSpacingAfter(10f);// 设置段落下空白 -
document.add(tParagraph); -
// 每个新的段落会另起一行 -
tParagraph = new Paragraph("新的段落", getChineseFont()); -
tParagraph.setAlignment(Element.ALIGN_CENTER);// 居中 -
document.add(tParagraph); -
</span>
综合代码如下:
-
<span style="font-family:SimSun;"> /** -
* 添加内容 插入Chunk, Phrase, Paragraph, List -
* -
* @author ShaoMin -
* @throws Exception -
*/ -
public void addContent() throws Exception { -
Document document = new Document(PageSize.A4); -
PdfWriter.getInstance(document, out); -
document.open(); -
// 1-Chunk块对象: a String, a Font, and some attributes -
document.add(new Chunk("中文输出: ", getChineseFont())); -
Chunk tChunk2 = new Chunk("输出的内容", getChineseFont()); -
tChunk2.setBackground(BaseColor.CYAN, 1f, 0.5f, 1f, 1.5f); // 设置背景色 -
tChunk2.setTextRise(6); // 上浮 -
tChunk2.setUnderline(0.2f, -2f); // 下划线 -
document.add(tChunk2); -
document.add(Chunk.NEWLINE); // 新建一行 -
// document.add(new Phrase("Phrase page :")); //会上浮,不知道原因?? -
// 2-Phrase短语对象: a List of Chunks with leading -
document.add(new Phrase("Phrase page :")); -
Phrase tPhrase = new Phrase(); -
Chunk name = new Chunk("China"); -
name.setUnderline(0.2f, -2f); -
tPhrase.add(name); -
tPhrase.add(Chunk.NEWLINE);// 放在容器中好用 -
tPhrase.add(new Chunk("换行了 :", getChineseFont())); -
tPhrase.add(new Chunk("chinese")); -
tPhrase.setLeading(14f);// 行间距 -
document.add(tPhrase); -
// 这边就好用,上面是Chunk,就不好用 -
// 放在段落或短语中又好用 -
document.add(Chunk.NEWLINE); -
Phrase director2 = new Phrase(); -
Chunk name2 = new Chunk("换行了---Japan", getChineseFont()); -
name2.setUnderline(0.2f, -2f); -
director2.add(name2); -
director2.add(new Chunk(",")); -
director2.add(new Chunk(" ")); -
director2.add(new Chunk("japanese上浮下", getChineseFont()).setTextRise(3f)); -
director2.setLeading(24); -
document.add(director2); -
// 3-Paragraph段落对象: a Phrase with extra properties and a newline -
document.add(new Paragraph("Paragraph page")); -
Paragraph info = new Paragraph(); -
info.add(new Chunk("China ")); -
info.add(new Chunk("chinese")); -
info.add(Chunk.NEWLINE); // 好用的 -
info.add(new Phrase("Japan ")); -
info.add(new Phrase("japanese")); -
info.setSpacingAfter(10f);// 设置段落下空白 -
document.add(info); -
// 段落是比较好用的 -
Paragraph tParagraph = new Paragraph("段落是文章中最基本的单位。内容上它具有一个相对完整的意思;在文章中,段具有换行的标。段是由句子或句群组成的,在文章中用于体现作者的思路发展或全篇文章的层次。有的段落只有一个句子,称为独句段,独句段一般是文章的开头段、结尾段、" -
+ "过渡段强调段等特殊的段落。多数段落包括不止一个句子或句群,叫多句段。中文段落开头前一般空两个格。", getChineseFont()); -
tParagraph.setAlignment(Element.ALIGN_JUSTIFIED);// 对齐方式 -
tParagraph.setIndentationLeft(12);// 左缩进 -
tParagraph.setIndentationRight(12);// 右缩进 -
tParagraph.setFirstLineIndent(24);// 首行缩进 -
tParagraph.setLeading(20f);// 行间距 -
tParagraph.setSpacingBefore(5f);// 设置上空白 -
tParagraph.setSpacingAfter(10f);// 设置段落下空白 -
document.add(tParagraph); -
// 每个新的段落会另起一行 -
tParagraph = new Paragraph("新的段落", getChineseFont()); -
tParagraph.setAlignment(Element.ALIGN_CENTER);// 居中 -
document.add(tParagraph); -
document.close(); -
} -
</span>
6、Image继承自Rectangle
1)、初始化:Image img = Image.getInstance("source/imag/bage.png")
2)、方法:
setAlignment(Image.LEFT)-对齐方式,setBorder(Image.BOX)-边框,
setBorderWidth(10)-边框宽度,setBorderColor(BaseColor.WHITE)-边框颜色,
scaleToFit(1000, 72)-大小,setRotationDegrees(-30)-旋转,
setAbsolutePosition()-绝对位置
-
<span style="font-family:SimSun;"> // 图片Image对象 -
Image img = Image.getInstance("source/imag/bage.png"); -
img.setAlignment(Image.LEFT); -
img.setBorder(Image.BOX); -
img.setBorderWidth(10); -
img.setBorderColor(BaseColor.WHITE); -
img.scaleToFit(1000, 72);// 大小 -
img.setRotationDegrees(-30);// 旋转 -
document.add(img);</span>
7、Anchor(锚点、超链接) 、Chapter、Section(目录章节)等:
-
<span style="font-family:SimSun;"> /** -
* 插入Anchor, Image, Chapter, Section -
* -
* @author ShaoMin -
* @throws Exception -
* -
*/ -
public void insertObject() throws Exception { -
Document document = new Document(PageSize.A4); -
PdfWriter.getInstance(document, out); -
document.open(); -
// Anchor超链接和锚点对象: internal and external links -
Paragraph country = new Paragraph(); -
Anchor dest = new Anchor("我是锚点,也是超链接", getChineseFont()); -
dest.setName("CN"); // 设置锚点的名字 -
dest.setReference("http://www.china.com");// 连接 -
country.add(dest); -
country.add(String.format(": %d sites", 10000)); -
document.add(country); -
Anchor toUS = new Anchor("连接到设置的CN锚点。", getChineseFont()); -
toUS.setReference("#CN");// 取到锚点 -
document.add(toUS); -
// 图片Image对象 -
Image img = Image.getInstance("source/imag/bage.png"); -
img.setAlignment(Image.LEFT); -
img.setBorder(Image.BOX); -
img.setBorderWidth(10); -
img.setBorderColor(BaseColor.WHITE); -
img.scaleToFit(1000, 72);// 大小 -
img.setRotationDegrees(-30);// 旋转 -
document.add(img); -
// Chapter, Section对象(目录对象) -
Paragraph title = new Paragraph("一级标题", getChineseFont()); -
Chapter chapter = new Chapter(title, 1); -
Paragraph title2 = new Paragraph("二级标题1", getChineseFont()); -
Section section = chapter.addSection(title2); -
section.setBookmarkTitle("bmk");// 左边目录显示的名字,不写就默认名 -
section.setIndentation(30); -
section.setIndentationLeft(5); -
section.setBookmarkOpen(false); -
section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT); -
Section section2 = chapter.addSection(new Paragraph("二级标题2", getChineseFont())); -
section2.setIndentation(30); -
section2.setIndentationLeft(5); -
section2.setBookmarkOpen(false); -
section2.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT); -
Section subsection = section.addSection(new Paragraph("三级标题1", getChineseFont())); -
subsection.setIndentationLeft(10); -
// subsection.setNumberDepth(1); -
subsection.setNumberStyle(Section.NUMBERSTYLE_DOTTED); -
Section subsection2 = section2.addSection(new Paragraph("三级标题2", getChineseFont())); -
subsection2.setIndentationLeft(10); -
subsection2.setNumberStyle(Section.NUMBERSTYLE_DOTTED); -
document.add(chapter); -
document.close(); -
} -
</span>
(四)、表格对象:Table、PdfPTable
1、构造方法:
PdfPTable datatable = new PdfPTable(6);//列数
PdfPTable datatable = new PdfPTable(new float[]{1,2,3})-每个单元格宽度
2、结构:
PdfPTable[PdfPTable[PdfPCell[Paragraph]]]
3、方法:
1) setWidths(数组)-单元格宽度, setTotalWidth(300f)-表格的总宽度,
setWidthPercentage(100)-表格的宽度百分比,setLockedWidth(true)-宽度锁定
2) getDefaultCell()-得到默认单元格,addCell()-添加单元格
setPadding(2)-单元格的间隔 ,setBackgroundColor(BaseColor.GREEN)-背景色
3) setSpacingAfter(40f)-设置表格下面空白行, setSpacingBefore(20f)-设置表格上面空白行
new Paragraph(“\n\n”)-可以实现换行,留白
4)setBorderWidth(2)-边框宽度
5)setHorizontalAlignment(Element.ALIGN_CENTER)-对齐方式
6)写入绝对位置:
PdfContentByte tContent = writer.getDirectContent()-得到层
table.writeSelectedRows(0,-1, 0, -1, 100, 200, tContent)-写入绝对位置
-
<span style="font-family:SimSun;"> /** -
* 插入表格 -
* -
* @author ShaoMin -
* @throws Exception -
*/ -
public void insertTable() throws Exception { -
Document document = new Document(PageSize.A4, 50, 50, 50, 50); -
// 使用PDFWriter进行写文件操作 -
PdfWriter.getInstance(document, out); -
document.open(); -
// 中文字体(现在高版本的不支持中文包) -
BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); -
Font fontChinese = new Font(bfChinese, 12, Font.NORMAL);// 中文、12、正常 -
int colNumber = 6; -
// PdfPTable[PdfPTable[PdfPCell[Paragraph]]] -
// 创建有6列的表格 -
PdfPTable datatable = new PdfPTable(colNumber); -
// 定义表格的宽度 -
int[] cellsWidth = { 1, 1, 1, 1, 1, 1 }; -
datatable.setWidths(cellsWidth);// 单元格宽度 -
// datatable.setTotalWidth(300f);//表格的总宽度 -
datatable.setWidthPercentage(100);// 表格的宽度百分比 -
datatable.getDefaultCell().setPadding(2);// 单元格的间隔 -
datatable.getDefaultCell().setBorderWidth(2);// 边框宽度 -
// 设置表格的底色 -
datatable.getDefaultCell().setBackgroundColor(BaseColor.GREEN); -
datatable.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER); -
// PdfPTable[PdfPCell[Paragraph]] -
// 添加表头元素 -
for (int i = 0; i < colNumber; i++) { -
datatable.addCell(new Paragraph(tableHeader[i], fontChinese)); -
} -
// 添加表格的内容 -
for (int i = 0; i < colNumber; i++) { -
datatable.addCell(new Paragraph(tableCont[i], fontChinese)); -
} -
// 空白表格 -
for (int i = 0; i < colNumber; i++) { -
PdfPCell cell = new PdfPCell(new Paragraph("")); -
cell.setFixedHeight(10);// 单元格高度 -
datatable.addCell(cell); -
} -
datatable.setSpacingAfter(40f);// 设置表格下面空白行 -
document.add(datatable);// 把表格加入文档 -
// 跨行跨列表格 -
PdfPTable table = new PdfPTable(3); // 3列表格 -
PdfPCell cell; // 单元格 -
cell = new PdfPCell(new Phrase("跨3列", getChineseFont())); -
cell.setColspan(3);// 跨3列 -
table.addCell(cell); -
cell = new PdfPCell(new Phrase("跨2行", getChineseFont())); -
cell.setRowspan(2);// 跨2行 -
table.addCell(cell); -
table.addCell("row 1; cell 1"); -
table.addCell("row 1; cell 2"); -
table.addCell("row 2; cell 1"); -
table.addCell("row 2; cell 2"); -
document.add(table); -
// 表格的嵌套 -
PdfPTable tableFather = new PdfPTable(4); -
tableFather.setSpacingBefore(20f);// 设置表格上面空白行 -
// 1行2列 -
PdfPTable nested1 = new PdfPTable(2); -
nested1.addCell("1.1"); -
nested1.addCell("1.2"); -
// 2行1列 -
PdfPTable nested2 = new PdfPTable(1); -
nested2.addCell("2.1"); -
nested2.addCell("2.2"); -
// 将表格插入到指定位置 -
for (int k = 0; k < 12; ++k) { -
if (k == 1) { -
tableFather.addCell(nested1); -
} else if (k == 6) { -
tableFather.addCell(nested2); -
} else { -
tableFather.addCell("cell " + k); -
} -
} -
document.add(tableFather); -
document.close(); -
} -
</span>
(五)、单元格对象: PdfPCell
1、构造函数
PdfPCell cell= new PdfPCell(new Paragraph(“表格”, 中文支持)
2、方法
1)setBackgroundColor(BaseColor.CYAN)-背景色
2)setMinimumHeight(30f)-最小高度
setFixedHeight(40f)-固定高度。表格的高度通过单元格高度完成
3)setBorder(Rectangle.NO_BORDER)-无边框,setBorderWidth(0)-无边框。不设,默认是有边框的
setBorderColor(new BaseColor(255, 0, 0))-边框颜色
4)setHorizontalAlignment(Element.ALIGN_CENTER)-水平居中
setVerticalAlignment(Element.ALIGN_MIDDLE)-垂直居中。设置单元格内容的显示
5)setRowspan(2)-跨2行,setColspan(2)-跨2列
-
<span style="font-family:SimSun;"> /** -
* 插入自定义表格 -
* -
* @author ShaoMin -
* @throws Exception -
*/ -
public void myTable() throws Exception { -
Document document = new Document(PageSize.A4, 50, 50, 50, 50); -
PdfWriter writer = PdfWriter.getInstance(document, out); -
document.open(); -
PdfPTable table = new PdfPTable(6); -
// 添加表头元素 -
for (int i = 0; i < 6; i++) { -
table.addCell(new Paragraph(tableHeader[i], getChineseFont())); -
} -
// 添加表格的内容 -
for (int i = 0; i < 6; i++) { -
table.addCell(new Paragraph(tableCont[i], getChineseFont())); -
} -
table.setSpacingBefore(10f);// 设置表格上面空白宽度 -
// 1-表格的宽度和布局 -
table.setHorizontalAlignment(Element.ALIGN_LEFT);// 居左 -
table.setTotalWidth(369.7f);// 表格的总宽度 -
table.setWidths(new float[] { 0.1565f, 0.15f, 0.15f, 0.145f, 0.15f, 0.145f });// 单元格宽度 -
table.setWidthPercentage(100);// 设置表格宽度为%100 -
// table.setLockedWidth(true);// 宽度锁定,不锁定,下面有变化 -
document.add(table); -
document.add(new Paragraph("\n\n")); -
// 居中 -
table.setHorizontalAlignment(Element.ALIGN_CENTER); -
document.add(table); -
document.add(new Paragraph("\n\n")); -
// 居右 -
table.setWidthPercentage(50);// 宽度减半 -
table.setHorizontalAlignment(Element.ALIGN_RIGHT); -
document.add(table); -
document.add(new Paragraph("\n\n")); -
// 固定宽度 -
table.setTotalWidth(300); -
table.setLockedWidth(true);// 锁定宽度 -
document.add(table); -
// 2-表格的边框、高度、设置单元格颜色 、前后距离 -
PdfPCell cell = new PdfPCell(new Paragraph("合并3个单元格", getChineseFont())); -
cell.setColspan(3); -
cell.setBackgroundColor(BaseColor.CYAN); -
cell.setMinimumHeight(30f);// 最小高度 -
cell.setFixedHeight(40f);// 固定高度 -
table.addCell(cell); -
// 单元格内文本 -
Paragraph tParagraph = new Paragraph("居中", getChineseFont()); -
tParagraph.setAlignment(Element.ALIGN_CENTER); -
cell = new PdfPCell(tParagraph); -
cell.setBorderColor(new BaseColor(255, 0, 0)); // 边框 ,下面的表格有可能会覆盖 -
cell.setFixedHeight(45f);// 固定高度,覆盖前面的固定高度 -
cell.setHorizontalAlignment(Element.ALIGN_CENTER);// 水平居中 -
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);// 垂直居中 -
table.addCell(cell); -
// 单元格背景色 -
cell = new PdfPCell(new Paragraph("无边框", getChineseFont())); -
cell.setBorder(Rectangle.NO_BORDER);// 无边框 -
cell.setBorderWidth(0);// 无边框 -
table.addCell(cell); -
// 边框颜色 -
cell = new PdfPCell(new Paragraph("单元格边框颜色", getChineseFont())); -
cell.setBorderColor(BaseColor.YELLOW); -
table.addCell(cell); -
document.add(new Paragraph("使用'SpacingBefore'和'setSpacingAfter'", getChineseFont())); -
table.setSpacingBefore(15f); // 前距离 -
document.add(table); -
table.setSpacingAfter(15f); // 后距离 -
document.add(table); -
// 3-写入文档的绝对位置 -
// 参数rowStart是你想开始的行的数目,参数rowEnd是你想显示的最后的行(如果你想显示所有的行,用-1), -
// xPos和yPos是表格的坐标,canvas是一个PdfContentByte对象。 -
document.add(new Paragraph( -
"写入文档的绝对位置:(writeSelectedRows(rowStart, rowEnd, xPos, yPos, canvas))参数rowStart是你想开始的行的数目,参数rowEnd是你想显示的最后的行(如果你想显示所有的行,用-1),xPos和yPos是表格的坐标,canvas是一个PdfContentByte对象。", -
getChineseFont())); -
PdfContentByte tContent = writer.getDirectContent(); -
table.writeSelectedRows(0, -1, 0, -1, 100, 200, tContent); -
document.add(new Paragraph("第1行到最后,从0开始计数", getChineseFont())); -
table.writeSelectedRows(1, -1, 100, 100, tContent); -
document.close(); -
} -
</span>
(六)、PDF结构-4层结构
1、四层结构
2、层对象: PdfContentByte
3、一、四层可操作;二、三层Itext内部处理
4、 操作:
⑴ PdfWriter 对象:
第 1 层操作:PdfWriter. getDirectContent(),
第 2 层操作:getDirectContentUnder()。
⑵ PdfStamper 对象
第 1 层操作: PdfStamper. getUnderContent(1),-可以加页数
第 2 层操作: PdfStamper .getOverContent(1)。
5、作用:添加水印、背景、添加内容到绝对位置、合并PDF
(六)、添加水印
1、方法:
PdfContentByte under = writer.getDirectContentUnder();//默认当前页
PdfContentByte under = stamp.getUnderContent(1);// 拿到层,可以有页数
2、文本水印
1)beginText():开始,endText()结束。
2)showTextAligned()写入文档,这个方法有很多重载,可以添加方位,旋转等。
-
<span style="font-family:SimSun;"> /** -
* 添加水印 -
* -
* @author ShaoMin -
* @throws Exception -
* -
*/ -
public void addShuyinByWriter() throws Exception { -
Document document = new Document(PageSize.A4); -
PdfWriter writer = PdfWriter.getInstance(document, out); -
document.open(); -
/* -
* PDF分为四层,第一层和第四层由低级操作来进行操作,第二层、第三层由高级对象操作(从下往上) -
* 第一层操作只能使用PdfWriter.DirectContent操作,第四层使用DirectContentUnder操作,。 -
* 第二层和第三层的PdfContentByte是由IText内部操作,没有提供api接口。 -
*/ -
PdfContentByte under = writer.getDirectContentUnder(); -
// under = writer.getDirectContent(); -
under.beginText(); -
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED); -
under.setFontAndSize(bf, 18); -
// under.setTextMatrix(30, 30); -
under.showTextAligned(Element.ALIGN_LEFT, "ShuiYin................", 230, 430, 45); -
under.endText(); -
document.close(); -
} -
</span>
3、图片水印与背景
1)添加水印:
2)水印与背景的区别:背景只需要把绝对置为从 文档左下角开始。 即设置setAbsolutePosition(0, 0)
3)位置的定位:理解页面对象——Rectangle
Rectangle tRectangle = new Rectangle(0, 0, 800, 600);
-
<span style="font-family:SimSun;"> /** -
* 添加水印 -
* -
* @author ShaoMin -
* @throws IOException -
* -
*/ -
public void addShuiYinByTempete() throws Exception { -
// 读取器 -
PdfReader reader = new PdfReader(templetePdf); -
// 解析器与输出 -
PdfStamper stamp = new PdfStamper(reader, out); -
// 图片水印 -
Image img = Image.getInstance("source/imag/bage.png"); -
img.setAbsolutePosition(100, 100);// 位置 -
PdfContentByte under = stamp.getUnderContent(1);// 拿到层,页数 -
under.addImage(img); -
// 文字水印 -
PdfContentByte over = stamp.getOverContent(1);// 拿到层,字显示在图片上 -
over.beginText(); -
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED); -
over.setFontAndSize(bf, 18); -
over.setTextMatrix(30, 30); -
over.showTextAligned(Element.ALIGN_LEFT, "ShuiYin", 230, 430, 45); -
over.endText(); -
// 背景图 -
Image img2 = Image.getInstance("resource/test.jpg"); -
img2.setAbsolutePosition(0, 0); -
PdfContentByte under2 = stamp.getUnderContent(3); -
under2.addImage(img2); -
// 关闭 -
stamp.close(); -
reader.close(); -
} -
</span>
(七)、添加头尾注和页码等
1、需要使用监听器,类似于Sax解析Xml:
1)PdfWriter. setPageEvent(PdfPageEvent event) - PdfPageEven接口
2)PdfPageEventHelper类实现了PdfPageEven接口。我们自定义只要实现PdfPageEventHelper即可,随意重
写需要的方法即可。
2、重写的方法:
onOpenDocument(PdfWriter writer, Document document)
onEndPage(PdfWriter writer, Document document)等等
3、添加头尾注和页码:——添加文本到绝对位置
-
<span style="font-family:SimSun;"> /** -
* 插入页眉页脚,需要使用监听器 -
* -
* @author ShaoMin -
* @throws Exception -
* -
*/ -
public void insertHeadAndFoot() throws Exception { -
Document doc = new Document(); -
PdfWriter writer = PdfWriter.getInstance(doc, out); -
// 内部类,处理器 -
writer.setPageEvent(new PdfPageHelper()); -
doc.open(); -
doc.add(new Paragraph("1 page")); -
doc.newPage(); -
doc.add(new Paragraph("2 page")); -
doc.close(); -
} -
</span>
-
<span style="font-family:SimSun;">/** -
* -
* @Title: 内部类 -
* @Description: -
* @Copyright: Copyright (c) 2014 -
* @Company: SinoSoft -
* -
* @author: ShaoMin -
* @version: 1.0 -
* @CreateDate:Nov 4, 2014 -
*/ -
class PdfPageHelper extends PdfPageEventHelper { -
@Override -
public void onEndPage(PdfWriter writer, Document document) { -
PdfContentByte cb = writer.getDirectContent();// 得到层 -
cb.saveState(); -
// 开始 -
cb.beginText(); -
cb.setFontAndSize(getBaseFont(), 10); -
// Header -
float x = document.top(-20);// 位置 -
// 左 -
cb.showTextAligned(PdfContentByte.ALIGN_LEFT, "H-Left", document.left(), x, 0); -
// 中 -
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "第" + writer.getPageNumber() + "页", (document.right() + document.left()) / 2, x, 0); -
// 右 -
cb.showTextAligned(PdfContentByte.ALIGN_RIGHT, "H-Right", document.right(), x, 0); -
// Footer -
float y = document.bottom(-20); -
// 左 -
cb.showTextAligned(PdfContentByte.ALIGN_LEFT, "F-Left", document.left(), y, 0); -
// 中 -
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "第" + writer.getPageNumber() + "页", (document.right() + document.left()) / 2, y, 0); -
// 右 -
cb.showTextAligned(PdfContentByte.ALIGN_RIGHT, "F-Right", document.right(), y, 0); -
cb.endText(); -
cb.restoreState(); -
} -
</span>
(八)、读取PDF即模板的使用
1、使用Adobe Acrobat 制作PDF模板(可以用word先编辑,另存为PDF格式)
1)文本域:工具-内容编辑-编辑文本域图像(自动会选中)
2)表单域:工具-表单-编辑-编辑-添加新域(或者编辑域)
3)编辑表单域可以设置一个name,如 ConNo;也可以设置显示的字体、大小、对齐方式等等。
2、涉及的核心类:PdfReader,PdfStamper
3、实现:
1)读取PDF文档( PdfReader )->交给解析器( PdfStamper )
-
<span style="font-family:SimSun;"> // 1-模板和生成的pdf -
String tPdfTemplateFile = "source/pdf/templete/EdorTemplete.pdf";// 获取模板路径 -
String tPdfResultFile = "temp/pdf/Edor_" + new Random().nextInt() + ".pdf";// 生成的文件路径 -
// 2-解析PDF模板 -
FileOutputStream fos = new FileOutputStream(tPdfResultFile);// 需要生成PDF -
PdfReader reader = new PdfReader(tPdfTemplateFile);// 模板 -
PdfStamper mPdfStamper = new PdfStamper(reader, fos);// 解析</span>
2)获取保单域( AcroFields )->获取所有的表单域数据(Map)
-
<span style="font-family:SimSun;"> // 3-获取到模板上预定义的参数域 -
AcroFields form = mPdfStamper.getAcroFields(); -
// 获取模板中定义的变量 -
Map<String, Item> acroFieldMap = form.getFields(); -
</span>
3)处理:循环Map,拿到key(即表单域的name),给表单域赋值即可。
AcroFields .setField(fieldName, fieldValue);
4)关闭PdfReader, PdfStamper。
-
<span style="font-family:SimSun;"> // 循环解析模板定义的表单域 -
int len = 4; -
for (Map.Entry<String, Item> entry : acroFieldMap.entrySet()) { -
// 获得块名 -
String fieldName = entry.getKey(); -
String fieldValue = "fill_" + len; -
System.out.println(fieldName + ":" + fieldValue); -
form.setField(fieldName, fieldValue); -
len++; -
} -
// 模板中的变量赋值之后不能编辑 -
mPdfStamper.setFormFlattening(true); -
reader.close();// 阅读器关闭,解析器暂时不关闭,因为创建动态表格还需要使用 -
mPdfStamper.close();</span>
5、完整代码如下:模板为上面截图模板:
-
<span style="font-family:SimSun;">package pdf.templete; -
import java.io.FileOutputStream; -
import java.util.HashMap; -
import java.util.Map; -
import java.util.Random; -
import com.itextpdf.text.pdf.AcroFields; -
import com.itextpdf.text.pdf.AcroFields.Item; -
import com.itextpdf.text.pdf.PdfReader; -
import com.itextpdf.text.pdf.PdfStamper; -
/** -
* -
* @Title: 利用PDF模板 -
* @Description: -
* @Copyright: Copyright (c) 2014 -
* @Company: SinoSoft -
* -
* @author: ShaoMin -
* @version: 1.0 -
* @CreateDate:Nov 4, 2014 -
*/ -
public class PdfTempleteWithIText { -
/** -
* @author ShaoMin -
* @param args -
*/ -
public static void main(String[] args) { -
PdfTempleteWithIText pdfTemplete = new PdfTempleteWithIText(); -
try { -
// 1-给PDF表单域赋值 -
pdfTemplete.fillFormDatas(); -
// 2-给PDF表格赋值 -
pdfTemplete.fillTableDatas(); -
} catch (Exception e) { -
e.printStackTrace(); -
} -
} -
/** -
* 获取模板表单,并赋值 固定用法 -
* -
* @author ShaoMin -
* @throws Exception -
*/ -
public void fillFormDatas() throws Exception { -
// 1-封装的数据,这边的key与pdf模板的域名保持一致 -
Map<String, String> mMapDatas = new HashMap<String, String>(); -
mMapDatas.put("CustomerName", "SAM-SHO");// 客户姓名 -
mMapDatas.put("ContNo", "123456789098765");// 合同号 -
mMapDatas.put("ContCount", "1");// 保单个数 -
mMapDatas.put("EdorType", "CT-退保");// 保全类型 -
mMapDatas.put("GetMoney", "999.99");// 保全失算金额 -
mMapDatas.put("AcceptName", "人寿保险");// 受理人 -
mMapDatas.put("AcceptDate", "2014-11-1");// 受理日期 -
// 2-模板和生成的pdf -
Random a = new Random(); -
a.nextInt(); -
String tPdfTemplateFile = "source/pdf/templete/EdorTemplete.pdf";// 获取模板路径 -
String tPdfResultFile = "temp/pdf/Edor_" + a.nextInt() + ".pdf";// 生成的文件路径 -
// 3-解析PDF模板 -
FileOutputStream fos = new FileOutputStream(tPdfResultFile);// 需要生成PDF -
PdfReader reader = new PdfReader(tPdfTemplateFile);// 模板 -
PdfStamper mPdfStamper = new PdfStamper(reader, fos);// 解析 -
// 4-获取到模板上预定义的参数域 -
AcroFields form = mPdfStamper.getAcroFields(); -
// 获取模板中定义的变量 -
Map<String, Item> acroFieldMap = form.getFields(); -
// 循环解析模板定义的表单域 -
for (Map.Entry<String, Item> entry : acroFieldMap.entrySet()) { -
// 获得块名 -
String fieldName = entry.getKey(); -
String fieldValue = mMapDatas.get(fieldName);// 通过名字,获取传入的参数值 -
if (!"".equals(fieldValue)) { -
// 为模板中的变量赋值(key与pdf模板定义的域名一致) -
form.setField(fieldName, fieldValue); -
System.out.println(fieldName + "," + fieldValue); -
} -
} -
// 模板中的变量赋值之后不能编辑 -
mPdfStamper.setFormFlattening(true); -
reader.close();// 阅读器关闭,解析器暂时不关闭,因为创建动态表格还需要使用 -
mPdfStamper.close(); -
} -
/** -
* 给PDF表格赋值 值动态的,一般建议使用模板, 直接创建绝对位置的表格 -
* -
* @author ShaoMin -
* @throws Exception -
*/ -
public void fillTableDatas() throws Exception { -
// 1-模板和生成的pdf -
String tPdfTemplateFile = "source/pdf/templete/EdorTemplete.pdf";// 获取模板路径 -
String tPdfResultFile = "temp/pdf/Edor_" + new Random().nextInt() + ".pdf";// 生成的文件路径 -
// 2-解析PDF模板 -
FileOutputStream fos = new FileOutputStream(tPdfResultFile);// 需要生成PDF -
PdfReader reader = new PdfReader(tPdfTemplateFile);// 模板 -
PdfStamper mPdfStamper = new PdfStamper(reader, fos);// 解析 -
// 3-获取到模板上预定义的参数域 -
AcroFields form = mPdfStamper.getAcroFields(); -
// 获取模板中定义的变量 -
Map<String, Item> acroFieldMap = form.getFields(); -
// 循环解析模板定义的表单域 -
int len = 4; -
for (Map.Entry<String, Item> entry : acroFieldMap.entrySet()) { -
// 获得块名 -
String fieldName = entry.getKey(); -
String fieldValue = "fill_" + len; -
System.out.println(fieldName + ":" + fieldValue); -
form.setField(fieldName, fieldValue); -
len++; -
} -
// 模板中的变量赋值之后不能编辑 -
mPdfStamper.setFormFlattening(true); -
reader.close();// 阅读器关闭,解析器暂时不关闭,因为创建动态表格还需要使用 -
mPdfStamper.close(); -
} -
}</span>
(九)、合并PDF-——核心是合并旧的,生成新的PDF
1、涉及的核心类:PdfReader,PdfCopy(PdfWriter的子类)
2、实现:2次循环
1)第一层循环:PDF合并的文件个数,有几个PDF需要合并。
①、每一个pdf文件都使用PdfReader获取:PdfReader reader = new PdfReader(files[i]);
② 、reader.getNumberOfPages()获取一个PDF有多少页
2)第二层循环:一个PDF文件的页数,一个PDF有几页
①、每一页都放入PdfCopy即可
PdfImportedPage page = copy.getImportedPage(reader, 第几页);
copy.addPage(page);
3、代码如下:
1)使用PdfCopy:
-
<span style="font-family:SimSun;"> /** -
* PDF文件合并 使用PdfCopy -
* -
* @author -
* @param files -
* @param os -
*/ -
public boolean mergePdfFiles(String[] files, String newfile) { -
boolean retValue = false; -
Document document = null; -
try { -
document = new Document(); -
PdfCopy copy = new PdfCopy(document, new FileOutputStream(newfile)); -
document.open(); -
for (int i = 0; i < files.length; i++) {// 几个pdf文件循环 -
PdfReader reader = new PdfReader(files[i]); -
int n = reader.getNumberOfPages(); -
for (int j = 1; j <= n; j++) {// 一个文件有多少页循环 -
document.newPage(); -
PdfImportedPage page = copy.getImportedPage(reader, j); -
copy.addPage(page); -
} -
} -
retValue = true; -
} catch (Exception e) { -
e.printStackTrace(); -
} finally { -
document.close(); -
} -
return retValue; -
} -
</span>
2)使用PdfWriter实现PDF合并
-
<span style="font-family:SimSun;"> /** -
* 合并PDF -
* -
* @author ShaoMin -
* @throws Exception -
* -
*/ -
public void mergePdf() throws Exception { -
String[] files = { "source/pdf/1.pdf", "source/pdf/2.pdf" }; -
String savepath = "source/pdf/mergePdf.pdf"; -
Document document = new Document(); -
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(savepath)); -
// PdfCopy copy = new PdfCopy(document, new -
// FileOutputStream(newfile));//使用copy -
document.open(); -
PdfContentByte cb = writer.getDirectContent();// 得到层 -
for (int i = 0; i < files.length; i++) { -
PdfReader reader = new PdfReader(files[i]); -
int n = reader.getNumberOfPages(); -
for (int j = 1; j <= n; j++) { -
document.newPage(); -
// PdfImportedPage page = copy.getImportedPage(reader, j); -
// copy.addPage(page); -
PdfImportedPage page = writer.getImportedPage(reader, j); -
cb.addTemplate(page, 0, 0);// 使用writer需要使用pdf的层,然后后添加 -
} -
} -
document.close(); -
// 使用PdfCopy 实现Pdf合并 -
// mergePdfFiles(files, savepath); -
} -
</span>
(十)、删除pdf页
1、思路:读取pdf文档,然后页码,然后输出到新的PDF
2、实现:
-
<span style="font-family:SimSun;"> /** -
* 删除页 -
* -
* @author ShaoMin -
* @throws Exception -
* -
*/ -
public void deletePage() throws Exception { -
// Document document = new Document(); -
// PdfWriter.getInstance(document, out); -
// document.open(); -
// document.add(new Paragraph("First page")); -
// document.add(new Paragraph(Document.getVersion())); -
// document.newPage(); -
// document.add(new Paragraph("New page1")); -
// document.newPage(); -
// document.add(new Paragraph("New page2")); -
// document.close(); -
// 删除的方法在于读取,然后选择页数,然后在输出到另一个pdf -
PdfReader reader = new PdfReader("deletePage.pdf");// 读取pdf -
reader.selectPages("1,3");// 选择页数 -
PdfStamper stamp = new PdfStamper(reader, out);// 输出 -
stamp.close(); -
reader.close(); -
} -
</span>
来源:oschina
链接:https://my.oschina.net/u/4279315/blog/3216066
