easyexcel横竖不固定如何写入

easyexcel横竖不固定如何写入,第1张

因为easyexcel做写入都是使用list作为数据,而这个账单则使用一个实体就够了,所以这里使用二维数组保存数据,而实体中的值使用一个自定义的注解来标记位置和单元格总的内容,反射获取注解中的位置,进行二维数组中的赋值,最后转为list传入easyexcel提供的生成代码里

0准备

准备一个自定义的注解,用来标记静态数据的位置、单元格内容

一个男子汉罢了

关注

关于easyexcel的不规则写入 原创

2022-01-26 17:00:46

1点赞

一个男子汉罢了

码龄2年

关注

最近在做一个项目时遇到了从数据库取数据生成一个账单的功能,其中一个excel中有多个sheet,有的是不规则的表格,有的则是比较规则的表格

做写入时发现了easyexcel这个开源的api,它在做大量数据的时候还可以保证内存不溢出,这点是比poi要好的,但是网上针对不规则的写入这个功能记录的比较少,这里写一下使用的过程

楼主也是小白一个,希望大家多指教,谢谢

这里先说一下思路:因为easyexcel做写入都是使用list作为数据,而这个账单则使用一个实体就够了,所以这里使用二维数组保存数据,而实体中的值使用一个自定义的注解来标记位置和单元格总的内容,反射获取注解中的位置,进行二维数组中的赋值,最后转为list传入easyexcel提供的生成代码里

0准备

准备一个自定义的注解,用来标记静态数据的位置、单元格内容

@Target({ElementTypeFIELD})

@Retention(RetentionPolicyRUNTIME)

@Documented

public @interface Sheet1RecordTemplate {

//excel中的行号

int rowNo();

//excel中的列号

int columnNo();

//单元格内容

String name();

}

实体:

这里说一下,这个实体是用来标记sheet中的静态内容的,与数据库无关

//静态单元格数据

public class ExcelEntity {

@Sheet1RecordTemplate(rowNo=1,columnNo = 1,name = "xxx有限公司")

//这里就代表第一行的第一列,内容为"xxx有限公司"

String value1;

@Sheet1RecordTemplate(rowNo=3,columnNo = 1,name = "结 算 单")

String value2;

@Sheet1RecordTemplate(rowNo=5,columnNo = 1,name = "客户名称")

String value3;

}

1首先是controller,这里具体调数据库的过程就不写了,总之得到了一个实体对象

//easyexcel生成

@RequestMapping("download")

