最近开发,有做到需要导出 PDF 的功能,这里做一个记录,方便自己查找,同时也希望能给你们带来帮助。
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CreatePDF {
public static void main(String[] args) {
try {
/**
* 这里是我准备的一些数据
*/
List<UserInfo> userInfo = new ArrayList<UserInfo>();
userInfo.add(new UserInfo("张三", "11"));
userInfo.add(new UserInfo("李三", "11"));
userInfo.add(new UserInfo("王三", "treterutyjighjhglkjh第三个第三方给定返回发过火疯狗后方个甲方个甲方根据根据服管家服管家服管家服管家"));
userInfo.add(new UserInfo("器三", "11"));
userInfo.add(new UserInfo("凄凄切切三", "11"));
userInfo.add(new UserInfo("似睡非睡富商大贾第三个三", "11"));
userInfo.add(new UserInfo("噶东风浩荡分级分工开个会客户进口红酒三", "11"));
userInfo.add(new UserInfo("广东佛山吉宏股份加工费第一三", "11"));
userInfo.add(new UserInfo("发三", "11"));
userInfo.add(new UserInfo("发三1254235", "11"));
/**
* 我这里使用的是 itextpdf ,前面的这些都是固定写法,你也可以根据自己的需要对字体、列数之类的进行修改.
* 这些设置里面我碰到了一个问题,就是我如果设置了字体的颜色后,有字的地方,它的背景颜色就会是灰色的
*/
Document document = new Document();
document.setPageSize(PageSize.A4);
String fileName = System.currentTimeMillis() + ".pdf";
String pdfPath = "D:\\Develop\\pdf\\";
PdfWriter instance = PdfWriter.getInstance(document, new FileOutputStream(pdfPath + fileName));
document.open();
String fontp = "C:\\Users\\Administrator\\Documents\\WeChat Files\\wxid_2567885681412\\FileStorage\\File\\2021-11\\msyh.ttc,0";
BaseFont bfChinese = BaseFont.createFont(fontp, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
// 标题字体
Font titleChinese = new Font(bfChinese, 16, Font.BOLD);
// 内容小标题字体
Font contenttitleChinese = new Font(bfChinese, 11, Font.NORMAL);
//设置标题
Paragraph par = new Paragraph("标题名字", titleChinese);
par.setAlignment(Element.ALIGN_CENTER);
//文档中加入标题
document.add(par);
//文档中加入空行
Paragraph blankRow51 = new Paragraph(5f, " ", contenttitleChinese);
document.add(blankRow51);
//设置小标题
Paragraph bigBlankRow = new Paragraph( "副标题名字", contenttitleChinese);
bigBlankRow.setAlignment(Element.ALIGN_CENTER);
document.add(bigBlankRow);
//文档中加入空行
blankRow51 = new Paragraph(5f, " ", contenttitleChinese);
document.add(blankRow51);
//设置表格的列数
//新建一个表格,它的列数是8列
PdfPTable table = new PdfPTable(8);
//设置表格占PDF文档100%宽度
table.setWidthPercentage(100);
//设置每列表格宽度
float[] columnWidths = {0.9f, 0.9f,0.9f,0.9f, 0.9f, 0.9f,0.9f,0.9f};
table.setWidths(columnWidths);
//设置表格标题样式
BaseColor lightGrey01 = new BaseColor(0xCC,0xCC,0xCC);
//判断是否能被4%
int i1 = userInfo.size() % 4;
/**
* 你看我这里为什么要对 数据进行 %4 的操作?然后为什么 %4 之后还把差的给补充进去了呢?
*
*
* 那是因为我这里待填充进表格每个数据都占了2列,这样填充满一行的话需要4个数据。如果它的数
* 据不能填充满一行的话,就会导致整个表格变形,所以这里对它进行了 %4 的操作,是保证它每次
* 都能填充满,没有数据的部分以空行填充
*/
for (int j = 1; j <= 4 - i1; j++) {
userInfo.add(new UserInfo("", ""));
}
for (int i = 0; i < userInfo.size(); i++) {
PdfPCell cell = toPdfPCell(userInfo.get(i).getUserName(),Element.ALIGN_CENTER);
table.addCell(cell);
table.addCell(toPdfPCell(userInfo.get(i).getPassword(), Element.ALIGN_CENTER));
}
//把表格加入到文档中
document.add(table);
//关闭文档
document.close();
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 这是给抽出来的第一个方法,对不需要合并的数据进行的解析,俗称的就是 1-1 类型的数据
*/
public static void toPdfPCell(JSONArray jsonArray, int align,PdfPTable table) throws DocumentException, IOException {
//判断是否能被4%
int length = jsonArray.size() % 4;
Map<String, String> objMap = new HashMap<>();
if (length > 0) {
objMap.put("name", "");
objMap.put("value", "");
}
for (int j = 1; j <= 4 - length; j++) {
jsonArray.add(JSON.parse(objMap.toString()));
}
for (Object object : jsonArray) {
JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(object));
String fontp = "C:\\Users\\Administrator\\Documents\\WeChat Files\\wxid_2567885681412\\FileStorage\\File\\2021-11\\msyh.ttc,0";
BaseFont bfChinese = BaseFont.createFont(fontp, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
// 内容字体
Font fontChinese = new Font(bfChinese, 11, Font.NORMAL);
PdfPCell cell=new PdfPCell(new Paragraph(jsonObject.getString("name"),fontChinese));
// 设置内容水平居中显示
cell.setHorizontalAlignment(align);
// 设置垂直居中
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
table.addCell(cell);
cell=new PdfPCell(new Paragraph(jsonObject.getString("value"),fontChinese));
// 设置内容水平居中显示
cell.setHorizontalAlignment(align);
// 设置垂直居中
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
table.addCell(cell);
}
}
/**
* 这是给抽出来的第二个方法,针对合并而言的,我这里的是 1-7 的合并方式。
* 同时你需要注意,拿我这块做得合并处理为例:我这里待填充的数据类型是 key-value 的键值的数据,但是
* 我这个最左边又需要有一个单独的小标题,所以我这里的一个思路:表格的列分为:1-7 ,然后 7部分的
* 数据它是再分为 key一行、value一行,所以你也可以看到我这里只是对 1的部分进行了一个跨行的合并
* ,对 7的部门进行了一个跨列的合并。
*
* 当有数据的时候,你进行的合并效果就行会显出来的,你也不需要担心他会挤爆你的表格,因为它是自适应
* 的。
*/
public static void toPdfMergePCell(JSONArray objectArray, int align,PdfPTable table,String type) throws DocumentException, IOException {
// 内容字体
String fontp = "C:\\Users\\Administrator\\Documents\\WeChat Files\\wxid_2567885681412\\FileStorage\\File\\2021-11\\msyh.ttc,0";
BaseFont bfChinese = BaseFont.createFont(fontp, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font fontChinese = new Font(bfChinese, 11, Font.NORMAL);
int mergeLine = objectArray.size() * 2;
PdfPCell cell=new PdfPCell(new Paragraph(type,fontChinese));
// 设置内容水平居中显示
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
// 设置垂直居中
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.disableBorderSide(1);
cell.setRowspan(mergeLine);
table.addCell(cell);
int count = 0;
for (Object obj : objectArray) {
JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(obj));
PdfPCell cellRight=new PdfPCell(new Paragraph(jsonObject.getString("name"),fontChinese));
// 设置内容水平居中显示
cellRight.setHorizontalAlignment(Element.ALIGN_LEFT);
if (count != 0) {
cellRight.disableBorderSide(1);
}
cellRight.disableBorderSide(2);
cellRight.disableBorderSide(4);
cellRight.disableBorderSide(8);
cellRight.setColspan(7);
table.addCell(cellRight);
cellRight = new PdfPCell(new Paragraph(StringUtils.isEmpty(jsonObject.getString("value")) ? "" : jsonObject.getString("value"), fontChinese));
// 设置内容水平居中显示
cellRight.setHorizontalAlignment(Element.ALIGN_LEFT);
cellRight.disableBorderSide(1);
if (count != (objectArray.size() - 1)) {
cellRight.disableBorderSide(2);
}
cellRight.disableBorderSide(4);
cellRight.disableBorderSide(8);
cellRight.setColspan(7);
//设置距离左边的距离
cellRight.setPaddingLeft(10);
table.addCell(cellRight);
count++;
}
}
}
/**
* 代码到这里其实就完了,这里再加一些其他的设置表格或者是文档的参数吧
*/
//设置表格标题样式
BaseColor lightGrey01 = new BaseColor(0xCC,0xCC,0xCC);
PdfPTable table = new PdfPTable(8);
table.setTotalWidth(new float[] { 50, 50, 50, 50, 50, 50, 50, 130 }); // 设置列宽
table.setLockedWidth(true); // 锁定列宽
PdfPCell cell; //生成单元格
cell.disableBorderSide(1); // 隐藏单元格周边的上边框
cell.disableBorderSide(2);// 隐藏单元格周边的下边框
cell.disableBorderSide(4); // 隐藏单元格周边的左边框
cell.disableBorderSide(8);// 隐藏单元格周边的右框
cell.setBorderWidthLeft(3);//设置边框的宽度
cell.setBorderWidthTop(3);//设置边框的宽度
cell.setBackgroundColor(lightGrey01); //加粗
cell = new PdfPCell(new Phrase("报批工程建筑面积明细表", boldFont));//向单元格中插入数据
cell.setColspan(8);//跨列合并单元格
cell.setRowspan(2);//跨行合并单元格
cell.setMinimumHeight(40); // 设置单元格高度
cell.setUseAscender(true); // 设置可以居中
cell.setHorizontalAlignment(Cell.ALIGN_CENTER); // 设置水平居中
cell.setVerticalAlignment(Cell.ALIGN_MIDDLE); // 设置垂直居中
table.addCell(cell);