iText操作PDF問題總結
這個星期我的任務就是處理一些報表的打印問題,因為我算項目組裏對jasperreport比較熟悉的了,這個東東也是我引進到這個項目。ireport畫報表,使用struts的action輸出PDF到瀏覽器,這是我們目前的解決方案。今天遇到一個ireport解決不了的要求——合並單元格。類似下麵這樣的表結構:----------------------------------------------
| |__c_____________
dept | value |__b_____________
| | a
--------------------------------------------------------
也就是需要跨行,跨列!-_-。在html表格中解決這個很簡單,隻要設置單元格的colspan和rowspan即可。我在ireport沒有找到解決方案,如果您知道,請不吝賜教。查找資料弄了兩個小時沒進展,決定自己用iText寫吧,通過google、baidu資料順利達到了我的要求,僅在此記錄下遇到的問題和解決方法。
一。一個HelloWorld實例:
package com.lowagie.examples.general;
import java.io.FileOutputStream;
import java.io.IOException;
import com.lowagie.text.*;
import com.lowagie.text.pdf.PdfWriter;
/**
* Generates a simple 'Hello World' PDF file.
*
* @author blowagie
*/
public class HelloWorld {
/**
* Generates a PDF file with the text 'Hello World'
*
* @param args no arguments needed here
*/
public static void main(String[] args) {
System.out.println("Hello World");
// step a: creation of a document-object
Document document = new Document();
try {
// step b:
// we create a writer that listens to the document
// and directs a PDF-stream to a file
PdfWriter.getInstance(document,new FileOutputStream("HelloWorld.pdf"));
// step c: we open the document
document.open();
// step d: we add a paragraph to the document
document.add(new Paragraph("Hello World"));
} catch (DocumentException de) {
System.err.println(de.getMessage());
} catch (IOException ioe) {
System.err.println(ioe.getMessage());
}
// step e: we close the document
document.close();
}
}
可以看到一個PDF文件的輸出,總共隻需要5個步驟import java.io.FileOutputStream;
import java.io.IOException;
import com.lowagie.text.*;
import com.lowagie.text.pdf.PdfWriter;
/**
* Generates a simple 'Hello World' PDF file.
*
* @author blowagie
*/
public class HelloWorld {
/**
* Generates a PDF file with the text 'Hello World'
*
* @param args no arguments needed here
*/
public static void main(String[] args) {
System.out.println("Hello World");
// step a: creation of a document-object
Document document = new Document();
try {
// step b:
// we create a writer that listens to the document
// and directs a PDF-stream to a file
PdfWriter.getInstance(document,new FileOutputStream("HelloWorld.pdf"));
// step c: we open the document
document.open();
// step d: we add a paragraph to the document
document.add(new Paragraph("Hello World"));
} catch (DocumentException de) {
System.err.println(de.getMessage());
} catch (IOException ioe) {
System.err.println(ioe.getMessage());
}
// step e: we close the document
document.close();
}
}
a.創建一個Document實例
Document document = new Document();
b.將Document實例和文件輸出流用PdfWriter類綁定在一起
PdfWriter.getInstance(document,new FileOutputStream("HelloWorld.pdf"));
c.打開文檔
document.open();
d.在文檔中添加文字
document.add(new Paragraph("Hello World"));
e.關閉文檔
document.close();
這樣5個步驟,就可以生成一個PDF文檔了。
二。如何使用jsp、servlet輸出iText生成的pdf?
如果每次都在服務端生成一個PDF文件給用戶,不僅麻煩,而且浪費服務器資源,最好的方法就是以二進製流的形式輸送到客戶端。
1)JSP輸出:
<%@ page import="java.io.*,java.awt.Color,com.lowagie.text.*,com.lowagie.text.pdf.*"%>
<%
response.setContentType
( "application/pdf" );
Document document = new Document();
ByteArrayOutputStream buffer
= new ByteArrayOutputStream();
PdfWriter writer=
PdfWriter.getInstance( document, buffer );
document.open();
document.add(new Paragraph("Hello World"));
document.close();
DataOutput output =
new DataOutputStream
( response.getOutputStream() );
byte[] bytes = buffer.toByteArray();
response.setContentLength(bytes.length);
for( int i = 0;
i < bytes.length;
i++ )
{
output.writeByte( bytes[i] );
}
%>
<%
response.setContentType
( "application/pdf" );
Document document = new Document();
ByteArrayOutputStream buffer
= new ByteArrayOutputStream();
PdfWriter writer=
PdfWriter.getInstance( document, buffer );
document.open();
document.add(new Paragraph("Hello World"));
document.close();
DataOutput output =
new DataOutputStream
( response.getOutputStream() );
byte[] bytes = buffer.toByteArray();
response.setContentLength(bytes.length);
for( int i = 0;
i < bytes.length;
i++ )
{
output.writeByte( bytes[i] );
}
%>
2)servlet輸出,稍微改造下就可以使用在struts中:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
public void doGet
(HttpServletRequest request,
HttpServletResponse response)
throws IOException,ServletException
{
Document document =
new Document(PageSize.A4, 36,36,36,36);
ByteArrayOutputStream ba
= new ByteArrayOutputStream();
try
{
PdfWriter writer =
PdfWriter.getInstance(document, ba);
document.open();
document.add(new
Paragraph("Hello World"));
}
catch(DocumentException de)
{
de.printStackTrace();
System.err.println
("A Document error:" +de.getMessage());
}
document.close();
response.setContentType
("application/pdf");
response.setContentLength(ba.size());
ServletOutputStream out
= response.getOutputStream();
ba.writeTo(out);
out.flush();
}
import javax.servlet.*;
import javax.servlet.http.*;
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
public void doGet
(HttpServletRequest request,
HttpServletResponse response)
throws IOException,ServletException
{
Document document =
new Document(PageSize.A4, 36,36,36,36);
ByteArrayOutputStream ba
= new ByteArrayOutputStream();
try
{
PdfWriter writer =
PdfWriter.getInstance(document, ba);
document.open();
document.add(new
Paragraph("Hello World"));
}
catch(DocumentException de)
{
de.printStackTrace();
System.err.println
("A Document error:" +de.getMessage());
}
document.close();
response.setContentType
("application/pdf");
response.setContentLength(ba.size());
ServletOutputStream out
= response.getOutputStream();
ba.writeTo(out);
out.flush();
}
三。如何輸出中文?
首先需要下載iTextAsian.jar包,可以到iText的主站上下,ireport也是需要這個包的。然後定義中文字體:
private static final Font getChineseFont() {
Font FontChinese = null;
try {
BaseFont bfChinese = BaseFont.createFont("STSong-Light",
"UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
FontChinese = new Font(bfChinese, 12, Font.NORMAL);
} catch (DocumentException de) {
System.err.println(de.getMessage());
} catch (IOException ioe) {
System.err.println(ioe.getMessage());
}
return FontChinese;
}
Font FontChinese = null;
try {
BaseFont bfChinese = BaseFont.createFont("STSong-Light",
"UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
FontChinese = new Font(bfChinese, 12, Font.NORMAL);
} catch (DocumentException de) {
System.err.println(de.getMessage());
} catch (IOException ioe) {
System.err.println(ioe.getMessage());
}
return FontChinese;
}
我將產生中文字體封裝在方法內,自定義一個段落PDFParagraph繼承自Paragraph,默認使用中文字體:
class PDFParagraph extends Paragraph {
public PDFParagraph(String content) {
super(content, getChineseFont());
}
}
public PDFParagraph(String content) {
super(content, getChineseFont());
}
}
使用的時候就可以簡化了:
Paragraph par = new PDFParagraph("你好");
四。如何設置PDF橫向顯示和打印?
Rectangle rectPageSize = new Rectangle(PageSize.A4);// 定義A4頁麵大小
rectPageSize = rectPageSize.rotate();// 加上這句可以實現A4頁麵的橫置
Document doc = new Document(rectPageSize,50,50,50,50);//4個參數,設置了頁麵的4個邊距
rectPageSize = rectPageSize.rotate();// 加上這句可以實現A4頁麵的橫置
Document doc = new Document(rectPageSize,50,50,50,50);//4個參數,設置了頁麵的4個邊距
五。如何設置跨行和跨列?
使用PdfPTable和PdfPCell 是沒辦法實現跨行的,隻能跨列,要跨行使用com.lowagie.text.Table和com.lowagie.text.Cell類,Cell類有兩個方法:setRowspan()和setColspan()。
六。如何設置單元格邊界寬度?
Cell類的係列setBorderWidthXXXX()方法,比如setBorderWidthTop(),setBorderWidthRight()等
七。如何設置表頭?
希望每一頁都有表頭,可以通過設置表頭來實現。對於PdfPTable類來說,可以這樣設置:
PdfPTable table = new PdfPTable(3);
table.setHeaderRows(2); // 設置了頭兩行為表格頭
table.setHeaderRows(2); // 設置了頭兩行為表格頭
而對於om.lowagie.text.Table類,需要在添加完所有表頭的單元格後加上一句代碼:
table.endHeaders();
八。如何設置列寬?
Table table = new Table(8);
float[] widths = { 0.10f, 0.15f, 0.21f, 0.22f, 0.08f, 0.08f, 0.10f,
0.06f };
table.setWidths(widths);
float[] widths = { 0.10f, 0.15f, 0.21f, 0.22f, 0.08f, 0.08f, 0.10f,
0.06f };
table.setWidths(widths);
上麵的代碼設置了一個有8列的表格,通過一個float數組設置列寬,這裏是百分比。
九。單元格內段落文字居中和換行?
居中通過Cell類來設置,一開始我以為設置段落對齊就可以了,沒想到是需要設置單元格:
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
轉義符\n實現。在我的這個應用中,因為數據庫取出的數據是為了顯示在html上的,所以有很多<br>標簽,可以使用正則表達式替換成"\n"
"<br>1.測試<br>2.測試2".replaceAll("<br>|</br>","\n");
十。如何顯示頁碼?
複雜的頁碼顯示和水印添加,需要使用到PdfPageEventHelper、PdfTemplate等輔助類,具體的例子參見iText的文檔,如果隻是為了簡單的顯示頁數,可以使用下麵的代碼:
HeaderFooter footer = new HeaderFooter(new Phrase("頁碼:",getChineseFont()), true);
footer.setBorder(Rectangle.NO_BORDER);
document.setFooter(footer);
document.open();
你可能注意到了,添加footer需要在document.open之前。
footer.setBorder(Rectangle.NO_BORDER);
document.setFooter(footer);
document.open();
最後更新:2017-05-17 12:32:27
上一篇:
MySQL數據恢複的九把瑞士軍刀
下一篇:
DBA在傳統企業數據庫安全建設上能做些什麼?
常見移動設備的 CSS3 Media Query 整理
十進製轉換成二進製、八進製、十六進製的通用方法
Image Recognition Using Edge Detection
雲棲大會 20多家知名企業首批獲授權,加入阿裏雲Link城市物聯網平台合作夥伴
POJ 3525 二分+半麵相交
PLSQL連Oracle數據庫Could not load \"……\\bin\\oci.dll\"
數據挖掘技術的有趣應用:Kaggle的實踐
《vSphere性能設計:性能密集場景下CPU、內存、存儲及網絡的最佳設計實踐》一3.2.3 使用合適的測量工具
svn服務端的安裝與使用方式簡介(一)
minix添加係統調用