说明:本人最近在着手实现导出日志数据,由于日志数据过多,在网上查找java 导出大量数据到excel的例子。

后发现园子里某位老哥通过StringTemplate模板生成excel格式的xml,这个思路令我大为惊奇。

在融入到自己的项目后,发现wps可以正常打开生成的文件,但excel2019无法打开。

通过各种测试,后发现一种方法能解决这个问题。

老哥原文链接:【https://www.cnblogs.com/barrywxx/p/10700283.html】

没看过的先看看老哥的思路。

我这里只针对excel无法打开生成的文件做解决说明

第一步:列数写为固定的16384

    /***
* 写入excel文件数据信息
* 一页写入
*/
public <T> void writeExcelOneSheetData(String sheetName, List<T> dataList) {
// 写入excel文件数据信息
// 列数
StringTemplate body = stGroup.getInstanceOf(templateSuffix + "body");
Worksheet worksheet = new Worksheet();
worksheet.setSheet(sheetName);
     // 最重要的是这一行,将列数写为固定的16384,别问为什么,我也不知道!
worksheet.setColumnNum(16384);
worksheet.setRowNum(dataList.size() + 10);
worksheet.setRows(dataList);
body.setAttribute("worksheet", worksheet);
this.writer.print(body.toString());
this.writer.flush();
worksheet = null;
body = null;
Runtime.getRuntime().gc();
}

第二步:生成的文件后缀使用xls,不要使用xlsx。

而后使用excel打开,会弹出文件不安全提示,问是否继续打开?点击是。问题完美解决!

期间还试过对内容里的特殊符号进行转译处理,后来发现不用转译也能正常显示。不过还是把转译的贴出来,需要自取:

    public static String xmlTranslation(String s) {
// 写之前对特殊字符串进行转义
//&lt; <
// &gt; >
// &amp; &
// &apos; '
// &quot; "
s = s.replace("&", "&amp;");
s = s.replace("<", "&lt;");
s = s.replace(">", "&gt;");
s = s.replace("'", "&apos;");
s = s.replace("\"", "&quot;");
return s;
}

这是我的完整代码,有需要自取:

package com.hz.plat.common.util;

