SpringBoot与文档excel,pdf集成案例分享

news2024/11/26 4:26:57

一、文档类型介绍

1、Excel文档

Excel一款电子表格软件。直观的界面、出色的计算功能和图表工具,在系统开发中,经常用来把数据转存到Excel文件,或者Excel数据导入系统中,这就涉及数据转换问题。

2、PDF文档

PDF是可移植文档格式,是一种电子文件格式,具有许多其他电子文档格式无法相比的优点。PDF文件格式可以将文字、字型、格式、颜色及独立于设备和分辨率的图形图像等封装在一个文件中。该格式文件还可以包含超文本链接、声音和动态影像等电子信息,支持特长文件,集成度和安全可靠性都较高。

二、Excel文件管理

1、POI依赖

Apache POI是Apache软件基金会的开源类库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。

github: https://github.com/apache/poi

<!-- Excel 依赖 -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.9</version>
</dependency>
<!-- 2007及更高版本 -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.9</version>
</dependency>

2、文件读取

public static List<List<Object>> readExcel(String path) throws Exception {
    File file = new File(path) ;
    List<List<Object>> list = new LinkedList<>();
    XSSFWorkbook xwb = new XSSFWorkbook(new FileInputStream(file));
    // 读取 Sheet1 表格内容
    XSSFSheet sheet = xwb.getSheetAt(0);
    // 读取行数:不读取Excel表头
    for (int i = (sheet.getFirstRowNum()+1); i <= (sheet.getPhysicalNumberOfRows()-1); i++) {
        XSSFRow row = sheet.getRow(i);
        if (row == null) { continue; }
        List<Object> linked = new LinkedList<>();
        for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
            XSSFCell cell = row.getCell(j);
            if (cell == null) { continue; }
            Object value ;
            // 这里需根据实际业务情况处理
            switch (cell.getCellType()) {
                case XSSFCell.CELL_TYPE_NUMERIC:
                    //处理数值带{.0}问题
                    value = Double.valueOf(String.valueOf(cell)).longValue() ;
                    break;
                default:
                    value = cell.toString();
            }
            linked.add(value);
        }
        if (linked.size()!= 0) {
            list.add(linked);
        }
    }
    return list;
}

3、文件创建

public static void createExcel(String excelName, String[] headList,List<List<Object>> dataList)
        throws Exception {
    // 创建 Excel 工作簿
    XSSFWorkbook workbook = new XSSFWorkbook();
    XSSFSheet sheet = workbook.createSheet();
    // 创建表头
    XSSFRow row = sheet.createRow(0);
    for (int i = 0; i < headList.length; i++) {
        XSSFCell cell = row.createCell(i);
        cell.setCellType(XSSFCell.CELL_TYPE_STRING);
        cell.setCellValue(headList[i]);
    }
    //添加数据
    for (int line = 0; line < dataList.size(); line++) {
        XSSFRow rowData = sheet.createRow(line+1);
        List<Object> data = dataList.get(line);
        for (int j = 0; j < headList.length; j++) {
            XSSFCell cell = rowData.createCell(j);
            cell.setCellType(XSSFCell.CELL_TYPE_STRING);
            cell.setCellValue((data.get(j)).toString());
        }
    }
    FileOutputStream fos = new FileOutputStream(excelName);
    workbook.write(fos);
    fos.flush();
    fos.close();
}

4、文件导出

public static void exportExcel(String[] headList, List<List<Object>> dataList,
                               OutputStream outputStream) throws Exception {
    // 创建 Excel 工作簿
    XSSFWorkbook workbook = new XSSFWorkbook();
    XSSFSheet sheet = workbook.createSheet();
    // 创建表头
    XSSFRow row = sheet.createRow(0);
    for (int i = 0; i < headList.length; i++) {
        XSSFCell cell = row.createCell(i);
        cell.setCellType(XSSFCell.CELL_TYPE_STRING);
        cell.setCellValue(headList[i]);
    }
    //添加数据
    for (int line = 0; line < dataList.size(); line++) {
        XSSFRow rowData = sheet.createRow(line+1);
        List<Object> data = dataList.get(line);
        for (int j = 0; j < headList.length; j++) {
            XSSFCell cell = rowData.createCell(j);
            cell.setCellType(XSSFCell.CELL_TYPE_STRING);
            cell.setCellValue((data.get(j)).toString());
        }
    }
    workbook.write(outputStream);
    outputStream.flush();
    outputStream.close();
}

