缘起
最近写一个程序,需要操作excel,遂稍微深入了解下poi从操作,
在需要复制一个sheet的时候,找到三份资料
问题
如果在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
//建立双向映射
CellStyle srcStyle = srcBook.getCellStyleAt(i);
CellStyle desStyle = desBook.createCellStyle();
src2des[srcStyle.getIndex()] = desStyle.getIndex();
des2src[desStyle.getIndex()] = srcStyle.getIndex();
//复制样式
desStyle.cloneStyleFrom(srcStyle);
}
return new StyleMapping(des2src, src2des);
}
/**
* 存放两个excel文件中的styleTable的映射关系,以便于在复制表格时,在目标文件中获取到对应的样式
*/
public static class StyleMapping {
/**
*
*/
private short[] des2srcIndexMapping;
/**
*
*/
private short[] src2desIndexMapping;
/**
* 不允许其他类创建此类型对象
*/
private StyleMapping() {
}
private StyleMapping(short[] des2srcIndexMapping, short[] src2desIndexMapping) {
this.des2srcIndexMapping = des2srcIndexMapping;
this.src2desIndexMapping = src2desIndexMapping;
}
public short srcIndex(short desIndex) {
if (desIndex < 0 || desIndex >= this.des2srcIndexMapping.length) {
throw new ExcelExecption("索引越界:源文件styleNum=" + this.des2srcIndexMapping.length + " 访问位置=" + desIndex);
}
return thi