资讯专栏INFORMATION COLUMN

poi操作excel,复制sheet,复制行,复制单元格,复制style

Carl / 952人阅读

摘要:缘起最近写一个程序,需要操作,遂稍微深入了解下从操作,在需要复制一个的时候,找到三份资料操作,复制,复制行,复制单元格使用操作拷贝导出时设置单元格类型为数值类型问题如果在一个的时候,需要把样式也过去,怎么办,会怎样呢如果像第三份资料中所做,

缘起

最近写一个程序,需要操作excel,遂稍微深入了解下poi从操作,

在需要复制一个sheet的时候,找到三份资料

poi操作excel,复制sheet,复制行,复制单元格

使用POI操作Excel:Sheet拷贝

POI导出Excel时设置单元格类型为数值类型

问题

如果在copy一个cell的时候,需要把样式也copy过去,怎么办,会怎样呢?

如果像第三份资料中所做,会创建太多的style,而这些style又是重复的 ,毫无意义,数据多了还报错

如果像第二份资料中所做,前提是同一个workbook,也不存在copy style 的问题,只不过是不同的cell引用相同的style而已

如果像第一份资料所做,他自己都注释掉了,因为报错

如何解决 思路

相同的book中,不需要copy

不同的book中,styleTable应该不一致,copy的时候,在目标book中创建,最后返回两个book中的style index的映射关系

代码

暂时没测试过,写出来就迫不及待要分享了。

import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 提供常用excel操作
*
    *
  • *
*/ public class ExcelOperationUtil { private static Logger logger = LoggerFactory.getLogger(ExcelOperationUtil.class); /** * 把一个excel中的styleTable复制到另一个excel中 * @return StyleMapping 两个文件中styleTable的映射关系 * @see StyleMapping */ public static StyleMapping copyCellStyle(Workbook srcBook, Workbook desBook){ if (null == srcBook || null == desBook) { throw new ExcelExecption("源excel 或 目标excel 不存在"); } if (srcBook.equals(desBook)) { throw new ExcelExecption("不要使用此方法在同一个文件中copy style"); } logger.debug("src中style number:{}, des中style number:{}", srcBook.getNumCellStyles(), desBook.getNumCellStyles()); short[] src2des = new short[srcBook.getNumCellStyles()]; short[] des2src = new short[desBook.getNumCellStyles() + srcBook.getNumCellStyles()]; for(short i=0;i= this.des2srcIndexMapping.length) { throw new ExcelExecption("索引越界:源文件styleNum=" + this.des2srcIndexMapping.length + " 访问位置=" + desIndex); } return this.des2srcIndexMapping[desIndex]; } /** * 根据源文件的style的index,获取目标文件的style的index * @param srcIndex 源excel中style的index * @return desIndex 目标excel中style的index */ public short desIndex(short srcIndex) { if (srcIndex < 0 || srcIndex >= this.src2desIndexMapping.length) { throw new ExcelExecption("索引越界:源文件styleNum=" + this.src2desIndexMapping.length + " 访问位置=" + srcIndex); } return this.src2desIndexMapping[srcIndex]; } } }
完善代码

工作忙了几天,终于可以回头把这件事结束掉了

        
            org.apache.poi
            poi
            3.17
        
        
            org.apache.poi
            poi-ooxml
            3.17
        
        
            org.apache.poi
            poi-scratchpad
            3.17
        

为啥贴出依赖?因为我一开始用3.8版本,如果是xls就可以,如果是xlsx死活不行,最后,换掉版本就可以了。

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;

