easypoi 如何合并相同的列_POI Excel 合并数据相同的行

该博客介绍如何使用easypoi库在Java中创建Excel,并根据内容合并相同的列。通过创建Workbook,设置Sheet,填充标题和数据,然后检查并合并具有相同值的单元格,实现数据的整理和格式化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

importjava.io.File;importjava.io.FileOutputStream;importjava.io.IOException;importjava.util.ArrayList;importjava.util.Date;importjava.util.HashMap;importjava.util.Iterator;importjava.util.List;importjava.util.Map;importorg.apache.poi.ss.usermodel.Cell;importorg.apache.poi.ss.usermodel.Row;importorg.apache.poi.ss.usermodel.Sheet;importorg.apache.poi.ss.usermodel.Workbook;importorg.apache.poi.ss.util.CellRangeAddress;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;public classDemo {/***@paramtitle 标题集合 tilte的长度应该与list中的model的属性个数一致

*@parammaps 内容集合

*@parammergeIndex 合并单元格的列*/

public static String createExcel(String[] title, Map>> maps, int[] mergeIndex){if (title.length==0){return null;

}/*初始化excel模板*/Workbook workbook= newXSSFWorkbook();

Sheet sheet= null;int n = 0;for(Map.Entry>>entry : maps.entrySet()){try{

sheet=workbook.createSheet();

workbook.setSheetName(n, entry.getKey());

workbook.setSelectedTab(0);

}catch(Exception e){

e.printStackTrace();

}/*初始化head,填值标题行(第一行)*/Row row0= sheet.createRow(0);for(int i = 0; i

cell_1.setCellValue(title[i]);

}/*得到当前sheet下的数据集合*/List> list =entry.getValue();/*遍历该数据集合*/List poiModels = newArrayList();if(null!=workbook){

Iterator iterator=list.iterator();int index = 1;while(iterator.hasNext()){

Row row=sheet.createRow(index);/*取得当前这行的map,该map中以key,value的形式存着这一行值*/Map map = (Map)iterator.next();/*循环列数,给当前行塞值*/

for(int i = 0; i

String old= "";/*old存的是上一行统一位置的单元的值,第一行是最上一行了,所以从第二行开始记*/

if(index > 1){

old= poiModels.get(i)==null?"":poiModels.get(i).getContent();

}/*循环需要合并的列*/

for(int j = 0; j < mergeIndex.length; j++){if(index == 1){/*记录第一行的开始行和开始列*/PoiModel poiModel= newPoiModel();

poiModel.setOldContent(map.get(title[i]));

poiModel.setContent(map.get(title[i]));

poiModel.setRowIndex(1);

poiModel.setCellIndex(i);

poiModels.add(poiModel);break;

}else if(i > 0 && mergeIndex[j] == i){/*这边i>0也是因为第一列已经是最前一列了,只能从第二列开始*/

/*当前同一列的内容与上一行同一列不同时,把那以上的合并, 或者在当前元素一样的情况下,前一列的元素并不一样,这种情况也合并*/

/*如果不需要考虑当前行与上一行内容相同,但是它们的前一列内容不一样则不合并的情况,把下面条件中

||poiModels.get(i).getContent().equals(map.get(title[i])) && !poiModels.get(i - 1).getOldContent().equals(map.get(title[i-1]))去掉就行*/

if(!poiModels.get(i).getContent().equals(map.get(title[i])) || poiModels.get(i).getContent().equals(map.get(title[i]))

&& !poiModels.get(i - 1).getOldContent().equals(map.get(title[i-1]))){/*当前行的当前列与上一行的当前列的内容不一致时,则把当前行以上的合并*/CellRangeAddress cra=new CellRangeAddress(poiModels.get(i).getRowIndex(), index - 1, poiModels.get(i).getCellIndex(), poiModels.get(i).getCellIndex());//在sheet里增加合并单元格

sheet.addMergedRegion(cra);/*重新记录该列的内容为当前内容,行标记改为当前行标记,列标记则为当前列*/poiModels.get(i).setContent(map.get(title[i]));

poiModels.get(i).setRowIndex(index);

poiModels.get(i).setCellIndex(i);

}

}/*处理第一列的情况*/

if(mergeIndex[j] == i && i == 0 && !poiModels.get(i).getContent().equals(map.get(title[i]))){/*当前行的当前列与上一行的当前列的内容不一致时,则把当前行以上的合并*/CellRangeAddress cra=new CellRangeAddress(poiModels.get(i).getRowIndex(), index - 1, poiModels.get(i).getCellIndex(), poiModels.get(i).getCellIndex());//在sheet里增加合并单元格

sheet.addMergedRegion(cra);/*重新记录该列的内容为当前内容,行标记改为当前行标记*/poiModels.get(i).setContent(map.get(title[i]));

poiModels.get(i).setRowIndex(index);

poiModels.get(i).setCellIndex(i);

}/*最后一行没有后续的行与之比较,所有当到最后一行时则直接合并对应列的相同内容*/

if(mergeIndex[j] == i && index ==list.size()){

CellRangeAddress cra=newCellRangeAddress(poiModels.get(i).getRowIndex(), index, poiModels.get(i).getCellIndex(), poiModels.get(i).getCellIndex());//在sheet里增加合并单元格

sheet.addMergedRegion(cra);

}

}

Cell cell=row.createCell(i, Cell.CELL_TYPE_STRING);

cell.setCellValue(map.get(title[i]));/*在每一个单元格处理完成后,把这个单元格内容设置为old内容*/poiModels.get(i).setOldContent(old);

}

index++;

}

}

n++;

}/*生成临时文件*/FileOutputStream out= null;

String localPath= null;

File tempFile= null;

String fileName= String.valueOf(new Date().getTime()/1000);try{

tempFile= File.createTempFile(fileName, ".xlsx");

localPath=tempFile.getAbsolutePath();

out= newFileOutputStream(localPath);

workbook.write(out);

}catch(IOException e){

e.printStackTrace();

}finally{try{

out.flush();

out.close();

}catch(IOException e){

e.printStackTrace();

}

}returnlocalPath;

}public static void main(String[] args) throwsIOException{/*此处标题的数组则对应excel的标题*/String[] title= {"id","标题","描述","负责人","开始时间"};

List> list = newArrayList();/*这边是制造一些数据,注意每个list中map的key要和标题数组中的元素一致*/

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

HashMap map = newHashMap();if(i > 5){if(i<7){

map.put("id","333");

map.put("标题","mmmm");

}else{

map.put("id","333");

map.put("标题","aaaaa");

}

}else if (i >3){

map.put("id","222");

map.put("标题","哈哈哈哈");

}else if (i>1 && i<3){

map.put("id","222");

map.put("标题","hhhhhhhh");

}else{

map.put("id","222");

map.put("标题","bbbb");

}

map.put("描述","sssssss");

map.put("负责人","vvvvv");

map.put("开始时间","2017-02-27 11:20:26");

list.add(map);

}

Map>> map = newHashMap();

map.put("测试合并数据", list);

System.out.println(createExcel(title, map,new int[]{0,1,2}));

}

}