import com.hz.plat.common.entity.Worksheet;
import lombok.extern.slf4j.Slf4j;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup; import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.util.List; /**
* 类功能描述:generator big data Excel
*
* @author WangXueXing create at 19-4-13 下午10:23
* @version 1.0.0
*/
@Slf4j
public class ExcelGenerator { StringTemplateGroup stGroup = null;
PrintWriter writer = null; String templateSuffix = "Excel"; public ExcelGenerator() {
} public ExcelGenerator(String suffix, File file) {
this.templateSuffix = suffix;
this.stGroup = new StringTemplateGroup("test");
this.writer = writeExcelHead(file);
} /**
* 写入单个Sheet的Excel
*
* @param templatePrefix 模板前缀,默认两个模板后缀分别为head及body
* @param outFile 生成Excel文件
* @param sheetName 单个sheet名称
* @param dataList 填充数据列表
* @param <T> 填充对象泛型
* @throws FileNotFoundException
* @throws ClassNotFoundException
*/
public static <T> void writeExcelOneSheet(String templatePrefix, File outFile, String sheetName, Class clazz, List<T> dataList) {
long startTimne = System.currentTimeMillis();
StringTemplateGroup stGroup = new StringTemplateGroup(String.valueOf(startTimne));
// 写入excel文件头部信息
StringTemplate head = stGroup.getInstanceOf(templatePrefix + "head");
try (PrintWriter writer = new PrintWriter(new BufferedOutputStream(Files.newOutputStream(outFile.toPath())))) {
writer.print(head.toString());
writer.flush();
// excel单表最大行数是65535
Field[] fields = clazz.getDeclaredFields();
// 写入excel文件数据信息
StringTemplate body = stGroup.getInstanceOf(templatePrefix + "body");
Worksheet worksheet = new Worksheet();
worksheet.setSheet(sheetName);
worksheet.setColumnNum(fields.length + 2);
worksheet.setRowNum(10000 + 10);
worksheet.setRows(dataList);
body.setAttribute("worksheet", worksheet);
writer.print(body.toString());
writer.flush();
// 写入excel文件尾部
writer.print("</Workbook>");
writer.flush();
} catch (Exception e) {
log.error("写入Excel异常", e);
}
} public static String xmlTranslation(String s) {
// 写之前对特殊字符串进行转义
//&lt; <
// &gt; >
// &amp; &
// &apos; '
// &quot; "
s = s.replace("&", "&amp;");
s = s.replace("<", "&lt;");
s = s.replace(">", "&gt;");
s = s.replace("'", "&apos;");
s = s.replace("\"", "&quot;");
return s;
} /***
* 获取PrintWriter
*/
private PrintWriter writeExcelHead(File file) {
// 正式开始
try {
PrintWriter writer = new PrintWriter(new BufferedOutputStream(Files.newOutputStream(file.toPath())));
// 写入excel文件头部信息
StringTemplate head = stGroup.getInstanceOf(templateSuffix + "head");
writer.print(head.toString());
writer.flush();
// 头部信息写入完成
return writer;
} catch (Exception e) {
log.error("写入Excel异常", e);
}
return null;
} /***
* 写入excel文件数据信息
* 分页写入
*/
public <T> void writeExcelAssignSheetData(String sheetName, List<List<T>> dataList) {
// 写入excel文件数据信息
// 列数
for (int i = 0, dataListSize = dataList.size(); i < dataListSize; i++) {
List<T> x = dataList.get(i);
writeExcelOneSheetData(sheetName + "(" + (i + 1) + ")", x);
}
} /***
* 写入excel文件数据信息
* 一页写入
*/
public <T> void writeExcelOneSheetData(String sheetName, List<T> dataList) {
// 写入excel文件数据信息
// 列数
StringTemplate body = stGroup.getInstanceOf(templateSuffix + "body");
Worksheet worksheet = new Worksheet();
worksheet.setSheet(sheetName);
worksheet.setColumnNum(16384);
worksheet.setRowNum(dataList.size() + 10);
worksheet.setRows(dataList);
body.setAttribute("worksheet", worksheet);
this.writer.print(body.toString());
this.writer.flush();
worksheet = null;
body = null;
Runtime.getRuntime().gc();
} /***
* 写入excel文件尾部
*/
public void finishExcel() {
// 写入excel文件尾部
writer.print("</Workbook>");
writer.flush();
writer.close();
} }

关于通过StringTemplate模板生成xml转成excel后office无法打开的问题解决的更多相关文章

  1. NPOI根据模板生成chart图表导出Excel

    导入NPOI的全部dll. 因为NPOI的API里面还没有对于Chart图表方面的操作,所以只能根据提示做好的图表作为模板,修改数据源的方法来改变图表. 注意:NPOI要用2003版以下的excel才 ...

  2. Html Table用JS导出excel格式问题 导出EXCEL后单元格里的000412341234会变成412341234 7-14 会变成 2018-7-14(7月14) 自定义格式 web利用table表格生成excel格式问题 js导出excel增加表头、mso-number-format定义数据格式 数字输出格式转换 mso-number-format:"\@"

    Html Table用JS导出excel格式问题 我在网上找的JS把HTML Tabel导出成EXCEL.但是如果Table里的数字内容为0开的的导成Excel后会自动删除0,我想以text的格式写入 ...

  3. JAVAWEB使用FreeMarker利用ftl把含有图片的word模板生成word文档,然后打包成压缩包进行下载

    这是写的另一个导出word方法:https://www.cnblogs.com/pxblog/p/13072711.html 引入jar包,freemarker.jar.apache-ant-zip- ...

  4. 使用freemarker生成xml模板

    今天在java交流群里有个人问我如何用freemarker生成xml模板文件,可以手动配置参数,于是我到网上百度了一下.发现有一位同行的博文写的很nice,于是我就照着他的代码敲了一遍,最后实现了,本 ...

  5. Spring MVC-集成(Integration)-生成XML示例(转载实践)

    以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_xml.htm 说明:示例基于Spring MVC 4.1.6. 以下示例说明如何 ...

  6. ASP.NET MVC 解析模板生成静态页一(RazorEngine)

    简述 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项.在早期的MVC版本中默认使用的是ASPX模板引擎,Razor在语法上的确不错,用起来非常方便,简洁的语法 ...

  7. NET MVC RazorEngine 解析模板生成静态页

    ASP.NET MVC 解析模板生成静态页一(RazorEngine) 简述 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项.在早期的MVC版本中默认使用的是 ...

  8. T4模板生成代码。 数据实体层与数据仓储层。备注

    文件生成模板:TempleteManager.ttinclude <#@ assembly name="System.Core" #><#@ assembly n ...

  9. freemarker根据模板生成word文件实现导出功能

    一.准备工作 1.创建一个03的word文档,动态的数据用占位符标志占位(如testname).然后另存为word2003的xml文件. 2.格式化xml文件,占位符的位置用${testname}代替 ...

  10. java通过FreeMarker模板生成Excel文件之.ftl模板制作

    关于怎么通过freemarker模板生成excel的文章很多,关键点在于怎么制作模板文件.ftl 网上的办法是: (1)把Excel模板的格式调好,另存为xml文件 (2)新建一个.ftl文件,把xm ...

