使用Freemarker模版导出xls文件使用excel打开提示文件损坏
本文是通过一步步的还原事件的发生并解决的一个过程记录,如果想知道如何解决的可以直接跳转文章末尾结论部分
提示一下,关注一下
Table
标签中的ss:ExpandedRowCount
属性
解决的问题
在项目中使用freemarker的xml模板导出xls格式的Excel文件时,使用国产Office工具可以打开查看,使用Excel打开提示文件已损坏
关键词
国产office,Excel,freemarker
环境信息
-
Windows 11 -
office 2019 -
永中office2022体验版 -
JDK8 -
springboot 2.6.13 -
freemarker 2.6.13
事件还原
1、首先使用Excel创建一个空白excel文件,输入我们要导出的表格模板,如下图所示,我们创建一个表格,表格中导出姓名、年龄、电话、住址等信息的这样一个表格,并且添加了一行示例数据

2、点击另存为,选中xml格式导出

3、打开xml文件,修改添加数据的地方,使用freemarker语法遍历输出数据
修改前如下图所示

修改后如下图所示

其中的#list
为固定语法,resultList
为获取输入模板数据的key,该值是一个List,as item
是*List**中的每一个对象以item
来遍历
item.name
为获取姓名,item.age
为获取年龄,item.phont
为获取电话,item.address
为获取住址
${item.name!''}
的完整意思就是输出用户名,为空时输出为空
4、创建springboot
程序,并在resources
下创建freemarker
目录,继续创建test.xml
模板文件,test.xml
文件内容就是上一步我们修改完成之后的xml
文件,结构如下

文件内容如下(本内容为Excel打开异常的,如需正常的,需跳转文章末尾)
提示一下,关注一下
Table
标签中的ss:ExpandedRowCount
属性
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"xmlns:o="urn:schemas-microsoft-com:office:office"xmlns:x="urn:schemas-microsoft-com:office:excel"xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"xmlns:html="http://www.w3.org/TR/REC-html40"><DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>zuiyu</Author><LastAuthor>zuiyu</LastAuthor><Created>2023-07-26T02:16:31Z</Created><LastSaved>2023-07-26T02:18:00Z</LastSaved><Version>16.00</Version></DocumentProperties><OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office"><AllowPNG/></OfficeDocumentSettings><ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"><WindowHeight>5880</WindowHeight><WindowWidth>14400</WindowWidth><WindowTopX>32767</WindowTopX><WindowTopY>32767</WindowTopY><ProtectStructure>False</ProtectStructure><ProtectWindows>False</ProtectWindows></ExcelWorkbook><Styles><Style ss:ID="Default" ss:Name="Normal"><Alignment ss:Vertical="Center"/><Borders/><Font ss:FontName="等线" x:CharSet="134" ss:Size="11" ss:Color="#000000"/><Interior/><NumberFormat/><Protection/></Style></Styles><Worksheet ss:Name="Sheet1"><Table ss:ExpandedColumnCount="4" ss:ExpandedRowCount="2" x:FullColumns="1"x:FullRows="1" ss:DefaultColumnWidth="51" ss:DefaultRowHeight="13.875"><Row><Cell><Data ss:Type="String">姓名</Data></Cell><Cell><Data ss:Type="String">年龄</Data></Cell><Cell><Data ss:Type="String">电话</Data></Cell><Cell><Data ss:Type="String">住址</Data></Cell></Row><#list resultList as item><Row><Cell><Data ss:Type="String">${item.name!''}</Data></Cell><Cell><Data ss:Type="Number">${item.age!''}</Data></Cell><Cell><Data ss:Type="Number">${item.phone!''}</Data></Cell><Cell><Data ss:Type="String">${item.address!''}</Data></Cell></Row></#list></Table><WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"><PageSetup><Header x:Margin="0.3"/><Footer x:Margin="0.3"/><PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/></PageSetup><Selected/><Panes><Pane><Number>3</Number><ActiveRow>4</ActiveRow><ActiveCol>5</ActiveCol></Pane></Panes><ProtectObjects>False</ProtectObjects><ProtectScenarios>False</ProtectScenarios></WorksheetOptions>
</Worksheet></Workbook>
5、编写导出excel文件的代码,都是测试数据,看看就好,只是举个例子
需要关注的点是,我们此处导出的用户数据为100,而上文中提示需要关注的参数
ss:ExpandedRowCount
参数值为2
,这就是后文要探讨的关键所在
package com.example.exceldemo.demos.excel;import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.URLEncoder;
import java.util.*;/*** @Author zuiyu* @Date 2023/7/26 10:26*/
@RestController
@RequestMapping("/excel")
public class ExcelController {@GetMapping("/export")public void export(HttpServletResponse response) throws IOException, TemplateException {Configuration configuration = new Configuration(Configuration.VERSION_2_3_26);configuration.setDefaultEncoding("utf-8");configuration.setClassForTemplateLoading(getClass(),"/freemarker");Template template = configuration.getTemplate("test.xml");List<Person> list = new ArrayList<>();for (int i = 0; i < 100; i++) {Person person1 = new Person();person1.setName("测试用户名:"+i);person1.setAge((i+1)*2);person1.setPhone(new Random().nextInt(100));person1.setAddress("地址:"+i);list.add(person1);}Map<String,Object> map = new HashMap<>();map.put("resultList",list);ServletOutputStream outputStream = response.getOutputStream();response.setContentType("application/octet-stream");response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("测试xml导出excel.xls", "UTF-8"));BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));template.process(map,bw);bw.flush();bw.close();System.out.println("导出成功");}
}
6、下面执行接口http://localhost:8080/excel/export
导出xls文件进行查看文件内容,我们的预期就是国产Office可以打开观看,而Excel打开时提示文件已损坏。打开结果就不进行展示了,感兴趣的可以使用上面的代码进行一下测试
7、下面我们修改ss:ExpandedRowCount="2"
为ss:ExpandedRowCount="9999"
,这样就可以容纳我们的100条记录。此时重启程序进行导出我们就可以发现不管是使用Excel查看还是国产Office查看都可以进行正常的显示了
8、下面是修改之后的完整的xml文件内容
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"xmlns:o="urn:schemas-microsoft-com:office:office"xmlns:x="urn:schemas-microsoft-com:office:excel"xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"xmlns:html="http://www.w3.org/TR/REC-html40"><DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>zuiyu</Author><LastAuthor>zuiyu</LastAuthor><Created>2023-07-26T02:16:31Z</Created><LastSaved>2023-07-26T02:18:00Z</LastSaved><Version>16.00</Version></DocumentProperties><OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office"><AllowPNG/></OfficeDocumentSettings><ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"><WindowHeight>5880</WindowHeight><WindowWidth>14400</WindowWidth><WindowTopX>32767</WindowTopX><WindowTopY>32767</WindowTopY><ProtectStructure>False</ProtectStructure><ProtectWindows>False</ProtectWindows></ExcelWorkbook><Styles><Style ss:ID="Default" ss:Name="Normal"><Alignment ss:Vertical="Center"/><Borders/><Font ss:FontName="等线" x:CharSet="134" ss:Size="11" ss:Color="#000000"/><Interior/><NumberFormat/><Protection/></Style></Styles><Worksheet ss:Name="Sheet1"><Table ss:ExpandedColumnCount="4" ss:ExpandedRowCount="9999" x:FullColumns="1"x:FullRows="1" ss:DefaultColumnWidth="51" ss:DefaultRowHeight="13.875"><Row><Cell><Data ss:Type="String">姓名</Data></Cell><Cell><Data ss:Type="String">年龄</Data></Cell><Cell><Data ss:Type="String">电话</Data></Cell><Cell><Data ss:Type="String">住址</Data></Cell></Row><#list resultList as item><Row><Cell><Data ss:Type="String">${item.name!''}</Data></Cell><Cell><Data ss:Type="Number">${item.age!''}</Data></Cell><Cell><Data ss:Type="Number">${item.phone!''}</Data></Cell><Cell><Data ss:Type="String">${item.address!''}</Data></Cell></Row></#list></Table><WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"><PageSetup><Header x:Margin="0.3"/><Footer x:Margin="0.3"/><PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/></PageSetup><Selected/><Panes><Pane><Number>3</Number><ActiveRow>4</ActiveRow><ActiveCol>5</ActiveCol></Pane></Panes><ProtectObjects>False</ProtectObjects><ProtectScenarios>False</ProtectScenarios></WorksheetOptions>
</Worksheet></Workbook>
总结
通过这次实验可以得知,文件的打开失败的根本原因就是数据行超过了设置的ExpandedRowCount
属性值。而我们要做的就是修改该值到能容纳我们要导出的数据即可。甚至是可以改为变量读取数据长度是否可行 。
如果感觉有用的话欢迎点赞、收藏、转发,关注公众号《醉鱼Java》获取一手面试资料,一起学编程
本文由 mdnice 多平台发布
相关文章:

使用Freemarker模版导出xls文件使用excel打开提示文件损坏
本文是通过一步步的还原事件的发生并解决的一个过程记录,如果想知道如何解决的可以直接跳转文章末尾结论部分 提示一下,关注一下 Table 标签中的 ss:ExpandedRowCount 属性 解决的问题 在项目中使用freemarker的xml模板导出xls格式的Excel文件时…...

初识Linux
今天简单了解了关于操作系统的发展史,学习了在Linux中如何远程连接云服务器的指令,以及在Linux中创建多个用户的指令。 1. ssh root 服务器远程地址 作用是用来连接XShell与云服务器,输入该指令后会自动生成输入密码的窗口,如…...

python——案例六:清空列表用clear()方法实现
案例六:清空列表用clear()方法实现LIST[0,1,2,3,4,5] print(清空前:,LIST) LIST.clear() print(清空后:,LIST)...

测试|Selenium之WebDriver常见API使用
测试|Selenium之WebDriver常见API使用 文章目录 测试|Selenium之WebDriver常见API使用1.定位对象(findElement)css定位xpath定位css选择器语法:xpath语法:校验结果 2.操作对象鼠标点击对象在对象上模拟按键输入clear清除对象输入的文本内容su…...

