首页 > 其他分享 >easyExcel 动态列以及自适应列宽的实现

easyExcel 动态列以及自适应列宽的实现

时间:2023-07-06 18:32:32浏览次数:41  
标签:return easyExcel List cell add new 列宽 动态 ArrayList

easyExcel 动态列以及自适应列宽的实现

在使用 EasyExcel 实现动态表头和数据以及自适应列宽时,可以按照以下步骤进行操作:

1. 动态表头和数据: EasyExcel 提供了 @ExcelProperty 注解来指定对象属性与 Excel 列之间的映射关系。我们可以通过定义一个包含所有可能出现的列名作为键和对应值类型为 String 的 Map,在读取或写入数据时将其转换为 Java 对象。

具体代码示例如下:

public class DynamicHeaderData {
    private Map<String, Object> header;
    private List<Map<String, Object>> data;

    // getter 和 setter 方法

}

在读取 Excel 数据时,使用 ReadSheetsetHeadRowNumber(int) 方法设置标题所在行数,并通过 doRead() 方法获取到标题行和数据行。

// 读取 Excel 数据并返回 DynamicHeaderData 对象
DynamicHeaderData dynamicHeaderData = new DynamicHeaderData();
List<Object> headerRow = null;
List<List<Object>> dataRows = new ArrayList<>();

EasyExcel.read(file).sheet(sheetIndex)
        .registerReadListener(new AnalysisEventListener<>() {
            @Override
            public void invoke(Object object, AnalysisContext context) {
                if (context.getCurrentRowNum() == headRowNumber) {
                    headerRow = (List<Object>) object;
                } else if (context.getCurrentRowNum() > headRowNumber) {
                    dataRows.add((List<Object>) object);
                }
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) { }
        }).doRead();

dynamicHeaderData.setHeader(convertToMap(headerRow));
dynamicHeaderData.setData(convertToListOfMaps(dataRows));

在写入 Excel 数据时,通过 WriteSheetsetHead(List<? extends BaseRowModel>) 方法设置标题行,并将数据转换为 List<List<T>> 格式。

    /**
     * 动态头,实时生成头写入
     * 思路是这样子的,先创建List<String>头格式的sheet仅仅写入头,然后通过table 不写入头的方式 去写入数据
     *
     * 1. 创建excel对应的实体对象 参照{@link DemoData}
     * 2. 然后写入table即可
     */
    @Test
    public void dynamicHeadWrite() {
        String fileName = TestFileUtil.getPath() + "dynamicHeadWrite" + System.currentTimeMillis() + ".xlsx";
        EasyExcel.write(fileName)
            // 这里放入动态头
            .head(head()).sheet("模板")
            .registerWriteHandler(new CustomWidthStyleStrategy()) //拦截器将在第二部分说明
            // 当然这里数据也可以用 List<List<String>> 去传入
            .doWrite(data());
    }

    private List<List<String>> head() {
        List<List<String>> list = new ArrayList<List<String>>();
        List<String> head0 = new ArrayList<String>();
        head0.add("字符串" + System.currentTimeMillis());
        
        List<String> head1 = new ArrayList<String>();
        head1.add("数字" + System.currentTimeMillis());
        
        List<String> head2 = new ArrayList<String>();
        head2.add("日期" + System.currentTimeMillis());
        
        list.add(head0);
        list.add(head1);
        list.add(head2);
        return list;
    }

    private List<List<String>> data() {
        List<List<String>> resList = new ArrayList<List<String>>();
        List<String> dataList = new ArrayList<String>();
        dataList.add("数据1" + System.currentTimeMillis());
        
        List<String> dataList2 = new ArrayList<String>();
        dataList2.add("数据2" + System.currentTimeMillis());
        
        List<String> dataList3 = new ArrayList<String>();
        dataList3.add("数据3" + System.currentTimeMillis());
        
        resList.add(head0);
        resList.add(head1);
        resList.add(head2);
        return resList;
    }

2. 自适应列宽: EasyExcel 默认会根据内容自适应设置单元格的宽度,但有时候默认的宽度可能不够准确。您可以通过继承 AbstractColumnWidthStyleStrategy 或者手动设置每一列的宽度来实现自适应。

/**
 * 表头宽度根据数据内容自适应
 */
public class CustomWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {

    private Map<Integer, Map<Integer, Integer>> CACHE = new HashMap<>();