5、文件导出接口

@RestController
public class ExcelDownLoadWeb {
    @RequestMapping("/file/outExcel")
    public void outExcel (HttpServletResponse response) throws Exception {
        String exportName = "2023-05-BSDATA" ;
        response.setContentType("application/vnd.ms-excel");
        response.addHeader("Content-Disposition", "attachment;filename="+
                             URLEncoder.encode(exportName, "UTF-8") + ".xlsx");
        List<List<Object>> dataList = ExcelUtil.readExcel("F:\\file-type\\user-excel.xlsx") ;
        String[] headList = new String[]{"测站", "时间", "降雨量"} ;
        ExcelUtil.exportExcel(headList,dataList,response.getOutputStream()) ;
    }
}

三、PDF文件管理

1、IText依赖

iText是一种生成PDF报表的Java组件。通过在服务器端使用页面或API封装生成PDF报表,客户端可以通过超链接直接显示或下载到本地,在系统开发中通常用来生成比较正式的报告或者合同类的电子文档。

github: https://github.com/itext/itextpdf

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.11</version>
</dependency>
<dependency>
    <groupId>com.itextpdf.tool</groupId>
    <artifactId>xmlworker</artifactId>
    <version>5.5.11</version>
</dependency>

2、API二次封装

首先对于Itext提供的API做一下表格、段落、图片等基础样式的二次封装,可以更好的适配业务。

public class PdfFontUtil {
    private PdfFontUtil(){}

    /**
     * 段落样式获取
     */
    public static Paragraph getParagraph (String content, Font font,Integer alignment){
        Paragraph paragraph = new Paragraph(content,font) ;
        if (alignment != null && alignment >= 0){
            paragraph.setAlignment(alignment);
        }
        return paragraph ;
    }
    /**
     * 图片样式
     */
    public static Image getImage (String imgPath,float width,float height) throws Exception {
        Image image = Image.getInstance(imgPath);
        image.setAlignment(Image.MIDDLE);
        if (width > 0 && height > 0){
            image.scaleAbsolute(width, height);
        }
        return image ;
    }
    /**
     * 表格生成
     */
    public static PdfPTable getPdfPTable01 (int numColumns,float totalWidth) throws Exception {
        // 表格处理
        PdfPTable table = new PdfPTable(numColumns);
        // 设置表格宽度比例为%100
        table.setWidthPercentage(100);
        // 设置宽度:宽度平均
        table.setTotalWidth(totalWidth);
        // 锁住宽度
        table.setLockedWidth(true);
        // 设置表格上面空白宽度
        table.setSpacingBefore(10f);
        // 设置表格下面空白宽度
        table.setSpacingAfter(10f);
        // 设置表格默认为无边框
        table.getDefaultCell().setBorder(0);
        table.setPaddingTop(50);
        table.setSplitLate(false);
        return table ;
    }
    /**
     * 表格内容
     */
    public static PdfPCell getPdfPCell (Phrase phrase){
        return new PdfPCell (phrase) ;
    }
    /**
     * 表格内容带样式
     */
    public static void addTableCell (PdfPTable dataTable,Font font,List<String> cellList){
        for (String content:cellList) {
            dataTable.addCell(getParagraph(content,font,-1));
        }
    }
}

3、生成PDF文件

这里基于上面的工具类,画一个PDF页面作为参考。

