欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Hutool工具类BigExcelWriter导出Excel调用autoSizeColumnAll()方法无法自适应列宽度的问题

程序员文章站 2022-04-07 18:29:37
看的这个人的https://blog.csdn.net/weixin_43466094/article/details/108940721没用啊。还是不自适应。升了包的版本也是无效。看起来比不设置稍微列宽长了一点而已后来看github上有issuehttps://github.com/looly/hutool/issues/1210以及百度,是中文计算长度的原因解决:新建一个MyExcelWriter.java继承BigExcelWriter,重写autoSizeColumnAll方法 pu...

看的这个人的
https://blog.csdn.net/weixin_43466094/article/details/108940721

没用啊。还是不自适应。升了包的版本也是无效。看起来比不设置稍微列宽长了一点而已

后来看github上有issue
https://github.com/looly/hutool/issues/1210

以及百度,是中文计算长度的原因

解决:
新建一个MyExcelWriter.java继承BigExcelWriter,重写autoSizeColumnAll方法

 public static MyExcelWriter getBigWriter() {
        try {
            return new MyExcelWriter();
        } catch (NoClassDefFoundError var1) {
            throw new DependencyException((Throwable) ObjectUtil.defaultIfNull(var1.getCause(), var1), "You need to add dependency of 'poi-ooxml' to your project, and version >= 4.1.2", new Object[0]);
        }
    }


 @Override
    public BigExcelWriter autoSizeColumnAll() {
        final SXSSFSheet sheet = (SXSSFSheet)this.sheet;
        sheet.trackAllColumnsForAutoSizing();
        super.autoSizeColumnAll();
        for (int i = 0; i <sheet.getRow(sheet.getLastRowNum()).getPhysicalNumberOfCells(); i++) {
            // 解决自动设置列宽中文失效的问题
            sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 17 / 10);
        }
        sheet.untrackAllColumnsForAutoSizing();
        return this;
    }

使用示范:

 /**
     * test
     * @param response
     * @throws IOException
     */
    @GetMapping("/testAutoSizeColumnAll")
    public void testAutoSizeColumnAll(HttpServletResponse response) throws IOException {
        List<?> row1 = CollUtil.newArrayList("增速排名", "关键词", "slope值", "周期", "最近一周排名");
        List<?> row2 = CollUtil.newArrayList("1", "lysol", "6.00", "2020-26周 - 2020-27周", "5");
        List<?> row3 = CollUtil.newArrayList("2", "masks for coronavirus protection", "1.00", "2020-26周 - 2020-27周", "3");


        List<List<?>> rows = CollUtil.newArrayList(row1, row2, row3);


        // 通过工具类创建writer,默认创建xls格式  todo  改成get
        MyExcelWriter writer =MyExcelWriter.getBigWriter();
        // 一次性写出内容,使用默认样式,强制输出标题
        writer.write(rows, true);
        // 设置所有列为自动宽度,不考虑合并单元格
        writer.autoSizeColumnAll();


        //response为HttpServletResponse对象
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
        response.setHeader("Content-Disposition","attachment;filename=test.xls");
        //out为OutputStream,需要写出到的目标流
        ServletOutputStream out = response.getOutputStream();

        writer.flush(out, true);
        // 关闭writer,释放内存
        writer.close();
        //此处记得关闭输出Servlet流
        IoUtil.close(out);

    }

如何获取列长度, 为第一行writer.merge做准备:
【Hutool Excel】List方式生成Excel

 //字段数量
        int fieldLength = StaffVo.class.getDeclaredFields().length;

【Hutool Excel】Map方式生成Excel

 //字段数量
        int fieldLength = rows.get(0).size();
	1. SXSSFSheet sheet = (SXSSFSheet) writer.getSheet();
	 sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 17 / 10);不然它报不能自动转
	2.   writer.autoSizeColumnAll();在 writer.write(之后
	-----------------历经傍晚测试到半夜三点
	与是否BigExcel无关
	与this无关
	与是否直接调封装方法写本地还是转读取为io流网络写出无关
	与是否合并首行无关  
	与特殊字符无关
猜测与  rows 数据结构有关——只支持【行列对象List:行列对象List<List<?>>】写出的方式,才autoSizeColumnAll
	
	都错。
	
	尼玛,不经意限制rows长度后(本意是想把线上数据黏贴一两条出来[列较多],放本地psvm里运行看excel效果是否有变化),发现数据量小时,正常自适应了!数据量大时,就会失效(99可行,100条不行。  ThreadUtil.sleep(30*1000);无效
	好巧的数字【妈的,早知道debug了,浪费我这么多时间在这测。这就是不自信debug的下场吗。这估计是为了BigExcel效率而特地限制的吧】,感觉像认为限制的呢,果然,点进原码发现SXSSFSheet _randomAccessWindowSize
	

原因:
破案了,是BigExcel机制的原因:
https://blog.csdn.net/zlp5201/article/details/21611673

 比如内存中限制行数为100,当行号到达101时,行号为0的记录刷新到硬盘并从内存中删除,当行号到达102时,行号为1的记录刷新到硬盘,并从内存中删除,以此类推。

       rowAccessWindowSize代表指定的内存中缓存记录数,默认为100,此值可以通过

new SXSSFWorkbook(int rowAccessWindowSize)或SXSSFSheet.setRandomAccessWindowSize(intwindowSize)来设置。

不过,
sheet.setRandomAccessWindowSize(10000);
无效。

 SXSSFSheet sheet = (SXSSFSheet) writer.getSheet();
        sheet.setRandomAccessWindowSize(5000);

无效。 2020年11月28日 03:55:59

或者是因为我直接写入磁盘得原因,100一次。虽重设无用。
如果写到流呢,会存在100一写的可能吗,会重设有用吗。【没试,但估计指定不可能:flushout又不管你写到哪】

或者换Writer类型【所有对生成后数据样式操作都受此机制影响,比如改行高。我这自适应不就是列宽,和它一码事。】

试试其他方式产生excel能否自适应宽(少量数据时),估计能,因为特么原理明白了:【没试,但估计指定不可能:生成后设置得自适应。这三种方式只是不同的在内存中制造excel的方式而已,而设置自适应又不在这呢。】https://blog.csdn.net/zhangjinwei417/article/details/99413184
试了,BigExcel时,setRandomAccessWindowSize(-1),没用-_-||

【你为了效率都不改fastdfs名了,都异步了,就不该歪做自适应这种影响生成效率的行为了。手动重设列宽效率还行,可以接受。】

本文地址:https://blog.csdn.net/CW_SZDX/article/details/110236881

相关标签: 工作IT