当前位置: 首页 > news >正文

java生成PDF合并单元格

需求

最近需要开发一个功能,涉及到Excel导出与pdf导出,其实pdf导出不适合表头太多的表格,不美观,但是需求如此,那就开发吧。

技术选型

参考了网上的资料,选用itextpdf做为技术支持,开始itextpdf-core对应的依赖,但是导出中文会有格式问题,并且乱码,需要引入本地的字体。

        <dependency><groupId>com.itextpdf</groupId><artifactId>itext7-core</artifactId><version>7.1.16</version><type>pom</type></dependency>
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.UnitValue;
import com.travelsky.commons.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;import javax.servlet.http.HttpServletResponse;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;/*** @Author maruko* @Date 2023/12/15 10:05* @Description: 导出pdf添加页数* @Version 1.0*/
@Slf4j
public class PdfPageUtil {/*** 下载导出为PDF* @param fileName 文件名* @param headers 表头 注意中英文* @param data 数据集合  实体类可采用entityToList转换* @param response* @throws Exception*/public static void downloadPdf(String fileName, List<String> headers, List<List<String>> data, HttpServletResponse response) throws Exception {// 设置编码格式response.setContentType("application/pdf;charset=UTF-8");response.setCharacterEncoding("utf-8");fileName = URLEncoder.encode(fileName, "UTF-8");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".pdf");PdfWriter writer = new PdfWriter(response.getOutputStream());PdfDocument pdfDoc = new PdfDocument(writer);Document document = new Document(pdfDoc);URL resource = PdfPageUtil.class.getClassLoader().getResource("simhei.ttf");String path = resource.getPath();PdfFont font = PdfFontFactory.createFont(path, PdfEncodings.IDENTITY_H, true);//根据表头数量设置列宽比例和宽度为页面宽度float[] columnWidths = new float[headers.size()];for (int i = 0; i < headers.size(); i++) {columnWidths[i] = 1;}// 创建表格并添加数据和表头Table table = new Table(UnitValue.createPercentArray(columnWidths)).useAllAvailableWidth();// 添加表头单元格for (String header : headers) {if (StringUtil.isEmpty(header)) {table.addHeaderCell("");} else {table.addHeaderCell(header).setFont(font);}}// 添加数据单元格到表格中for (List<String> rowData : data) {for (String cell : rowData) {if (StringUtil.isEmpty(cell)) {table.addCell("");} else {table.addCell(cell).setFont(font);}}}document.add(table);document.close();}public static List<List<String>> entityToList(List<?> list, String[] fields, Class<?> classType) {List<List<String>> dataList = new ArrayList<>();String temp = JSONObject.toJSONString(list);List<?> objects = JSONArray.parseArray(temp, classType);for (Object object : objects) {Map<String, String> map = JSONObject.parseObject(JSONObject.toJSONString(object),new TypeReference<Map<String, String>>() {});List<String> tempList = new ArrayList<>();for (String field : fields) {tempList.add(map.get(field));}dataList.add(tempList);}return dataList;}
}

问题

上述实现,对于中文有一定问题,还无法合并单元格,所以换了其它依赖