/**
 * 提供常用excel操作
*
    *
  • *
*/ public class ExcelOperationUtil { private static Logger logger = LoggerFactory.getLogger(ExcelOperationUtil.class); /** * sheet 复制,复制数据、如果同一个文件,复制样式,不同文件则只复制数据
* 如果是同book中复制,建议使用workbook中的cloneSheet()方法
* *
建议用于 不同book间只复制数据 * */ public static void copySheet(Sheet srcSheet, Sheet desSheet) { copySheet(srcSheet, desSheet, true, true, null); } /** * sheet 复制,如果同一个文件,复制样式,不同文件则不复制
* *
建议用于 同book中,只复制样式,不复制数据
* eg: copySheet(srcSheet, desSheet, false) * * @param copyValueFlag 控制是否复制数据 */ public static void copySheet(Sheet srcSheet, Sheet desSheet, boolean copyValueFlag) { copySheet(srcSheet, desSheet, copyValueFlag, true, null); } /** * sheet 复制,复制数据、样式
* *
建议用于 不同book间复制,同时复制数据和样式
* eg: copySheet(srcSheet, desSheet, mapping) * * @param mapping 不同文件间复制时,如果要复制样式,必传,否则不复制样式 */ public static void copySheet(Sheet srcSheet, Sheet desSheet, StyleMapping mapping) { copySheet(srcSheet, desSheet, true, true, mapping); } /** * sheet 复制,复制数据
* *
建议用于 同book中,只复制数据,不复制样式
* eg: copySheet(srcSheet, desSheet, false, null) * * @param srcSheet * @param desSheet * @param copyStyleFlag * @param mapping */ public static void copySheet(Sheet srcSheet, Sheet desSheet, boolean copyStyleFlag, StyleMapping mapping) { copySheet(srcSheet, desSheet, true, copyStyleFlag, mapping); } /** * sheet 复制, 灵活控制是否控制数据、样式
* *
不建议直接使用 * * @param copyValueFlag 控制是否复制数据 * @param copyStyleFlag 控制是否复制样式 * @param mapping 不同book中复制样式时,必传 */ public static void copySheet(Sheet srcSheet, Sheet desSheet, boolean copyValueFlag, boolean copyStyleFlag, StyleMapping mapping) { if (srcSheet.getWorkbook() == desSheet.getWorkbook()) { logger.warn("统一workbook内复制sheet建议使用 workbook的cloneSheet方法"); } //合并区域处理 copyMergedRegion(srcSheet, desSheet); //行复制 Iterator rowIterator = srcSheet.rowIterator(); int areadlyColunm = 0; while (rowIterator.hasNext()) { Row srcRow = rowIterator.next(); Row desRow = desSheet.createRow(srcRow.getRowNum()); copyRow(srcRow, desRow, copyValueFlag, copyStyleFlag, mapping); //调整列宽(增量调整) if (srcRow.getPhysicalNumberOfCells() > areadlyColunm) { for (int i = areadlyColunm; i < srcRow.getPhysicalNumberOfCells(); i++) { desSheet.setColumnWidth(i, srcSheet.getColumnWidth(i)); } areadlyColunm = srcRow.getPhysicalNumberOfCells(); } } } /** * 复制行 */ public static void copyRow(Row srcRow, Row desRow) { copyRow(srcRow, desRow, true, true, null); } /** * 复制行 */ public static void copyRow(Row srcRow, Row desRow, boolean copyValueFlag) { copyRow(srcRow, desRow, copyValueFlag, true, null); } /** * 复制行 */ public static void copyRow(Row srcRow, Row desRow, StyleMapping mapping) { copyRow(srcRow, desRow, true, true, mapping); } /** * 复制行 */ public static void copyRow(Row srcRow, Row desRow, boolean copyStyleFlag, StyleMapping mapping) { copyRow(srcRow, desRow, true, copyStyleFlag, mapping); } /** * 复制行 */ public static void copyRow(Row srcRow, Row desRow,boolean copyValueFlag, boolean copyStyleFlag, StyleMapping mapping) { Iterator it = srcRow.cellIterator(); while (it.hasNext()) { Cell srcCell = it.next(); Cell desCell = desRow.createCell(srcCell.getColumnIndex()); copyCell(srcCell, desCell, copyValueFlag, copyStyleFlag, mapping); } } /** * 复制区域(合并单元格) */ public static void copyMergedRegion(Sheet srcSheet, Sheet desSheet) { int sheetMergerCount = srcSheet.getNumMergedRegions(); for (int i = 0; i < sheetMergerCount; i++) { desSheet.addMergedRegion(srcSheet.getMergedRegion(i)); CellRangeAddress cellRangeAddress = srcSheet.getMergedRegion(i); } } /** * 复制单元格,复制数据,如果同文件,复制样式,不同文件则不复制样式 */ public static void copyCell(Cell srcCell, Cell desCell) { copyCell(srcCell, desCell, true, true,null); } /** * 复制单元格, 如果同文件,复制样式,不同文件则不复制样式 * @param copyValueFlag 控制是否复制数据 */ public static void copyCell(Cell srcCell, Cell desCell, boolean copyValueFlag) { copyCell(srcCell, desCell, copyValueFlag, true, null); } /** * 复制单元格,复制数据,复制样式 * @param mapping 不同文件间复制时,如果要复制样式,必传,否则不复制样式 */ public static void copyCell(Cell srcCell, Cell desCell, StyleMapping mapping) { copyCell(srcCell, desCell, true, true, mapping); } /** * 复制单元格,复制数据 * @param copyStyleFlag 控制是否复制样式 * @param mapping 不同文件间复制时,如果要复制样式,必传,否则不复制样式 */ public static void copyCell(Cell srcCell, Cell desCell, boolean copyStyleFlag, StyleMapping mapping) { copyCell(srcCell, desCell, true, copyStyleFlag, mapping); } /** * 复制单元格 * @param copyValueFlag 控制是否复制单元格的内容 * @param copyStyleFlag 控制是否复制样式 * @param mapping 不同文件间复制时,如果需要连带样式复制,必传,否则不复制样式 */ public static void copyCell(Cell srcCell, Cell desCell, boolean copyValueFlag, boolean copyStyleFlag, StyleMapping mapping) { Workbook srcBook = srcCell.getSheet().getWorkbook(); Workbook desBook = desCell.getSheet().getWorkbook(); //复制样式 //如果是同一个excel文件内,连带样式一起复制 if (srcBook == desBook && copyStyleFlag) { //同文件,复制引用 desCell.setCellStyle(srcCell.getCellStyle()); } else if (copyStyleFlag) { //不同文件,通过映射关系复制 if (null != mapping) { short desIndex = mapping.desIndex(srcCell.getCellStyle().getIndex()); desCell.setCellStyle(desBook.getCellStyleAt(desIndex)); } } //复制评论 if (srcCell.getCellComment() != null) { desCell.setCellComment(srcCell.getCellComment()); } //复制内容 desCell.setCellType(srcCell.getCellTypeEnum()); if (copyValueFlag) { switch (srcCell.getCellTypeEnum()) { case STRING: desCell.setCellValue(srcCell.getStringCellValue()); break; case NUMERIC: desCell.setCellValue(srcCell.getNumericCellValue()); break; case FORMULA: desCell.setCellFormula(srcCell.getCellFormula()); break; case BOOLEAN: desCell.setCellValue(srcCell.getBooleanCellValue()); break; case ERROR: desCell.setCellValue(srcCell.getErrorCellValue()); break; case BLANK: //nothing to do break; default: break; } } } /** * 把一个excel中的styleTable复制到另一个excel中
* 如果是同一个excel文件,就不用复制styleTable了 * @return StyleMapping 两个文件中styleTable的映射关系 * @see StyleMapping */ public static StyleMapping copyCellStyle(Workbook srcBook, Workbook desBook){ if (null == srcBook || null == desBook) { throw new ExcelException("源excel 或 目标excel 不存在"); } if (srcBook.equals(desBook)) { throw new ExcelException("不要使用此方法在同一个文件中copy style,同一个excel中复制sheet不需要copy Style"); } if ((srcBook instanceof HSSFWorkbook && desBook instanceof XSSFWorkbook) || (srcBook instanceof XSSFWorkbook && desBook instanceof HSSFWorkbook)) { throw new ExcelException("不支持在不同的版本的excel中复制样式)"); } logger.debug("src中style number:{}, des中style number:{}", srcBook.getNumCellStyles(), desBook.getNumCellStyles()); short[] src2des = new short[srcBook.getNumCellStyles()]; short[] des2src = new short[desBook.getNumCellStyles() + srcBook.getNumCellStyles()]; for(short i=0;i= this.des2srcIndexMapping.length) { throw new ExcelException("索引越界:源文件styleNum=" + this.des2srcIndexMapping.length + " 访问位置=" + desIndex); } return this.des2srcIndexMapping[desIndex]; } /** * 根据源文件的style的index,获取目标文件的style的index * @param srcIndex 源excel中style的index * @return desIndex 目标excel中style的index */ public short desIndex(short srcIndex) { if (srcIndex < 0 || srcIndex >= this.src2desIndexMapping.length) { throw new ExcelException("索引越界:源文件styleNum=" + this.src2desIndexMapping.length + " 访问位置=" + srcIndex); } return this.src2desIndexMapping[srcIndex]; } } }

