一、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、添加頭尾注和頁碼:——添加文本到絕對位置
(八)、讀取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>
轉載:https://blog.csdn.net/u012228718/article/details/40706499