public String downLoad(WriteDTO writeDTO) {

WriteVO writeVO = new WriteVO();

BeanUtilscopyProperties(writeDTO, writeVO); //将dto转换为vo

WriteVO excel = writeServicegetExcel(writeVOgetId()); //id传service

WriteDTO writeDTO1 = new WriteDTO();

BeanUtilscopyProperties(excel, writeDTO1); //将取出的数据再转dto,使用dto进行生成

try {

EasyexcelUtilrun(writeDTO1,""); //调一个工具类,完成生成

} catch (Exception e) {

eprintStackTrace();

return "生成成功";

}

2工具类,进行excel的生成

public class EasyexcelUtil {

public static void run(WriteDTO writeDTO, String filepath) throws ClassNotFoundException, IllegalAccessException, InstantiationException {

//创建二维数组保存账单格式,反射赋值

Class<> clazz = ClassforName(ExcelEntityclassgetName());

Field[] declaredFields = clazzgetDeclaredFields();

String[][] cellNums = new String[17][10]; //二维数组的格式,按你们自己的表格来写

for (Field field : declaredFields) {

fieldsetAccessible(true);

//isAnnotationPresent如果指定类型的注释存在于此元素上,返回true

if (fieldisAnnotationPresent(Sheet1RecordTemplateclass)) {

Sheet1RecordTemplate annotation = fieldgetAnnotation(Sheet1RecordTemplateclass);

int rowNo = annotationrowNo();

int columnNo = annotationcolumnNo();

String name = annotationname();

cellNums[rowNo-1][columnNo-1]=name; //从0开始,所以减1

}

}

//从数据库中取出赋值给表格(二维数组),这里是动态单元格的数据

cellNums[4][1]=writeDTOgetUser();

//二维数组转list

List<List<String>> excelList = new ArrayList<>();

for (int i = 0; i < cellNumslength; i++) {

List<String> columnList = new ArrayList<String>();

for (int j = 0; j < cellNums[i]length; j++) {

columnListadd(j, cellNums[i][j]);

}

excelListadd(i, columnList);

}

String fileName = "D://file/账单模版xls";

//生成

WriteSheet sheet = EasyExcelwriterSheet(0, "结算单")

registerWriteHandler(new MyMergeStrategy())//合并单元格策略

registerWriteHandler(new CellSytle())//样式策略

build();

ExcelWriter excelWriter = EasyExcelwrite(fileName)

excelType(ExcelTypeEnumXLS)

autoCloseStream(true)

// inMemory(true) //文件放在内存还是磁盘

build();

excelWriterwrite(excelList, sheet);//生成Excel

excelWriterfinish();

}

}

3样式策略

这里说明一下,样式尽量需要复用,创建大量样式对象是很消耗性能的,我这里定义了6个,这个样式最好自己总结一下

public class CellSytle implements CellWriteHandler {

//样式进行复用

private CellStyle cellStyle1= null;

private CellStyle cellStyle2= null;

private CellStyle cellStyle3= null;

private CellStyle cellStyle4= null;

private CellStyle cellStyle5= null;

private CellStyle cellStyle6= null;

@Override

public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {

}

@Override

public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {

}

@Override

public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

}

//不懂的小伙伴这里可以多看看参数可以调用的方法,能获取到很多对象使用

@Override

public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {

//全局行列格式

//默认的行高,列宽

writeSheetHoldergetSheet()setDefaultRowHeight((short) 264);

writeSheetHoldergetSheet()setDefaultColumnWidth(11);

//单元格当前行数

int rowIndex = cellgetRowIndex();

//单元格当前列数

int columnIndex = cellgetColumnIndex();

//当前行

Row row = cellgetRow();

//样式进行复用

if (cellStyle1==null){

cellStyle1=createTitleCellStyle(cellgetSheet()getWorkbook()createCellStyle(), writeSheetHolder, 0);

}

if (cellStyle2==null){

cellStyle2=createHeadCellStyle(cellgetSheet()getWorkbook()createCellStyle(), writeSheetHolder, 0);

}

if (cellStyle3==null){

cellStyle3=createContentCellStyle(cellgetSheet()getWorkbook()createCellStyle(), writeSheetHolder, 1);

}

if (cellStyle4==null){

cellStyle4=createContentCellStyle(cellgetSheet()getWorkbook()createCellStyle(), writeSheetHolder, 2);

}

if (cellStyle5==null){

cellStyle5=createContentCellStyle(cellgetSheet()getWorkbook()createCellStyle(), writeSheetHolder, 3);

}

if (cellStyle6==null){

cellStyle6=createContentCellStyle(cellgetSheet()getWorkbook()createCellStyle(), writeSheetHolder, 4);

}

//按行设置样式的策略

switch (rowIndex){

case 0:

if (columnIndex>10){

break;

}

rowsetHeight((short) 600);

cellsetCellStyle(cellStyle1);

break;

case 1:

break;

case 2:

if (columnIndex>10){

break;

}

rowsetHeight((short) 400);

cellsetCellStyle(cellStyle2);

break;

case 3:

break;

case 4:

if (columnIndex>10){

break;

}

cellsetCellStyle(cellStyle3);

//这行的第8个单元格样式不一样

if (columnIndex==8){

cellsetCellStyle(cellStyle4);

}

break;

default:

break;

}

}

/

创建样式

这里的样式是自定义的,方法差不多就行,参数的rowStyle命名不严谨,应该是cellStyle

/

private static CellStyle createTitleCellStyle(CellStyle rowStyle,WriteSheetHolder writeSheetHolder, int sheetNo) {

rowStylesetAlignment(HorizontalAlignmentCENTER);//水平居中

rowStylesetVerticalAlignment(VerticalAlignmentCENTER);//垂直对齐

Font font = writeSheetHoldergetSheet()getWorkbook()createFont(); // 创建字体样式

fontsetBold(true); //字体加粗

fontsetFontName("宋体"); // 设置字体类型

if (sheetNo == 0) {

fontsetFontHeightInPoints((short) 16); // 设置字体大小

} else if (sheetNo == 1) {

rowStylesetBorderBottom(BorderStyleTHIN); //下边框

rowStylesetBorderLeft(BorderStyleTHIN); //左边框

rowStylesetBorderRight(BorderStyleTHIN); //右边框

rowStylesetBorderTop(BorderStyleTHIN); //上边框

fontsetFontHeightInPoints((short) 22); // 设置字体大小

}

rowStylesetFont(font); // 为标题样式设置字体样式

return rowStyle;

}

/

创建样式

/

private static CellStyle createHeadCellStyle(CellStyle rowStyle, WriteSheetHolder writeSheetHolder,int sheetNo) {

rowStylesetAlignment(HorizontalAlignmentCENTER); //水平居中

rowStylesetVerticalAlignment(VerticalAlignmentCENTER); //垂直对齐

Font font = writeSheetHoldergetSheet()getWorkbook()createFont(); // 创建字体样式

fontsetFontName("宋体"); // 设置字体类型

if (sheetNo == 0) {

fontsetFontHeightInPoints((short) 12); // 设置字体大小

} else if (sheetNo == 1) {

rowStylesetBorderBottom(BorderStyleTHIN); //下边框

rowStylesetBorderLeft(BorderStyleTHIN); //左边框

rowStylesetBorderRight(BorderStyleTHIN); //右边框

rowStylesetBorderTop(BorderStyleTHIN); //上边框

fontsetFontHeightInPoints((short) 15); // 设置字体大小

}

rowStylesetFont(font); // 为标题样式设置字体样式

return rowStyle;

}

/

创建内容样式

/

private static CellStyle createContentCellStyle(CellStyle rowStyle, WriteSheetHolder writeSheetHolder,int contentType) {

rowStylesetVerticalAlignment(VerticalAlignmentCENTER);// 垂直居中

Font font = writeSheetHoldergetSheet()getWorkbook()createFont(); // 创建字体样式

fontsetFontName("宋体"); // 设置字体类型

fontsetFontHeightInPoints((short) 10);

rowStylesetFont(font);

switch (contentType) {

case 1:

rowStylesetAlignment(HorizontalAlignmentLEFT);// 从左边对齐

rowStylesetBorderBottom(BorderStyleTHIN); //下边框

rowStylesetBorderLeft(BorderStyleTHIN); //左边框

rowStylesetBorderRight(BorderStyleTHIN); //右边框

rowStylesetBorderTop(BorderStyleTHIN); //上边框

break;

case 2:

rowStylesetWrapText(true);// 设置自动换行

rowStylesetAlignment(HorizontalAlignmentCENTER);// 居中对齐

rowStylesetBorderBottom(BorderStyleTHIN); //下边框

rowStylesetBorderLeft(BorderStyleTHIN); //左边框

rowStylesetBorderRight(BorderStyleTHIN); //右边框

rowStylesetBorderTop(BorderStyleTHIN); //上边框

break;

case 3:

rowStylesetAlignment(HorizontalAlignmentCENTER);// 居中对齐;

rowStylesetBorderBottom(BorderStyleTHIN); //下边框

break;

case 4:

rowStylesetAlignment(HorizontalAlignmentLEFT);// 从左边对齐

break;

}

return rowStyle;

}

}