随机推荐

  1. Python 引用问题 - ImportError: attempted relative import with no known parent package

    问题描述 近日在尝试引用其他文件的代码时,遇到了错误: ImportError: attempted relative import with no known parent package. 问题大 ...

  2. python学习笔记:第七章面向对象

    与java类似,python作为一种面向对象的编程语言,也可以创建自定义的对象和类. 它的特性主要有:继承,封装,多态,方法,属性,超类 1.变量的作用域 c = 50 #全局变量, 作用域为整个模块 ...

  3. 跟运维学 Linux - 01

    跟运维学 Linux - 01 运维的诞生 运维工程师有很多叫法:系统运维.Linux 工程师.系统管理员... 网管可以说是运维工程师最早的雏形.在个人电脑未普及时,大家去网吧玩游戏. 玩家:&qu ...

  4. JFrame一些基础小知识

    JFrame.setLocationRelativeTo方法 JFrame.setLocationRelativeTo()是一个Java Swing中的方法,它用于将窗口居中显示在屏幕上. 当你调用该 ...

  5. 【overcome error】dereferencing pointer to incomplete type

    @ 目录 前言 解决 代码情况 分析问题 尾声 前言 这个问题是我在学习数据结构链栈部分遇到的,英文报错如题所示,中文意思是:取消引用不完整类型的指针,在百度一圈也没明白,(百度搜索,看一个和全看基本 ...

  6. 【pandas小技巧】--日期相关处理

    日期处理相关内容之前pandas基础系列中有一篇专门介绍过,本篇补充两个常用的技巧. 1. 多列合并为日期 当收集来的数据中,年月日等信息分散在多个列时,往往需要先合并成日期类型,然后才能做分析处理. ...

  7. Prism报错

    Rules.Default..WithoutFastExpressionCompiler()报错 说没有找到容器 1.查看Prism.Wpf源码 获取DryIoc容器规则 2.证明项目中出现了另外一个 ...

  8. 《深入理解Java虚拟机》读书笔记:Class类文件的结构

    Class类文件的结构 Sun公司以及其他虚拟机提供商发布了许多可以运行在各种不同平台上的虚拟机,这些虚拟机都可以载入和执行同一种平台无关的的程序存储格式--字节码(ByteCode),从而实现了程序 ...

  9. SpringBoot 启动流程追踪(第二篇)

    上一篇文章分析了除 refresh 方法外的流程,并着重分析了 load 方法,这篇文章就主要分析 refresh 方法,可以说 refresh 方法是 springboot 启动流程最重要的一环,没 ...

  10. C++算法之旅、04 基础篇 | 第一章

    常用代码模板1--基础算法 - AcWing ios::sync_with_stdio(false) 提高 cin 读取速度,副作用是不能使用 scanf 数据输入规模大于一百万建议用scanf 快速 ...