使用 iText 导出pdf表格
iText 是一种生成PDF报表的Java组件,其maven依赖如下:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.0.6</version>
</dependency>
老版本的jar包 itext-2.1.7.jar 依赖如下:
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.1.7</version>
</dependency>
生成表格的关键类 com.itextpdf.text.pdf.PDFPTable
。
示例1:生成一张两行两列的表格。
public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException{
PdfPTable table = new PdfPTable(2);//生成一个两列的表格
PdfPCell cell;
int size = 15;
cell = new PdfPCell(new Phrase("one"));
cell.setFixedHeight(size);//设置高度
table.addCell(cell);
cell = new PdfPCell(new Phrase("two"));
cell.setFixedHeight(size);
table.addCell(cell);
cell = new PdfPCell(new Phrase("three"));
cell.setFixedHeight(size);
table.addCell(cell);
cell = new PdfPCell(new Phrase("four"));
cell.setFixedHeight(size);
table.addCell(cell);
return table;
}
public void createPDF(String filename) throws IOException {
Document document = new Document(PageSize.A4);
try {
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
document.addTitle("example of PDF");
document.open();
PdfPTable table = createTable(writer);
document.add(table);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
} finally {
document.close();
}
}
效果如下图:
示例2:合并列。
public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException {
PdfPTable table = new PdfPTable(2);//生成一个两列的表格
...
cell = new PdfPCell(new Phrase("five"));
cell.setColspan(2);//设置所占列数
cell.setFixedHeight(size*2);//设置高度
cell.setHorizontalAlignment(Element.ALIGN_CENTER);//设置水平居中
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);//设置垂直居中
table.addCell(cell);
return table;
}
效果如下图:
注意:每一行的长度要和初始化表格的长度相等,即要把整行给占满,否则后面的都不会打印出来,所以要用到 setColspan() 方法来合并列,使用 setRowspan() 方法合并行。
示例3:合并行。
public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException {
PdfPTable table = new PdfPTable(2);//生成一个两列的表格
...
cell = new PdfPCell(new Phrase("five"));
cell.setColspan(1);//设置所占列数
cell.setRowspan(2);//合并行
cell.setFixedHeight(size*2);//设置高度
cell.setHorizontalAlignment(Element.ALIGN_CENTER);//设置水平居中
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);//设置垂直居中
table.addCell(cell);
cell = new PdfPCell(new Phrase("six"));
cell.setFixedHeight(size);
table.addCell(cell);
cell = new PdfPCell(new Phrase("seven"));
cell.setFixedHeight(size);
table.addCell(cell);
return table;
}
效果如下:
事实上,实现行合并还有一种方法,就是table中再套一个table。
public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException {
PdfPTable table = new PdfPTable(2);//生成一个两列的表格
...
cell = new PdfPCell(new Phrase("five"));
cell.setColspan(1);//设置所占列数
cell.setFixedHeight(size*2);//设置高度
cell.setHorizontalAlignment(Element.ALIGN_CENTER);//设置水平居中
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);//设置垂直居中
table.addCell(cell);
PdfPTable table2 = new PdfPTable(1);//新建一个table
cell = new PdfPCell(new Phrase("six"));
cell.setFixedHeight(size);
table2.addCell(cell);
cell = new PdfPCell(new Phrase("seven"));
cell.setFixedHeight(size);
table2.addCell(cell);
cell = new PdfPCell(table2);//将table放到cell中
table.addCell(cell);//将cell放到外层的table中去
return table;
}
示例4:在表格中加入单选框/复选框。
public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException {
PdfPTable table = new PdfPTable(2);//生成一个两列的表格
...
Phrase phrase1 = new Phrase();
Chunk chunk1 = new Chunk(" YES");
Chunk chunk2 = new Chunk(" NO");
phrase1.add(chunk1);
phrase1.add(chunk2);
cell = new PdfPCell(phrase1);
cell.setColspan(2);
table.addCell(cell);
//增加两个单选框
PdfFormField radiogroup=PdfFormField.createRadioButton(writer, true);
radiogroup.setFieldName("salesModel");
Rectangle rect1 = new Rectangle(110, 722, 120, 712);
Rectangle rect2 = new Rectangle(165, 722, 175, 712);
RadioCheckField radio1 = new RadioCheckField(writer, rect1, null, "self-support" ) ;
RadioCheckField radio2 = new RadioCheckField(writer, rect2, null, "cooprate") ;
radio2.setChecked(true);
PdfFormField radiofield1 = radio1.getRadioField();
PdfFormField radiofield2 = radio2.getRadioField();
radiogroup.addKid(radiofield1);
radiogroup.addKid(radiofield2);
writer.addAnnotation(radiogroup);
return table;
}
效果如图:
这里需要自己去调节单选框的位置,即 Rectangle rect1 = new Rectangle(...) 里面的参数。
示例5:两种表格叠加,附件样式如下:
1)maven 依赖:
<!-- PDF工具类 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<!-- PDF中文支持 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13.1</version>
</dependency>
2)appication.properties
# 自定义存储或读取路径
#注:自定义路径时,默认的四个文件夹下中的“META-INF下的resoures文件夹”仍然有效,其他三个文件夹失效
#注:搜索文件时,自定义的文件夹的优先级要高于默认的四个文件夹
web.upload-path=C:/PDF/
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/static,classpath:/resources/,file:{web.upload-path}
springboot.mvc.static-path-pattern=/**
3)实现
@Value("${web.upload-path}")
private String uploadPath;
public String generateOrgDocumentPdf() throws AppException, IOException, DocumentException {
String newPDFPath = uploadPath + "信息采集表.pdf";
createTableFile(newPDFPath );
return newPDFPath;
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.itextpdf.text.*;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.itextpdf.text.pdf.PdfWriter;
/**
* 生成PDF文档
*/
public void createTableFile(String newPDFPath) throws AppException, IOException, DocumentException {
//新建Document对象,并打开
Document document = new Document(PageSize.A4);
try {
//创建文件
File file = new File(newPDFPath);
PdfWriter writer = PdfWriter.getInstance(document,new FileOutputStream(file));
//文档属性
document.addTitle("Titl");
document.addAuthor("Author");
document.addSubject("Subject");
document.addKeywords("Keywords");
document.addCreator("Creator");
//页边空白
document.setMargins(60, 60, 80, 40);
document.open();
//添加内容
//1、标题
document.add(PdfFontUtils.getFont(1, "信息采集表"));
//创建一个空行
// document.add(Chunk.NEWLINE );
//2、表格
//2.1 设置表格列数:6
PdfPTable table = new PdfPTable(6);
//2.2 指定表格每一列宽度
table.setWidths(new float[] {0.15f,0.15f,0.15f,0.15f,0.15f,0.25f});
//2.3添加第一行内容
//2.3.1添加第1列内容
PdfPCell cell = new PdfPCell(PdfFontUtils.getFont(7, "字段1"));
//设置第一行第一列背景颜色
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//2.3.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//2.3.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段2"));
//设置背景颜色
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//2.3.4添加第4列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//2.3.5添加第5列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段3"));
//设置背景颜色
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//2.3.6添加第6列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//2.4添加第2行,跨所有列
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段4"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
//设置跨列数
cell.setColspan(6);
table.addCell(cell);
//2.5添加第三行内容
//2.5.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段5"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
//设置跨列数
cell.setColspan(3);
table.addCell(cell);
//2.5.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7,"字段6"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
//设置跨列数
cell.setColspan(2);
table.addCell(cell);
//2.5.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段7"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//2.6添加第四行内容
//2.6.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
//设置跨列数
cell.setColspan(3);
table.addCell(cell);
//2.6.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
//设置跨列数
cell.setColspan(2);
table.addCell(cell);
//2.6.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//2.7添加第五行内容
//2.7.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段8"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
//设置跨列数
cell.setColspan(2);
table.addCell(cell);
//2.7.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段9"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
//设置跨列数
cell.setColspan(3);
table.addCell(cell);
//2.7.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7,"字段10"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//2.8添加第六行内容
//2.8.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
//设置跨列数
cell.setColspan(2);
table.addCell(cell);
//2.8.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
//设置跨列数
cell.setColspan(3);
table.addCell(cell);
//2.8.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//2.9添加table
document.add(table);
//3、新建一个表-8列
table = new PdfPTable(8);
//3.1添加第1行,跨所有列
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段11"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
//设置跨列数
cell.setColspan(8);
table.addCell(cell);
//3.2添加第2行内容
//3.2.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段12"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
cell.setColspan(2);
table.addCell(cell);
//3.2.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段13"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
cell.setColspan(2);
table.addCell(cell);
//3.2.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段14"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
cell.setColspan(2);
table.addCell(cell);
//3.2.4添加第4列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段15"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
cell.setColspan(2);
table.addCell(cell);
//3.3添加第3行内容
//3.3.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
cell.setColspan(2);
table.addCell(cell);
//3.3.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
cell.setColspan(2);
table.addCell(cell);
//3.3.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
cell.setColspan(2);
table.addCell(cell);
//3.3.4添加第4列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
cell.setColspan(2);
table.addCell(cell);
//3.4添加第4行,跨所有列
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段16"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
//设置跨列数
cell.setColspan(8);
table.addCell(cell);
//循环加入行为记录表格-length:需要循环添加的数据的多少
for (int i = 1; i <= length; i++){
//取数字的中文表达
String num = this.getNumberChinese(Integer.toString(i));
//3.5添加第5行(字段17),跨所有列-------我这里的字段17格式类似于:(一)行为一
cell = new PdfPCell(PdfFontUtils.getFont(6, "(" + num + ")、行为" + num));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
//设置跨列数
cell.setColspan(8);
table.addCell(cell);
//3.6添加第6行
//3.6.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段18"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
cell.setColspan(2);
table.addCell(cell);
//3.6.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段19"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
cell.setColspan(2);
table.addCell(cell);
//3.6.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段20"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
cell.setColspan(2);
table.addCell(cell);
//3.6.4添加第4列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段21"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
cell.setColspan(2);
table.addCell(cell);
//3.7添加第7行
//3.7.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
cell.setColspan(2);
table.addCell(cell);
//3.7.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
cell.setColspan(2);
table.addCell(cell);
//3.7.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
cell.setColspan(2);
table.addCell(cell);
//3.7.4添加第4列内容
cell = new PdfPCell(PdfFontUtils.getFont(7,"内容"));
cell.setColspan(2);
table.addCell(cell);
//3.8添加第8行,跨所有列
cell = new PdfPCell(PdfFontUtils.getFont(6, "字段22"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
//设置跨列数
cell.setColspan(8);
table.addCell(cell);
//3.10添加第9行
//3.10.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段23"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.10.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.10.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段24"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.10.4添加第4列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.10.5添加第5列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段25"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.10.6添加第6列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.10.7添加第7列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段26"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.10.8添加第8列内容
cell = new PdfPCell(PdfFontUtils.getFont(7,"内容"));
table.addCell(cell);
//3.11添加第10行
//3.11.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段27"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.11.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.11.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段28"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.11.4添加第4列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.11.5添加第5列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段29"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.11.6添加第6列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.11.7添加第7列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段30"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.11.8添加第8列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.12添加第11行
//3.12.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段31"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.12.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.12.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段32"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.12.4添加第4列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.12.5添加第5列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段33"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.12.6添加第6列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.12.7添加第7列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段34"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.12.8添加第8列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.13添加第12行
//3.13.1添加第1列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段35"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.13.2添加第2列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.13.3添加第3列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段36"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.13.4添加第4列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.13.5添加第5列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段37"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.13.6添加第6列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
//3.13.7添加第7列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "字段38"));
cell.setBackgroundColor(new BaseColor(0xC0,0xC0,0xC0));
table.addCell(cell);
//3.13.8添加第8列内容
cell = new PdfPCell(PdfFontUtils.getFont(7, "内容"));
table.addCell(cell);
}
//3.14添加table
document.add(table);
} catch (Exception e) {
e.printStackTrace();
}
//4、关闭document
document.close();
}
/**
* 将数字123转为中文格式一二三
*/
private String getNumberChinese(String number) {
String result = "";
//存储数字与中文表示的键值对
Map<String,String> map = new HashMap<String,String>();
map.put("1","一");
map.put("2","二");
map.put("3","三");
map.put("4","四");
map.put("5","五");
map.put("6","六");
map.put("7","七");
map.put("8","八");
map.put("9","九");
int len = number.length();
if (len == 1) {
result = map.get(number);
} else if (len == 2) {
result = map.get(number.substring(0,1)) + "十" + map.get(number.substring(1,2));
}
return result;
}
import java.io.IOException;
import java.net.URL;
import org.springframework.core.io.ClassPathResource;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
public class PdfFontUtils {
/**
* 文档排版
*/
public static Paragraph getFont(int type, String text) throws IOException{
BaseFont songti = null;
BaseFont heiti = null;
BaseFont fangsong = null;
URL url = new ClassPathResource("META-INF/resources/static/font/STZHONGS.TTF").getURL();
String song = url.getPath();
url = new ClassPathResource("META-INF/resources/static/font/SIMHEI.TTF").getURL();
String hei = url.getPath();
url = new ClassPathResource("META-INF/resources/static/font/STFANGSO.TTF").getURL();
String fang = url.getPath();
try {
/**
* 设置字体
*
* windows路径字体
* FONT_TYPE=C:/Windows/fonts/simsun.ttc
* linux路径字体 宋体 (如果没有这个字体文件,就将windows的字体传上去)
* FONT_TYPE=/usr/share/fonts/win/simsun.ttc
*/
songti = BaseFont.createFont(song, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
heiti = BaseFont.createFont(hei, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
fangsong = BaseFont.createFont(fang, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Font font1 = new Font(songti);
Font font2 = new Font(heiti);
Font font3 = new Font(fangsong);
if(1 == type){//1-标题
font1.setSize(22f);
} else if(2 == type){//2-标题一
font2.setSize(16f);
} else if(3 == type){//3-标题二
font3.setSize(16f);
} else if(4 == type){//4-标题三
font3.setSize(16f);
} else if(5 == type){//5-正文
font3.setSize(10.5f);
} else if(6 == type){//6-左对齐
font3.setSize(10.5f);
} else {
font3.setSize(10.5f);//默认大小
}
//注: 字体必须和 文字一起new
Paragraph paragraph = null;
if(1 == type){
paragraph = new Paragraph(text, font1);
paragraph.setAlignment(Paragraph.ALIGN_CENTER);//居中
paragraph.setSpacingBefore(40f);//上间距
paragraph.setSpacingAfter(30f);//下间距
} else if(2 == type){//2-标题一
paragraph = new Paragraph(text, font2);
paragraph.setAlignment(Element.ALIGN_JUSTIFIED); //默认
paragraph.setFirstLineIndent(40);
paragraph.setSpacingBefore(20f);//上间距
paragraph.setSpacingAfter(30f);//下间距
} else if(3 == type){
paragraph = new Paragraph(text, font3);
paragraph.setFirstLineIndent(40);
paragraph.setSpacingBefore(20f);//上间距
paragraph.setSpacingAfter(1f);//下间距
} else if(4 == type){//4-标题三
paragraph = new Paragraph(text, font3);
paragraph.setAlignment(Element.ALIGN_JUSTIFIED);
paragraph.setFirstLineIndent(40);
paragraph.setSpacingBefore(2f);//上间距
paragraph.setSpacingAfter(2f);//下间距
paragraph.setLeading(40f);//设置行间距
} else if(5 == type){
paragraph = new Paragraph(text, font3);
paragraph.setAlignment(Element.ALIGN_JUSTIFIED);
paragraph.setFirstLineIndent(40);//首行缩进
paragraph.setSpacingBefore(1f);//上间距
paragraph.setSpacingAfter(1f);//下间距
} else if(6 == type){//左对齐
paragraph = new Paragraph(text, font3);
paragraph.setAlignment(Element.ALIGN_LEFT);
paragraph.setSpacingBefore(1f);//上间距
paragraph.setSpacingAfter(1f);//下间距
}else if(7 == type){
paragraph = new Paragraph(text, font3);
paragraph.setAlignment(Element.ALIGN_CENTER);
paragraph.setSpacingBefore(1f);//上间距
paragraph.setSpacingAfter(1f);//下间距
}
return paragraph;
}
}
示例6:在springboot中导出pdf文件。
@RequestMapping("printPdf")
public ModelAndView printPdf() throws Exception {
Product product1 = new Product("产品一","cp01",120);
Product product2 = new Product("产品一","cp01",120);
Product product3 = new Product("产品一","cp01",120);
List<Product> products = new ArrayList<>();
products.add(product1);
products.add(product2);
products.add(product3);
Map<String, Object> model = new HashMap<>();
model.put("sheet", products);
return new ModelAndView(new ViewPDF(), model);
}
public class ViewPDF extends AbstractPdfView {
@Override
protected void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer,
HttpServletRequest request, HttpServletResponse response) throws Exception {
String fileName = new Date().getTime() + "_quotation.pdf";
response.setCharacterEncoding("UTF-8");
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "filename=" + new String(fileName.getBytes(), "iso8859-1"));
List<Product> products = (List<Product>) model.get("sheet");
PdfUtil pdfUtil = new PdfUtil();
pdfUtil.createPDF(document, writer, products);
}
}
注意:
1、父类 AbstractPdfView
的 bulidPdfDocument 方法,其参数 document 的类型是 com.lowagie.text.Document
,意味着新版的 itextpdf-5.0.6.jar 不能使用,只能用老版本的(改名之前的)itext-2.1.7.jar。
2、如果不想要这种直接在浏览器中预览的效果,而是以附件形式直接下载文件,就修改 response.setHeader() 方法里的参数。
response.setHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes(), "iso8859-1"));
public class PdfUtil {
public void createPDF(Document document,PdfWriter writer, List<Product> products) throws IOException {
try {
document.addTitle("sheet of product");
document.addAuthor("scurry");
document.addSubject("product sheet.");
document.addKeywords("product.");
document.open();
PdfPTable table = createTable(writer,products);
document.add(table);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
} finally {
document.close();
}
}
public static PdfPTable createTable(PdfWriter writer,List<Product> products) throws IOException, DocumentException {
PdfPTable table = new PdfPTable(3);//生成一个三列的表格
PdfPCell cell;
int size = 20;
Font font = new Font(BaseFont.createFont("C://Windows//Fonts//simfang.ttf", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
for(int i = 0;i<products.size();i++) {
cell = new PdfPCell(new Phrase(products.get(i).getProductCode(),font));//产品编号
cell.setFixedHeight(size);
table.addCell(cell);
cell = new PdfPCell(new Phrase(products.get(i).getProductName(),font));//产品名称
cell.setFixedHeight(size);
table.addCell(cell);
cell = new PdfPCell(new Phrase(products.get(i).getPrice()+"",font));//产品价格
cell.setFixedHeight(size);
table.addCell(cell);
}
return table;
}
}
如果项目要打包部署到linux服务器上,前两种的中文解决办法都不好使了,只能下载中文字体资源文件。然而这其中又有一个坑,打包后文件路径读取不到,需要以加载资源文件的形式读取文件。
BaseFont baseFont = BaseFont.createFont(new ClassPathResource("/simsun.ttf").getPath(), BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
效果如下图:
示例7:给浏览器输出pdf。
如果想给浏览器输出某些东西,可以流的方式,也可以字节的方式。
ByteArrayOutputStream out = new ByteArrayOutputStream();
PdfWriter.getInstance(document, out);
document.open();
document.add(table);
document.close();
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition","inline;filename=citiesreport.pdf");
ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(out.toByteArray());
示例8:给pdf文件添加水印(文字或图片)。
/**
* 斜角排列、全屏多个重复的花式文字水印
*
* @param input 需要加水印的PDF读取输入流
* @param output 输出生成PDF的输出流
* @param waterMarkString 水印字符
* @param xAmout x轴重复数量
* @param yAmout y轴重复数量
* @param opacity 水印透明度
* @param rotation 水印文字旋转角度,一般为45度角
* @param waterMarkFontSize 水印字体大小
* @param color 水印字体颜色
*/
public static void stringWaterMark(InputStream input, OutputStream output, String waterMarkString, int xAmout, int yAmout, float opacity, float rotation, int waterMarkFontSize, BaseColor color) {
try {
PdfReader reader = new PdfReader(input);
PdfStamper stamper = new PdfStamper(reader, output);
// 添加中文字体
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
int total = reader.getNumberOfPages() + 1;
PdfContentByte over;
// 给每一页加水印
for (int i = 1; i < total; i++) {
Rectangle pageRect = stamper.getReader().getPageSizeWithRotation(i);
// 计算水印每个单位步长X,Y
float x = pageRect.getWidth() / xAmout;
float y = pageRect.getHeight() / yAmout;
over = stamper.getOverContent(i);
PdfGState gs = new PdfGState();
// 设置透明度为
gs.setFillOpacity(opacity);
over.setGState(gs);
over.saveState();
over.beginText();
over.setColorFill(color);
over.setFontAndSize(baseFont, waterMarkFontSize);
for (int n = 0; n < xAmout + 1; n++) {
for (int m = 0; m < yAmout + 1; m++) {
over.showTextAligned(Element.ALIGN_CENTER, waterMarkString, x * n, y * m, rotation);
}
}
over.endText();
}
stamper.close();
} catch (Exception e) {
new Exception("NetAnd PDF add Text Watermark error"+e.getMessage());
}
}
/**
* 图片水印,整张页面平铺
* @param input 需要加水印的PDF读取输入流
* @param output 输出生成PDF的输出流
* @param imageFile 水印图片路径
*/
public static void imageWaterMark(InputStream input, OutputStream output, String imageFile, float opacity) {
try {
PdfReader reader = new PdfReader(input);
PdfStamper stamper = new PdfStamper(reader, output);
Rectangle pageRect = stamper.getReader().getPageSize(1);
float w = pageRect.getWidth();
float h = pageRect.getHeight();
int total = reader.getNumberOfPages() + 1;
Image image = Image.getInstance(imageFile);
image.setAbsolutePosition(0, 0);// 坐标
image.scaleAbsolute(w, h);
PdfGState gs = new PdfGState();
gs.setFillOpacity(opacity);// 设置透明度
PdfContentByte over;
// 给每一页加水印
float x, y;
Rectangle pagesize;
for (int i = 1; i < total; i++) {
pagesize = reader.getPageSizeWithRotation(i);
x = (pagesize.getLeft() + pagesize.getRight()) / 2;
y = (pagesize.getTop() + pagesize.getBottom()) / 2;
over = stamper.getOverContent(i);
over.setGState(gs);
over.saveState();//没这个的话,图片透明度不起作用,必须在beginText之前,否则透明度不起作用,会被图片覆盖了内容而看不到文字了。
over.beginText();
// 添加水印图片
over.addImage(image);
}
stamper.close();
} catch (Exception e) {
new Exception("NetAnd PDF add image Watermark error" + e.getMessage());
}
}
效果如下图:
示例9:使用模板导出pdf。
使用模板的形式导出PDF,用 iText 对pdf模板进行动态数据的填充。
1、制作pdf模板
1.1、先在Word中编辑好对应的模板,如图,选择另存为,选择格式为pdf导出。
1.2、导出pdf格式后,使用PDF编辑器对其增加域面板,以及添加对应的文本域信息,我这边采用的PDF编辑器是 Gaaiho Doc(Gaaiho Doc)第一个月免费。选择添加文本域对表格进行添加,需要注意的是如果有单选框或多选框,另外需要设置默认导出值,这边与后台传送过来的数据相对应。根据导出值与后台对应的数据进行选中。
2、后端实现
2.1、在 pop.xml 中导入相关依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
2.2、Service 层
@Override
public R exportPdf(HttpServletResponse response, Integer id){
boolean flag=true;
String path = "d:/";
//获取数据
Medicalrecords medicalrecords = medicalrecordsDao.findById(id);
Doctor doctor = doctorDao.findById(medicalrecords.getDc_id());
// 指定解析器
System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
"com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
String filename="病历.pdf";
response.setContentType("application/pdf");
try {
// int i=1/0;
response.setHeader("Content-Disposition", "attachment;fileName="
+ URLEncoder.encode(filename, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return R.ok().put("flag",false);
}
OutputStream os = null;
PdfStamper ps = null;
PdfReader reader = null;
try {
os = response.getOutputStream();
// 2 读入pdf表单(给予导出表单pdf的文件miing)
reader = new PdfReader(path+ "/"+filename);
// 3 根据表单生成一个新的pdf
ps = new PdfStamper(reader, os);
// 4 获取pdf表单
AcroFields form = ps.getAcroFields();
// 5给表单添加中文字体 这里采用系统字体。不设置的话,中文可能无法显示
// BaseFont bf = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1",
// BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
//这边设置pdf字体,可以更改字体的格式
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
form.addSubstitutionFont(bf);
// 6查询数据(将数据赋给Map集合,key的值对应Pdf模板的值,value对应数据库中取出的)
Map<String,Object> data = new HashMap<>();
data.put("mr_uid",medicalrecords.getMr_uid());
data.put("mr_name",medicalrecords.getMr_name());
data.put("mr_gender",medicalrecords.getMr_gender());
data.put("mr_birthday",medicalrecords.getMr_birthday());
data.put("mr_address",medicalrecords.getMr_address());
data.put("mr_telephone",medicalrecords.getMr_telephone());
data.put("mr_illness",medicalrecords.getMr_illness());
data.put("mr_diagnosis",medicalrecords.getMr_diagnosis());
data.put("mr_drugs",medicalrecords.getMr_drugs());
data.put("mr_doctor",doctor.getDc_name());
data.put("mr_charge",medicalrecords.getMr_charge());
data.put("mr_date",medicalrecords.getMr_date());
// 7遍历data 给pdf表单表格赋值
for (String key : data.keySet()) {
form.setField(key, MapUtils.getString(data, key));
}
ps.setFormFlattening(true);
flag=true;
} catch (Exception e) {
flag=false;
e.printStackTrace();
return R.ok(e.getMessage()).put("flag",flag);
} finally {
try {
ps.close();
reader.close();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
2.3、Controller 层
@GetMapping("/exportPdf/{mr_id}")
public R exportPdf(@PathVariable("mr_id") String id, HttpServletResponse response){
return medicalrecordsService.exportPdf(response,Integer.parseInt(id));
}
解决中文字体的问题
1、使用windows系统自带的字体。
public static PdfPTable createTable(PdfWriter writer) throws DocumentException, IOException {
Font font = new Font(BaseFont.createFont("C:/Windows/Fonts/SIMYOU.TTF",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
PdfPTable table = new PdfPTable(2);//生成一个两列的表格
int size = 20;
PdfPCell cell = new PdfPCell(new Phrase("显示中文",font));
cell.setFixedHeight(size);
cell.setColspan(2);
table.addCell(cell);
return table;
}
2、使用 itext-asian.jar 中的中文字体。
Font font = new Font(BaseFont.createFont("STSongStd-Light","UniGB-UCS2-H",BaseFont.NOT_EMBEDDED));
在这里可能会报 Font 'STSongStd-Light' with 'UniGB-UCS2-H' is not recognized. 的错,把 itexitextpdf 包的版本从5.0.6改成5.4.3就解决了。
3、使用自己下载的资源字体。这种方法效果最好,能够应对各种系统、各种状况。
Font font = new Font(BaseFont.createFont("/simsun.ttf",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
使用 iText 导出pdf表格
iText 是一种生成PDF报表的Java组件,其maven依赖如下: