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

说明:本人最近在着手实现导出日志数据,由于日志数据过多,在网上查找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();
    }

}
View Code

 

posted @ 2023-02-23 13:28  玩屎的猪  阅读(179)  评论(1)    收藏  举报