手把手教你uniapp和小程序分包
分包目的在于提高小程序的体积,多一个包就多2M,最多20M 常规的分包: 小程序一打开首先加载主包,然后再加载分包 分包可以用主包内的资源,主包不可以使用分包的资源 分包A不可以使用分包B里面的内容 分包可以使用a…...

Java中的代理模式
Java中的代理模式 1. 静态代理2. JDK动态代理3. CGLib动态代理 1. 静态代理 接口 public interface ICeo {void meeting(String name) throws InterruptedException; }目标类 public class Ceo implements ICeo{public void meeting(String name) throws InterruptedExcepti…...

LeetCode每日一题——1331.数组序号转换
题目传送门 题目描述 给你一个整数数组 arr ,请你将数组中的每个元素替换为它们排序后的序号。 序号代表了一个元素有多大。序号编号的规则如下: 序号从 1 开始编号。一个元素越大,那么序号越大。如果两个元素相等,那么它们的…...

2、Tomcat介绍(下)
组件分类 在Apache Tomcat中,有几个顶级组件,它们是Tomcat的核心组件,负责整个服务器的运行和管理。这些顶级组件包括: Server(服务器):Tomcat的server.xml配置文件中的<Server>元素代表整个Tomcat服务器实例。每…...

JAVA 正则表达式(heima)
JAVA 正则表达式(heima) public class RegexDemo01 {/** 正则表达式介绍:本质来说就是一个字符串,字符串中可以指定规则,来对其他字符串进行校验。* public boolean matches(String regex):根据传入的正则表达式&#…...

布瑞特单圈绝对值旋转编码器串口数据读取
布瑞特单圈绝对值旋转编码器串口数据读取 数据手册:http://briter.net/col.jsp?id109 (2.1版本RS485说明书通信协议 单圈.pdf) 绝对式编码器为布瑞特BRT38-ROM16384-RT1,采用RS485通信。 该绝对式编码器共有5根线:红、黄、黑、绿、白 由…...

Linux第六章之vim与gcc使用
一、Linux编辑器-vim使用 vi/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面。例如语法加亮,可视化操作不仅可以在终端运行,也…...

【Golang】Golang进阶系列教程--为什么说 Go 语言字符串是不可变的?
文章目录 前言推荐阅读 前言 最近有读者留言说,平时在写代码的过程中,是会对字符串进行修改的,但网上都说 Go 语言字符串是不可变的,这是为什么呢? 这个问题本身并不困难,但对于新手来说确实容易产生困惑…...

ES开启身份认证
文章目录 X-Pack简介之前的安全方案ES开启认证ES服务升级https协议开启集群节点之间的证书认证 X-Pack简介 X-Pack是Elastic Stack扩展功能,提供安全性,警报,监视,报告,机器学习和许多其他功能。 X-Pack的发展演变&am…...

Docker安装es以及ik分词器
1、拉取镜像 docker pull elasticsearch:7.10.12、下载对应版本的ik分词、并将它们解压到ik文件夹下,如图 https://github.com/medcl/elasticsearch-analysis-ik/releases 3、在服务器上创建文件夹 mkdir /usr/elklog/elk/es mkdir /usr/elklog/elk/es/data mkdi…...
中断、进程调度、进程切换、系统调用,模式切换的那些事情
提示:风萧声动,玉壶光转,一夜鱼龙舞 文章目录 前言中断进程调度进程切换线程切换模式切换所以他们有什么关系? 前言 本文内容主要参考以下几个博文中学得 进程与线程(中)的2.2.7 进程切换VS模式切换&#…...

使用web-view实现网页端和uni-app端是数据传输
要实现这个功能 第一步:要在vue的public文件夹下面引入 <script type"text/javascript" src"https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script> 第二步:建立一个新的空的uni-app项目…...

Ajax快速入门
Ajax Ajax就是前端访问服务器端数据的一个技术 还有主要就是异步交互 就是在不刷新整页面的情况下,和服务器交换部分我也数据 比如搜索的联想技术 同步和异步的概念 一个是客户端需要等待服务器完成处理,才能进行别的事 一个是客户端不需要等待服务器处…...

Google OAuth 2 authorization - Error: redirect_uri_mismatch 400
出现这个问题,一般是因为google授权origin地址和重定向redirect_uri地址没有匹配上。 请仔细检查重定向地址的url中origin部分和授权origin部分是否能够匹配:...

Qt 中操作xml文件和JSON字符串
文章目录 1、概述1.1、xml介绍1.2、json介绍 2、xml文件增删改查2.1、写xml文件内容2.2、读xml文件内容2.3、删除xml文件内容2.4、修改xml文件内容 3、构建JSON字符串3.1、JSON字符串排版4、剪切板操作 1、概述 1.1、xml介绍 XML 指可扩展标记语言(EXtensible Mark…...
React 基础篇(二)
💻 React 基础篇(二)🏠专栏:React 👀个人主页:繁星学编程🍁 🧑个人简介:一个不断提高自我的平凡人🚀 🔊分享方向:目前主攻…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...