使用Freemarker模版导出xls文件使用excel打开提示文件损坏

简介: 使用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,该值是一个Listas 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》获取一手面试资料,一起学编程


目录
相关文章
|
3月前
|
Python
Excel中如何批量重命名工作表与将每个工作表导出到单独Excel文件
本文介绍了如何在Excel中使用VBA批量重命名工作表、根据单元格内容修改颜色,以及将工作表导出为独立文件的方法。同时提供了Python实现导出工作表的代码示例,适用于自动化处理Excel文档。
|
5月前
|
人工智能 算法 安全
使用CodeBuddy实现批量转换PPT、Excel、Word为PDF文件工具
通过 CodeBuddy 实现本地批量转换工具,让复杂的文档处理需求转化为 “需求描述→代码生成→一键运行” 的极简流程,真正实现 “技术为效率服务” 的目标。感兴趣的快来体验下把
163 10
|
10月前
|
人工智能 自然语言处理 Java
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
FastExcel 是一款基于 Java 的高性能 Excel 处理工具,专注于优化大规模数据处理,提供简洁易用的 API 和流式操作能力,支持从 EasyExcel 无缝迁移。
1979 65
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
|
8月前
|
文字识别 Serverless 开发工具
【全自动改PDF名】批量OCR识别提取PDF自定义指定区域内容保存到 Excel 以及根据PDF文件内容的标题来批量重命名
学校和教育机构常需处理成绩单、报名表等PDF文件。通过OCR技术,可自动提取学生信息并录入Excel,便于统计分析和存档管理。本文介绍使用阿里云服务实现批量OCR识别、内容提取、重命名及导出表格的完整步骤,包括开通相关服务、编写代码、部署函数计算和设置自动化触发器等。提供Python示例代码和详细操作指南,帮助用户高效处理PDF文件。 链接: - 百度网盘:[链接](https://pan.baidu.com/s/1mWsg7mDZq2pZ8xdKzdn5Hg?pwd=8866) - 腾讯网盘:[链接](https://share.weiyun.com/a77jklXK)
831 5
|
8月前
|
文字识别 BI
【图片型PDF】批量识别扫描件PDF指定区域局部位置内容,将识别内容导出Excel表格或批量改名文件,基于阿里云OCR对图片型PDF识别改名案例实现
在医疗和政务等领域,图片型PDF文件(如病历、报告、公文扫描件)的处理需求广泛。通过OCR技术识别这些文件中的文字信息,提取关键内容并保存为表格,极大提高了信息管理和利用效率。本文介绍一款工具——咕嘎批量OCR系统,帮助用户快速处理图片型PDF文件,支持区域识别、内容提取、导出表格及批量改名等功能。下载工具后,按步骤选择处理模式、进行区域采样、批量处理文件,几分钟内即可高效完成数百个文件的处理。
814 8
|
10月前
|
Python
批量将不同的工作簿合并到同一个Excel文件
本文介绍如何使用Python的`pandas`库批量合并不同工作簿至同一Excel文件。通过模拟生成三个班级的成绩数据,分别保存为Excel文件,再将这些文件合并成一个包含所有班级成绩的总成绩单。步骤包括安装必要库、生成数据、保存与合并工作簿。
248 6
|
3月前
|
Python
如何根据Excel某列数据为依据分成一个新的工作表
在处理Excel数据时,我们常需要根据列值将数据分到不同的工作表或文件中。本文通过Python和VBA两种方法实现该操作:使用Python的`pandas`库按年级拆分为多个文件,再通过VBA宏按班级生成新的工作表,帮助高效整理复杂数据。
|
3月前
|
数据采集 数据可视化 数据挖掘
用 Excel+Power Query 做电商数据分析:从 “每天加班整理数据” 到 “一键生成报表” 的配置教程
在电商运营中,数据是增长的关键驱动力。然而,传统的手工数据处理方式效率低下,耗费大量时间且易出错。本文介绍如何利用 Excel 中的 Power Query 工具,自动化完成电商数据的采集、清洗与分析,大幅提升数据处理效率。通过某美妆电商的实战案例,详细拆解从多平台数据整合到可视化报表生成的全流程,帮助电商从业者摆脱繁琐操作,聚焦业务增长,实现数据驱动的高效运营。
|
5月前
|
存储 安全 大数据
网安工程师必看!AiPy解决fscan扫描数据整理难题—多种信息快速分拣+Excel结构化存储方案
作为一名安全测试工程师,分析fscan扫描结果曾是繁琐的手动活:从海量日志中提取开放端口、漏洞信息和主机数据,耗时又易错。但现在,借助AiPy开发的GUI解析工具,只需喝杯奶茶的时间,即可将[PORT]、[SERVICE]、[VULN]、[HOST]等关键信息智能分类,并生成三份清晰的Excel报表。告别手动整理,大幅提升效率!在安全行业,工具党正碾压手动党。掌握AiPy,把时间留给真正的攻防实战!官网链接:https://www.aipyaipy.com,解锁更多用法!
|
3月前
|
Python
将Excel特定某列数据删除
将Excel特定某列数据删除

热门文章

最新文章