4合并单元格策略

EasyExcel 适用于简单数据的导入导出,现阶段EasyExcel 不支持读取,对导出Excel样式、 读写规则要求严格的请使用POI!!!

参考:

>

1、在VBA中环境中

获取最后一行有数据的单元格的行号的代码如下

dim i as long

i=sheet1range("a65536")end(xlup)row

获取最后一列有数据的单元格的列号的代码如下

dim i as long

i=sheet1range("iv1")end(xlleft)column

2、想知道表格最多有多少行,在a1单元格输入公式

=countblack(b:b)

想知道表格最多有多少列,在a1单元格输入公式

=countblack(2:2)

3、在工作表中,想取得一列或一行中最后一个有数据的单元格的行号或列号

如果单元格是连续的,中间没有空单元格,可以输入公式=counta(a:a)或=counta(1:1)

如果单元格区域中间有空单元格,可以输入公式,然后按下Ctrl+Shift+Enter键结束公

式编辑

=max(if(a1:a20000="",0,row(a1:a20000))

=max(if(1:1="",0,column(1:1))

1userModel模式

一种是使用最多的,像用的HSSFWorkBook、XSSFWorkBook、SXSSFWorkBook,这里我们称它为(也是内存消耗较大的模式)。为什么内存占用大呢?直接看读取源码,拿XSSFWorkbook加载为例,最终会调用这个方法:

这里就可以看到,会一直读流,每行都会生成一个对象,加载到zipEntries中去,这就是内存占用大的根本原因。

2eventModel模式

也就是SAX模式,easyexcel就是重写了poi的这个方法,达到更小的内存占用。通过将流一行行的读取,加载到内存,达到节约内存的目的。

XlsxSaxAnalyser将数据读取成inputStream流,缓存到了sheetMap

拿到一行数据后,会去调用dealData方法,dealData方法会去调用之初始化的监听器,执行业务处理,readListenerinvoke方法。

apache

pomxml

优点:可以写非常大的数据量,比如100w或者更多,写数据更快,占用内存更少

原理:

API文档 >

不会。EasyExcel在写入文件时不会锁住文件,也不会限制其他程序读取或写入该文件。EasyExcel在写入文件时不会锁定文件。它能够在写入期间打开文件,写入数据后关闭文件。因此,在文件在打开的情况下,可以通过EasyExcel向其写入数据。但需要注意,如果在进行数据写入时另一个程序正尝试打开相同的文件,则可能会出现冲突,可能造成数据丢失或文件损坏。

easyexcel合并单元格导出内存溢出是一个比较常见的问题,主要是因为在合并单元格的时候,由于数据量太大,导致内存溢出。解决这个问题的方法有:1、减少合并单元格的数量;2、优化excel文件,减少数据量;3、更换更高配置的电脑,提高内存容量;4、使用更高版本的excel,支持更大的数据量。总之,您可以根据自己的实际情况,选择合适的解决方案来解决这个问题。

以上就是关于easyexcel横竖不固定如何写入全部的内容,包括:easyexcel横竖不固定如何写入、EasyExcel 官方文档总结、Excel 如何获取EXCEL 有数据区域的最大行数等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/9325673.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-27
下一篇2023-04-27

发表评论

登录后才能评论

评论列表(0条)

    保存