一个自定义异常类

public class ExcelException extends RuntimeException {

    public ExcelException() {
    }

    public ExcelException(String message) {
        super(message);
    }

    public ExcelException(String message, Throwable cause) {
        super(message, cause);
    }

    public ExcelException(Throwable cause) {
        super(cause);
    }

    public ExcelException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71194.html

相关文章

  • 基于POIExcel工具类

    摘要:一般订单打印纸高度毫米字母或半角字符判断是否为全角全角符号及中文连续出现,认为是单词组成部分的字符和间单页的票据右端联页宽占用的宽度回退一行每减一次少一行实际高度的距离补足行高拉高的行内容要调整使用靠上对齐补充 import org.apache.poi.hssf.usermodel.*; import org.apache.poi.hssf.util.Region; import ...

    sevi_stuo 评论0 收藏0
  • 从零开始,SpreadJS新人学习笔记【第5周】

    摘要:复制粘贴单元格格式和单元格类型本周,让我们一起来学习的复制粘贴单元格格式和单元格类型,希望我的学习笔记能够帮助你们,从零开始学习,并逐步精通。 复制粘贴、单元格格式和单元格类型 本周,让我们一起来学习SpreadJS 的复制粘贴、单元格格式和单元格类型,希望我的学习笔记能够帮助你们,从零开始学习 SpreadJS,并逐步精通。 在此前的学习笔记中,相信大家已经学会并熟练掌握了Sprea...

    shadowbook 评论0 收藏0
  • 使用ApachePOI生成XLSXExcel文档大数据量导出

    摘要:最近在做使用进行大数据量导出,现在把其整理成工具类供大家参考。版本增加了前缀为相关的类,主要用于大数据量的写入与读取。 最近在做使用POI进行大数据量导出,现在把其整理成工具类供大家参考。Apache POI 3.8版本增加了前缀为SXSSF相关的类,主要用于大数据量的写入与读取。关于ApachePOI导出Excel基本的使用我这里就不详解了,具体参考: Apache POI官方网站...

    Shihira 评论0 收藏0
  • python 中 xlwt 操作excel

    摘要:中使用操作非常方和使用调框架相比这就是天堂啊一安装模块二简单使用导入模块创建对象创建工作表往表中写内容第一各参数行第二个参数列第三个参数内容保存表为在中使用操作在创建对象的时候就需要写好表名创建对象完成后这个表就已经存在但是使用需要在最后 python中使用xlwt操作excel非常方,和Java使用调框架apache poi相比这就是天堂啊一.安装xlwt模块 pip3 instal...

    张巨伟 评论0 收藏0

发表评论

0条评论

Carl

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<