### 使用 EasyPOI 合并 Excel相同内容的单元格 为了实现合并具有相同内容的单元格,在使用 EasyPOI行数据导出时,可以采用特定的方式处理数据以及设置相应的属性。 #### 实体类定义 当定义用于导出的数据实体类时,可以通过 `@Excel` 和其他关联注解来指定的信息。对于需要合并的情况,通常会在父级对象上标注 `@ExcelCollection` 来表示一对多的关系[^1]: ```java import cn.afterturn.easypoi.excel.annotation.Excel; import cn.afterturn.easypoi.excel.annotation.ExcelCollection; public class ParentVO { @Excel(name = "Parent Name", mergeVertical = true, isMerge = true) private String parentName; @ExcelCollection(name="Children") private List<ChildVO> children; } ``` 这里的关键在于设置了 `mergeVertical=true` 及 `isMerge=true` 属性,这使得在同一内垂直方向上的重复项会被自动合并[^4]。 #### 导出配置与调用 创建一个简单的工具方法来进实际的文件导出工作,并确保传入正确的参数以便于控制输出格式。需要注意的是,当版本下只支持 `.xls` 文件格式下的此类操作[^2]: ```java import cn.afterturn.easypoi.poi.export.ExcelExportUtil; import org.apache.poi.hssf.usermodel.HSSFWorkbook; public Workbook exportData(List<?> list){ ExportParams params = new ExportParams(); params.setType(ExcelType.HSSF); // 设置为HSSF类型 return ExcelExportUtil.exportExcel(params, ParentVO.class, list); } ``` 上述代码片段展示了如何通过设定 `params.setType()` 方法指明要使用的 Excel 类型为 HSSF (即 .xls),从而允许后续进有效的单元格合并操作。 #### 完整示例流程 假设有一个场景是要展示多个学生及其所属班级信息,其中每个班只有一个班主任,则可以在对应的 VO 对象中加入合适的注释标记以达到预期效果: ```java // ClassVO.java import cn.afterturn.easypoi.excel.annotation.Excel; import java.util.List; public class ClassVO { @Excel(name = "Class Name", mergeVertical = true, isMerge = true) private String className; @ExcelCollection(name="Students") private List<StudentVO> students; } // StudentVO.java import cn.afterturn.easypoi.excel.annotation.Excel; public class StudentVO { @Excel(name = "Student Name") private String studentName; @Excel(name = "Age") private Integer age; } ``` 最后利用之提到过的 `exportData` 函数即可完成整个过程中的数据准备和最终文档生成的工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值