    /**
     * 设置列宽
     *
     * @param writeSheetHolder
     * @param cellDataList
     * @param cell
     * @param head
     * @param relativeRowIndex
     * @param isHead
     */
    @Override
    protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
        if (needSetWidth) {
            Map<Integer, Integer> maxColumnWidthMap = CACHE.get(writeSheetHolder.getSheetNo());
            if (maxColumnWidthMap == null) {
                maxColumnWidthMap = new HashMap<>();
                CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
            }

            Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
            if (columnWidth >= 0) {
                if (columnWidth > 255) {
                    columnWidth = 255;
                }
                Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
                if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
                    maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
                    writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256);
                }
            }
        }
    }

    /**
     * 数据长度
     *
     * @param cellDataList
     * @param cell
     * @param isHead
     * @return
     */
    private Integer dataLength(List<WriteCellData<?>> cellDataList, Cell cell, Boolean isHead) {
        if (isHead) {
            return cell.getStringCellValue().getBytes().length;
        } else {
            CellData cellData = cellDataList.get(0);
            CellDataTypeEnum type = cellData.getType();
            if (type == null) {
                return -1;
            } else {
                switch (type) {
                    case STRING:
                        return cellData.getStringValue().getBytes().length + 1;
                    case BOOLEAN:
                        return cellData.getBooleanValue().toString().getBytes().length;
                    case NUMBER:
                        return cellData.getNumberValue().toString().getBytes().length * 2;
                    default:
                        return -1;
                }
            }
        }
    }
}

注意,自适应列宽可能会对性能产生一定影响,特别是在处理大量数据时。如果您需要更高的性能,可以考虑通过统计内容长度并手动设置合适的列宽。

完成该拦截器,记得将该拦截器注册到EasyExcel

EasyExcel.write(fileName)
            // 这里放入动态头
            .head(head()).sheet("模板")
    
    		// 这一步非常关键,如果没有注册,相当于该类白写
            .registerWriteHandler(new CustomWidthStyleStrategy()) //拦截器将在第二部分说明
            
    		// 当然这里数据也可以用 List<List<String>> 去传入
            .doWrite(data());

以上就是使用 EasyExcel 实现动态表头和数据以及自适应列宽的简单示例。根据具体需求和情况进行调整即可。

标签:return,easyExcel,List,cell,add,new,列宽,动态,ArrayList
From: https://blog.51cto.com/u_15399050/6644308

相关文章

  • css动态生成多个class样式
    在纯CSS中,无法动态生成多个类样式。CSS是一种静态样式表语言,它主要用于描述网页上元素的外观和布局,而不能在运行时动态生成类样式。然而,你可以通过使用CSS预处理器(如Sass、Less等)或CSS-in-JS工具(如StyledComponents、Emotion等)来在一定程度上实现动态生成类样式的效果。举例来......
  • 【动态规划】子串、子序列问题
    目录应用应用1:Leetcode647.回文子串题目解题思路动态规划边界条件状态转移代码应用应用1:Leetcode647.回文子串题目647.回文子串解题思路动态规划设\(dp[i][j]\)表示子串\(s[i\cdotsj]\)是否是回文子串,若\(dp[i][j]=True\),则表示子串\(s[i\cdotsj]\)是回......
  • Flask框架:运用Ajax轮询动态绘图
    Ajax是异步JavaScript和XML可用于前后端交互,在之前《Flask框架:运用Ajax实现数据交互》简单实现了前后端交互,本章将通过Ajax轮询获取后端的数据,前台使用echart绘图库进行图形的生成与展示,后台通过render_template方法返回一串JSON数据集,前台收到后将其应用到绘图库上,实现动态监控内......
  • scala case class和普通class 动态参数赋值
    普通class赋值,将A类的属性赋值给B类//动态赋值测试objectDynamicAssignmentTest{defmain(args:Array[String]):Unit={varaList=List(newA1("A1",12),newA1("A2",13),)valb1List=scala.collection.mutable.ListBuffer......
  • EasyExcel实现excel文件重复多次写入和导出&下载文件
    一、EasyExcel实现excel文件的导出官方文档导入依赖<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>......
  • 动态库如何被加载
    linux的可执行文件都是ELF格式,它肯定是会有个section叫.interp,这里面保存的是动态链接器的路径。  我们在执行这个ELF格式的可执行文件时,内核会先根据.interp节找到动态链接器,然后把控制权交给动态链接器,由动态链接器去加载依赖的动态库。1、链接器如何找到依赖的动态库......
  • 22-数码管的动态显示
    1.数码管动态显示不同位的数码管显示不同的数值使用动态扫描的方式,使用6位8段数码管显示1,2,3,4,5,6,选中第一个数码管让其显示1,显示时间位T;经过时间T之后选中第二个数码管显示2,显示时间为T,依次进行相似的操作,显示到6之后,经过时间T之后再显示1显示一个周期所有的时间为6个周......
  • 学不会动态规划——背包篇
    前言终于把线性动态规划学完了,本蒟蒻要开始背包了,祝我好运吧!如果文章有任何问题,欢迎评论或者私信让我知道......
  • js如何动态清除form表单中input款下的错误信息
    form表单<formaction=""method="post"novalidateid="myform">{%csrf_token%}{%forforminform_obj%}<divclass="form-group"><labelfor="{{form.i......
  • Poi Excel 动态变化行高,动态创建Sheet
    需求Excel最终需要由A4纸打印出来标题名称需要动态变化行高自动变化每页都需要保留标题分析基础需求即填充标题填充数据,设置样式,基础需求可以通过easyExcel或者Poi的API来实现,但是由于需求3、4,easyExcel并不支持,只能选择使用ApachePoi。ApachePOI没有直接的API来自动......