public class PdfPagetTest {
    // 基础配置
    private static String PDF_SITE = "E:\\temp\\PDF页面2023-04-15.pdf" ;
    private static String FONT = "C:/Windows/Fonts/simhei.ttf";
    private static String PAGE_TITLE = "PDF" ;
    // 基础样式
    private static Font TITLE_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H,20, Font.BOLD);
    private static Font NODE_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H,15, Font.BOLD);
    private static Font BLOCK_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H,13, Font.BOLD, BaseColor.BLACK);
    private static Font INFO_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H,12, Font.NORMAL,BaseColor.BLACK);
    private static Font CONTENT_FONT = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

    private static void createPdfPage () throws Exception {
        // 创建文档
        Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(PDF_SITE));
        document.open();
        // 报告标题
        document.add(PdfFontUtil.getParagraph(PAGE_TITLE,TITLE_FONT,1)) ;
        document.add(PdfFontUtil.getParagraph("\n商户名称:XXX科技有限公司",INFO_FONT,-1)) ;
        document.add(PdfFontUtil.getParagraph("\n生成时间:2020-01-15\n\n",INFO_FONT,-1)) ;
        // 报告内容
        // 段落标题 + 报表图
        document.add(PdfFontUtil.getParagraph("城市数据分布统计",NODE_FONT,-1)) ;
        document.add(PdfFontUtil.getParagraph("\n· 可视化图表\n\n",BLOCK_FONT,-1)) ;
        // 设置图片宽高
        float documentWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin();
        float documentHeight = documentWidth / 580 * 320;
        document.add(PdfFontUtil.getImage("F:\\file-type\\myChart.jpg",documentWidth-80,documentHeight-80)) ;
        // 数据表格
        document.add(PdfFontUtil.getParagraph("\n· 数据详情\n\n",BLOCK_FONT,-1)) ;
        PdfPTable dataTable = PdfFontUtil.getPdfPTable01(4,400) ;
        // 设置表格
        List<String> tableHeadList = tableHead () ;
        List<List<String>> tableDataList = getTableData () ;
        PdfFontUtil.addTableCell(dataTable,CONTENT_FONT,tableHeadList);
        for (List<String> tableData : tableDataList) {
            PdfFontUtil.addTableCell(dataTable,CONTENT_FONT,tableData);
        }
        document.add(dataTable);
        document.add(PdfFontUtil.getParagraph("\n· 报表描述\n\n",BLOCK_FONT,-1)) ;
        document.add(PdfFontUtil.getParagraph("数据报告可以监控每天的推广情况," +
                "可以针对不同的数据表现进行分析,以提升推广效果。",CONTENT_FONT,-1)) ;
        document.newPage() ;
        document.close();
        writer.close();
    }
    private static List<List<String>> getTableData (){
        List<List<String>> tableDataList = new ArrayList<>() ;
        for (int i = 0 ; i < 3 ; i++){
            List<String> tableData = new ArrayList<>() ;
            tableData.add("浙江"+i) ;
            tableData.add("杭州"+i) ;
            tableData.add("276"+i) ;
            tableData.add("33.3%") ;
            tableDataList.add(tableData) ;
        }
        return tableDataList ;
    }
    private static List<String> tableHead (){
        List<String> tableHeadList = new ArrayList<>() ;
        tableHeadList.add("省份") ;
        tableHeadList.add("城市") ;
        tableHeadList.add("数量") ;
        tableHeadList.add("百分比") ;
        return tableHeadList ;
    }
    public static void main(String[] args) throws Exception {
        createPdfPage () ;
    }
}

4、页面效果

四、网页转PDF

1、页面Jar包依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

2、编写页面样式

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
    <style>
        body{font-family:SimSun;}
    </style>
</head>
<body>
项目信息:<br/>
名称:${name}<br/>
作者:${author}<br/><br/>
<img 
src="https://oscimg.oschina.net/oscnet/up-612b9330a67ba747846b0e0890e4906678b.png"/>
<br/>
</body>
</html>

3、核心配置类

