JAVA导出EXCEL根据某列自定义单元格合并(easyExcel)
easyexcel
快速、简洁、解决大文件内存溢出的java处理Excel工具
项目地址:https://gitcode.com/gh_mirrors/ea/easyexcel
免费下载资源
·
1、合并单元格处理器
import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellRangeAddress; import org.springframework.util.ObjectUtils; import java.util.List; /** * 合并处理器 */ @Slf4j public class ExcelFillCellLineMergeHandler implements CellWriteHandler { private int[] mergeColumnIndex; private int mergeRowIndex; public ExcelFillCellLineMergeHandler() { } public ExcelFillCellLineMergeHandler(int mergeRowIndex, int[] mergeColumnIndex) { this.mergeRowIndex = mergeRowIndex; this.mergeColumnIndex = mergeColumnIndex; } @Override public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { } @Override public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { } @Override public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> list, Cell cell, Head head, Integer integer, Boolean aBoolean) { int curRowIndex = cell.getRowIndex(); //当前单元格的行数 int curColIndex = cell.getColumnIndex(); // 当前单元格的列数 if (curRowIndex > mergeRowIndex) { for (int i = 0; i < mergeColumnIndex.length; i++) { if (curColIndex == mergeColumnIndex[i]) { //单元格数据处理 mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex); break; } } } } /** * @description 当前单元格向上合并 * cell 当前单元格 * curRowIndex 当前行 * curColIndex 当前列 * @params [writeSheetHolder, cell, curRowIndex, curColIndex] * @return void * @throws */ private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) { //当前单元格中数据 Object curData = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue(); Object leftCellData = ""; Object preLeftCellData = ""; if (curRowIndex >1 && curColIndex >1) { Cell leftCell = cell.getSheet().getRow(curRowIndex).getCell(1); leftCellData = leftCell.getCellType() == CellType.STRING ? leftCell.getStringCellValue() : leftCell.getNumericCellValue(); } //获取当前单元格的上面一个单元格 Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex); if (curRowIndex >1 && curColIndex >1) { Cell preLeftCell = cell.getSheet().getRow(curRowIndex - 1).getCell(1); preLeftCellData = preLeftCell.getCellType() == CellType.STRING ? preLeftCell.getStringCellValue() : preLeftCell.getNumericCellValue(); } //获取当前单元格的上面一个单元格中的数据 Object preData = preCell.getCellType() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue(); // 将当前单元格数据与上一个单元格数据比较 if (leftCellData.equals(preLeftCellData) && preData.equals(curData)) { //获取当前sheet页 Sheet sheet = writeSheetHolder.getSheet(); //得到所有的合并单元格 List<CellRangeAddress> mergeRegions = sheet.getMergedRegions(); //是否合并 boolean isMerged = false; for (int i = 0; i < mergeRegions.size() && !isMerged; i++) { //CellRangeAddress POI合并单元格 //CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) //例子:CellRangeAddress(2, 6000, 3, 3); //第2行起 第6000行终止 第3列开始 第3列结束。 CellRangeAddress cellRangeAddr = mergeRegions.get(i); // cellRangeAddr.isInRange(int rowInd, int colInd)确定给定坐标是否在此范围的范围内。 // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元 if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) { sheet.removeMergedRegion(i); cellRangeAddr.setLastRow(curRowIndex); sheet.addMergedRegion(cellRangeAddr); isMerged = true; } } // 若上一个单元格未被合并,则新增合并单元 if (!isMerged) { CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex); sheet.addMergedRegion(cellRangeAddress); } } } }
2、单元格样式
import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.metadata.style.WriteFont; import org.apache.poi.ss.usermodel.*; public class StyleUtils { /** * 标题样式 * @return */ public static WriteCellStyle getHeadStyle(){ // 头的策略 WriteCellStyle headWriteCellStyle = new WriteCellStyle(); // 背景颜色 // headWriteCellStyle.setFillForegroundColor(IndexedColors.LIGHT_TURQUOISE1.getIndex()); // headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); // 字体 WriteFont headWriteFont = new WriteFont(); headWriteFont.setFontName("宋体");//设置字体名字 headWriteFont.setFontHeightInPoints((short)14);//设置字体大小 headWriteFont.setBold(true);//字体加粗 headWriteCellStyle.setWriteFont(headWriteFont); //在样式用应用设置的字体; // 样式 headWriteCellStyle.setBorderBottom(BorderStyle.THIN);//设置底边框; headWriteCellStyle.setBottomBorderColor((short) 0);//设置底边框颜色; headWriteCellStyle.setBorderLeft(BorderStyle.THIN); //设置左边框; headWriteCellStyle.setLeftBorderColor((short) 0);//设置左边框颜色; headWriteCellStyle.setBorderRight(BorderStyle.THIN);//设置右边框; headWriteCellStyle.setRightBorderColor((short) 0);//设置右边框颜色; headWriteCellStyle.setBorderTop(BorderStyle.THIN);//设置顶边框; headWriteCellStyle.setTopBorderColor((short) 0); //设置顶边框颜色; headWriteCellStyle.setWrapped(true); //设置自动换行; headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);//设置水平对齐的样式为居中对齐; headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //设置垂直对齐的样式为居中对齐; headWriteCellStyle.setShrinkToFit(true);//设置文本收缩至合适 return headWriteCellStyle; } /** * 内容样式 * @return */ public static WriteCellStyle getContentStyle(){ // 内容的策略 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); // 背景绿色 // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定 // contentWriteCellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex()); // contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); // 设置字体 WriteFont contentWriteFont = new WriteFont(); contentWriteFont.setFontHeightInPoints((short) 12);//设置字体大小 contentWriteFont.setFontName("宋体"); //设置字体名字 contentWriteCellStyle.setWriteFont(contentWriteFont);//在样式用应用设置的字体; //设置样式; contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);//设置底边框; contentWriteCellStyle.setBottomBorderColor((short) 0);//设置底边框颜色; contentWriteCellStyle.setBorderLeft(BorderStyle.THIN); //设置左边框; contentWriteCellStyle.setLeftBorderColor((short) 0);//设置左边框颜色; contentWriteCellStyle.setBorderRight(BorderStyle.THIN);//设置右边框; contentWriteCellStyle.setRightBorderColor((short) 0);//设置右边框颜色; contentWriteCellStyle.setBorderTop(BorderStyle.THIN);//设置顶边框; contentWriteCellStyle.setTopBorderColor((short) 0); ///设置顶边框颜色; contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);// 水平居中 contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中 contentWriteCellStyle.setWrapped(true); //设置自动换行; // contentWriteCellStyle.setShrinkToFit(true);//设置文本收缩至合适 return contentWriteCellStyle; } }
import java.util.List; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.util.ListUtils; import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.style.AbstractCellStyleStrategy; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import org.apache.commons.collections4.CollectionUtils; @Getter @Setter @EqualsAndHashCode public class HorizontalCellStyleStrategy extends AbstractCellStyleStrategy { private WriteCellStyle headWriteCellStyle; private List<WriteCellStyle> contentWriteCellStyleList; public HorizontalCellStyleStrategy() { } public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle, List<WriteCellStyle> contentWriteCellStyleList) { this.headWriteCellStyle = headWriteCellStyle; this.contentWriteCellStyleList = contentWriteCellStyleList; } public HorizontalCellStyleStrategy(WriteCellStyle headWriteCellStyle, WriteCellStyle contentWriteCellStyle) { this.headWriteCellStyle = headWriteCellStyle; if (contentWriteCellStyle != null) { this.contentWriteCellStyleList = ListUtils.newArrayList(contentWriteCellStyle); } } @Override protected void setHeadCellStyle(CellWriteHandlerContext context) { if (stopProcessing(context) || headWriteCellStyle == null) { return; } WriteCellData<?> cellData = context.getFirstCellData(); WriteCellStyle.merge(headWriteCellStyle, cellData.getOrCreateStyle()); } @Override protected void setContentCellStyle(CellWriteHandlerContext context) { if (stopProcessing(context) || CollectionUtils.isEmpty(contentWriteCellStyleList)) { return; } WriteCellData<?> cellData = context.getFirstCellData(); if (context.getRelativeRowIndex() == null || context.getRelativeRowIndex() <= 0) { WriteCellStyle.merge(contentWriteCellStyleList.get(0), cellData.getOrCreateStyle()); } else { WriteCellStyle.merge( contentWriteCellStyleList.get(context.getRelativeRowIndex() % contentWriteCellStyleList.size()), cellData.getOrCreateStyle()); } } protected boolean stopProcessing(CellWriteHandlerContext context) { return context.getFirstCellData() == null; } }
3、导出EXCEL
示例:根据第一列,合并0-7列上下临近单元格相同的数据
List<ExportDto> exportDtoVos = new ArrayList<ExportDto>(); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding(Charsets.UTF_8.name()); String yyyyMMddHHmmss = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); String fileName = URLEncoder.encode(yyyyMMddHHmmss+"_flow", Charsets.UTF_8.name()); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); // 设置单元格样式 HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(StyleUtils.getHeadStyle(), StyleUtils.getContentStyle()); int[] mergeColumeIndex = {0,1,2,3,4,5,6,7}; int mergeRowIndex = 1; EasyExcel.write(response.getOutputStream(),ExportDto.class).registerWriteHandler(new ExcelFillCellLineMergeHandler(mergeRowIndex, mergeColumeIndex)) .registerWriteHandler(horizontalCellStyleStrategy).sheet("sheet1").doWrite(exportDtoVos);
效果图:
GitHub 加速计划 / ea / easyexcel
16
5
下载
快速、简洁、解决大文件内存溢出的java处理Excel工具
最近提交(Master分支:5 个月前 )
c42183df
Bugfix 5 个月前
efa7dff6 * 重新加回 `commons-io`
5 个月前
更多推荐
已为社区贡献2条内容
所有评论(0)