        <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.10</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency>

实现方式


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.travelsky.domain.pdf.PdfHeader;
import lombok.extern.slf4j.Slf4j;import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;/*** @Author maruko* @Date 2023/12/15 10:05* @Description: 导出pdf添加页数* @Version 1.0*/
@Slf4j
public class PdfPageUtil {public static void main(String[] args) throws Exception {}/*** 下载导出为PDF** @param fileName   文件名* @param headerSize 表头数量* @param headers    表头 注意中英文* @param data       数据集合  实体类可采用entityToList转换* @param response   HttpServletResponse* @throws Exception ex*/public static void downloadPdf(String fileName, int headerSize, List<List<PdfHeader>> headers, List<List<String>> data, HttpServletResponse response) throws Exception {// 设置编码格式response.setContentType("application/pdf;charset=UTF-8");response.setCharacterEncoding("utf-8");fileName = URLEncoder.encode(fileName, "UTF-8");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".pdf");Document document = new Document();PdfWriter pdfWriter = PdfWriter.getInstance(document, response.getOutputStream());pdfWriter.setViewerPreferences(PdfWriter.PageModeUseThumbs);//设置A4document.setPageSize(PageSize.A4);document.open();// 创建表格并添加数据和表头 采用百分比模式 不用固定长度PdfPTable table = new PdfPTable(headerSize);table.setWidthPercentage(100.0F);// 添加表头单元格for (List<PdfHeader> header : headers) {for (PdfHeader pdfHeader : header) {fillHeaderCell(pdfHeader, getPdfChineseFont(), table);}}// 添加数据单元格到表格中for (List<String> rowData : data) {for (String cell : rowData) {fillCell(cell, getPdfChineseFont(), table);}}document.add(table);document.close();}/*** 填充单元格** @param header PdfRowHeader* @param font   Font* @param table  PdfPTable*/private static void fillHeaderCell(PdfHeader header, Font font, PdfPTable table) {PdfPCell headerCell = new PdfPCell();//不为0才有合并列if (header.getRowSpan() > 0) {headerCell.setRowspan(header.getRowSpan());}if (header.getColSpan() > 0) {headerCell.setColspan(header.getColSpan());}headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE);headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);headerCell.setFixedHeight(30);Paragraph paragraph = new Paragraph(header.getContent(), font);headerCell.setPhrase(paragraph);table.addCell(headerCell);}/*** 填充单元格** @param content String* @param font    Font* @param table   PdfPTable*/private static void fillCell(String content, Font font, PdfPTable table) {PdfPCell headerCell = new PdfPCell(new Paragraph(content, font));headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE);headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);headerCell.setFixedHeight(30);table.addCell(headerCell);}/*** 实体类转换成List** @param list       数据集合* @param fields     字段* @param classType  实体类* @return List<List < String>>*/public static List<List<String>> entityToList(List<?> list, String[] fields, Class<?> classType) {List<List<String>> dataList = new ArrayList<>();String temp = JSONObject.toJSONString(list);List<?> objects = JSONArray.parseArray(temp, classType);for (Object object : objects) {Map<String, String> map = JSONObject.parseObject(JSONObject.toJSONString(object),new TypeReference<Map<String, String>>() {});List<String> tempList = new ArrayList<>();for (String field : fields) {tempList.add(map.get(field));}dataList.add(tempList);}return dataList;}/*** 获取中文字体** @return Font* @throws Exception ex*/private static Font getPdfChineseFont() throws Exception {BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);return new Font(bfChinese, 12, Font.NORMAL);}
}

相关文章:

  • 电路图识图基础知识-电机顺序启动控制电路解析(二十二)
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | EventKey Codes(键盘码)
  • 滑动窗口最大值和最小值
  • 【靶场】xxe漏洞2
  • 【AI论文精读7】GraphRAG
  • 下载WinLibs时UCRT Runtime和MSVCRT Runtime(针对旧版本Windows)的区别
  • 基于“SpringBoot+uniapp的考研书库微信小程序设计与实现7000字论文
  • Monorepo + PNPM 搭建高效多项目管理
  • 云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
  • 深入浅出掌握 Axios(持续更新)
  • 深入解析 Nacos MCP Router:云原生时代的 MCP 服务调度中枢
  • 云原生核心技术 (4/12): Docker 进阶:镜像优化实战与 Docker Compose 揭秘
  • uniapp+vue2+h5图片下载保存,微信浏览器、非微信浏览器
  • spark数据处理练习题番外篇【上】
  • Spring Boot集成Mina的Socket资源管理:从稳定通信到高性能优化
  • Windows上SSH连接Ubuntu失败
  • XWPFTemplate生成word
  • 置信水平、置信区间
  • 一体系数据平台的进化:基于阿里云 EMR Serverless Spark的持续演进
  • ESP32读取DHT11温湿度数据
  • 做网站视频赚钱吗/最吸引人的引流话术
  • 东莞网站建设平台/怎么查百度搜索排名
  • 网站国外空间/bt蚂蚁磁力搜索天堂
  • 做设计赚钱的网站/企业建站 平台
  • 长沙网站推广智投未来/网站seo关键词
  • 做编程题的网站/推广网站文案