public class PageConfig {
    private static final String DEST = "F:\\file-type\\HTML页面2020-01-15.pdf";
    private static final String HTML = "/pdf_page_one.html";
    private static final String FONT = "C:/Windows/Fonts/simsun.ttc";
    private static Configuration freemarkerCfg = null ;
    static {
        freemarkerCfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        //freemarker的模板目录
        try {
            String path = "TODO:模板路径{自定义}" ;
            freemarkerCfg.setDirectoryForTemplateLoading(new File(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 创建文档
     */
    private static void createPdf(String content,String dest) throws Exception {
        Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
        document.open();
        XMLWorkerFontProvider fontImp = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
        fontImp.register(FONT);
        XMLWorkerHelper.getInstance().parseXHtml(writer, document,
                new ByteArrayInputStream(content.getBytes()), null, Charset.forName("UTF-8"), fontImp);
        document.close();
    }
    /**
     * 页面渲染
     */
    private static String freeMarkerRender(Map<String, Object> data, String htmlTmp) throws Exception {
        Writer out = new StringWriter();
        Template template = freemarkerCfg.getTemplate(htmlTmp,"UTF-8");
        template.process(data, out);
        out.flush();
        out.close();
        return out.toString();
    }
    /**
     * 方法入口
     */
    public static void main(String[] args) throws Exception {
        Map<String,Object> data = new HashMap<> ();
        data.put("name","smile");
        data.put("author","知了") ;
        String content = PageConfig.freeMarkerRender(data,HTML);
        PageConfig.createPdf(content,DEST);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/784972.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java程序设计六大原则设计模式

Java程序设计六大原则 一、单一职责原则&#xff1a; 一个接口或者类只有一个原因引起变化&#xff0c;即一个接口或者类只有一个职责&#xff0c;负责一件事情。&#xff08;此原则同样适用于方法&#xff09; 好处&#xff1a;1、复杂性降低&#xff1b;2、可读性提高&…

深度学习和神经网络

人工神经网络分为两个阶段&#xff1a; 1 &#xff1a;接收来自其他n个神经元传递过来的信号&#xff0c;这些输入信号通过与相应的权重进行 加权求和传递给下个阶段。&#xff08;预激活阶段&#xff09; 2&#xff1a;把预激活的加权结果传递给激活函数 sum :加权 f:激活…

代码随想录算法训练营之JAVA|第十一天| 239. 滑动窗口最大值

今天是第11天刷leetcode&#xff0c;立个flag。 算法挑战链接 239. 滑动窗口最大值https://leetcode.cn/problems/sliding-window-maximum/description/ 第一想法 题目理解&#xff1a;找到滑动窗口中最大的值&#xff0c;写入数组中&#xff0c;返回该数组即可。 第一个想…

VeriEye 13.0商用虹膜识别软件python SDK试用指南

最近&#xff0c;商用虹膜识别软件VeriEye 13.0发布&#xff0c;且额外地新增了python接口&#xff0c;这样就很方便大家直接调用其提供的虹膜识别接口了。 在使用python接口前&#xff0c;需要先下载安装试用版SDK&#xff0c;然后激活许可证。具体如下&#xff1a; 1. VeriE…

代码审计利器 Fortify SCA 2023.1(23.1) Crack

Fortify SCA 支持丰富的开发环境、语言、平台和框架&#xff0c;可对开发与生产混合环境进行安全检查。 25 种编程语言 超过 911,000 个组件级 API 可检测超过 961 个漏洞类别 支持所有主流平台、构建环境和 IDE。 Fortify SCA是一款商业软件&#xff0c;价格较为昂贵&#xf…

基金”中考”百亿基金经理”惜墨如金”

时下是基金二季报披露高峰&#xff0c;基民往往会期盼基金经理能在季报里带来“定心丸”。但个别基金经理的投资分析仅一两百字带过&#xff0c;对业绩亏损和调仓思路等关键问题更是直接忽略。 券商中国记者发现&#xff0c;有管理规模超370亿的基金经理&#xff0c;投资运作分…

ZohoProjects入选2022年度项目及项目组合管理类

有效的项目管理方法保证项目按照进度、成本、质量要求进行交付&#xff0c;是针对单个项目或项目群的管理&#xff0c;从而确保项目符合企业的战略目标&#xff0c;实现企业收益最大化。 对于项目管理工作来说&#xff0c;我们通常会认为只有专业的经理才能胜任&#xff0c;软件…

【每日一题】—— C. Game with Reversing (Codeforces Round 879 (Div. 2))

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;每日一题 &#x1f48c;其他专栏&#xff1a; &#x1f534; 每日反刍 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓称…

flask框架的请求处理逻辑

Django 和 Flask 是 Python 的两个非常流行的 Web 框架&#xff0c;它们对 HTTP 请求的处理方式有一些区别。 在 Django 中&#xff0c;当你的应用接收到一个 HTTP 请求时&#xff0c;Django 会将请求封装为一个 HttpRequest 对象&#xff0c;然后通过视图函数的参数传递这个对…

【计算机网络】简易TCP网络小程序

文章目录 1. 简易TCP网络程序1.1 服务端1.1.1 服务端创建套接字1.1.2 服务端绑定1.1.3 服务端监听1.1.4 服务端获取连接1.1.5 服务端处理请求 1.2 客户端1.2.1 客户端创建套接字1.2.2 客户端连接服务器1.2.3 客户端发起请求 1.3 服务器测试1.4 单执行流服务器的弊端 2. 多进程版…

【个人笔记】Linux的用户登录与退出

目录 Linux 的发行版Linux 的登录1.命令行登录2.ssh登录3.图形界面登录图形模式与文字模式的切换方式 Linux 的退出Linux 的关机与重启Linux 查看用户登录Linux在线命令工具 Linux 的发行版 Linux 的发行版说简单点就是将 Linux 内核与应用软件做一个打包。 目前市面上较知名…

使用Spring Boot实现Redis键过期回调功能

使用Spring Boot实现Redis键过期回调功能 当使用Redis作为缓存或数据存储的时候&#xff0c;有时候需要在键过期时执行一些特定的操作&#xff0c;比如清除相关数据或发送通知。在Spring Boot中&#xff0c;可以通过实现RedisMessageListener接口来实现Redis键过期回调功能。下…

任务的综合应用

需求 创建 4 个任务&#xff1a;TaskLED_1&#xff0c;TaskLED_2&#xff0c;TaskKEY_1&#xff0c;TaskKEY_2 任务要求如下&#xff1a; TaskLED_1&#xff1a;间隔 500ms 闪烁 LED1 TaskLED_2&#xff1a;间隔 1000ms 闪烁 LED2 TaskKEY_1&#xff1a;如果 taskLED1 存在…

Windows10强制删除文件或文件夹内容

一、需求描述 我们的Windows电脑中,会存在一些特殊的应用场景比如【(文件、文件夹)被读写保护、隐藏、或被程序一直占用、被感染了病毒】导致无法删除;此时候就需要采取强制删除的方式解决。 二、需求分析 文件、文件夹被占用,无法正常删除;但是有需要强制删除。 三、解…

安全攻击 --- XSS攻击

XSS跨站脚本攻击 &#xff08;1&#xff09;简介 OWASP TOP 10 之一&#xff0c;XSS被称为跨站脚本攻击&#xff08;Cross-Site-Scripting&#xff09;主要基于JavaScript&#xff08;JS&#xff09;完成攻击行为XSS通过精心构造JS代码注入到网页中&#xff0c;并由浏览器解释…

生态合作丨MemFireDB通过麒麟软件NeoCertify认证

近日&#xff0c;敏博科技“MemFireDB分布式关系数据库系统V2.8”与麒麟软件“银河麒麟高级服务器操作系统V10” 完成兼容性测试&#xff0c;获得麒麟软件 NeoCertify 认证证书。测试结果显示&#xff0c;MemFireDB数据库在国产操作系统上运行稳定&#xff0c;产品已经达到通用…

曲线拟合曲面拟合(MATLAB拟合工具箱)前馈量计算(压力闭环控制应用)

利用PLC进行压力闭环控制的项目背景介绍请查看下面文章链接,这里不再赘述。 信捷PLC压力闭环控制应用(C语言完整PD、PID源代码)_RXXW_Dor的博客-CSDN博客闭环控制的系列文章,可以查看PID专栏的的系列文章,链接如下:张力控制之速度闭环(速度前馈量计算)_RXXW_Dor的博客-CSD…

Windows下Python调用海康SDK实时显示网络摄像头

参考资源&#xff1a; 1.《Windows下Python调用海康SDK实时显示网络摄像头》 2.《HikVision SDK: C 至 Python》 3.《linux下Python调用海康SDK实时显示网络摄像头》 4.《python调用海康sdk操作热成像设备获取对应点温度》 5.《Windows下Python调用海康SDK实时视频流获取》 6.《…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)六:后台主页功能实现下

一、本章内容 接上一章,继续实现后端主页内容,主要实现工具栏对应相关内容的实现,包括系统消息、系统公告、全屏切换、语言切换、主题切换等。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 基于VUE3+Layui从头搭建通用后台管理系统合集…

(五)RabbitMQ-进阶 死信队列、延迟队列、防丢失机制

Lison <dreamlison163.com>, v1.0.0, 2023.06.23 RabbitMQ-进阶 死信队列、延迟队列、防丢失机制 文章目录 RabbitMQ-进阶 死信队列、延迟队列、防丢失机制死信队列延迟队列延迟队列介绍**延迟队列_死信队列_的实现**延迟队列_插件实现下载插件RabbitMQ 配置类RabbitMQ …