参考:
http://blog.csdn.net/wutbiao/article/details/8696446
项目中需求:
将12个excel文件合并为一个总excel文件。首先想的思路是读取每个excel文件的sheet然后再copy到总excel文件里,查阅了前辈写的POI工具类,最后生成成功。但逐次打开12个excle文件效率很低,耗时9s,决定换其他思路开发。现将此工具类代码暂放,以后再学习使用。
import java.util.Iterator;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class POIUtils {
public class XSSFDateUtil extends DateUtil {
}
public static void copyCellStyle(XSSFCellStyle fromStyle, XSSFCellStyle toStyle) {
toStyle.cloneStyleFrom(fromStyle);//此一行代码搞定
//下面统统不用
/*
//对齐方式
toStyle.setAlignment(fromStyle.getAlignment());
//边框和边框颜色
toStyle.setBorderBottom(fromStyle.getBorderBottom());
toStyle.setBorderLeft(fromStyle.getBorderLeft());
toStyle.setBorderRight(fromStyle.getBorderRight());
toStyle.setBorderTop(fromStyle.getBorderTop());
toStyle.setTopBorderColor(fromStyle.getTopBorderColor());
toStyle.setBottomBorderColor(fromStyle.getBottomBorderColor());
toStyle.setRightBorderColor(fromStyle.getRightBorderColor());
toStyle.setLeftBorderColor(fromStyle.getLeftBorderColor());
//背景和前景
//toStyle.setFillPattern(fromStyle.getFillPattern()); //填充图案,不起作用,转为黑色
toStyle.setFillBackgroundColor(fromStyle.getFillBackgroundColor()); //不起作用
toStyle.setFillForegroundColor(fromStyle.getFillForegroundColor());
toStyle.setDataFormat(fromStyle.getDataFormat()); //数据格式
//toStyle.setFont(fromStyle.getFont()); //不起作用
toStyle.setHidden(fromStyle.getHidden());
toStyle.setIndention(fromStyle.getIndention());//首行缩进
toStyle.setLocked(fromStyle.getLocked());
toStyle.setRotation(fromStyle.getRotation());//旋转
toStyle.setVerticalAlignment(fromStyle.getVerticalAlignment()); //垂直对齐
toStyle.setWrapText(fromStyle.getWrapText()); //文本换行
*/
}
public static void mergeSheetAllRegion(XSSFSheet fromSheet, XSSFSheet toSheet) {//合并单元格
int num = fromSheet.getNumMergedRegions();
CellRangeAddress cellR = null;
for (int i = 0; i < num; i++) {
cellR = fromSheet.getMergedRegion(i);
toSheet.addMergedRegion(cellR);
}
}
public static void copyCell(XSSFWorkbook wb,XSSFCell fromCell, XSSFCell toCell) {
XSSFCellStyle newstyle=wb.createCellStyle();
copyCellStyle(fromCell.getCellStyle(), newstyle);
//toCell.setEncoding(fromCell.getEncoding());
//样式
toCell.setCellStyle(newstyle);
if (fromCell.getCellComment() != null) {
toCell.setCellComment(fromCell.getCellComment());
}
// 不同数据类型处理
int fromCellType = fromCell.getCellType();
toCell.setCellType(fromCellType);
if (fromCellType == XSSFCell.CELL_TYPE_NUMERIC) {
if (XSSFDateUtil.isCellDateFormatted(fromCell)) {
toCell.setCellValue(fromCell.getDateCellValue());
} else {
toCell.setCellValue(fromCell.getNumericCellValue());
}
} else if (fromCellType == XSSFCell.CELL_TYPE_STRING) {
toCell.setCellValue(fromCell.getRichStringCellValue());
} else if (fromCellType == XSSFCell.CELL_TYPE_BLANK) {
// nothing21
} else if (fromCellType == XSSFCell.CELL_TYPE_BOOLEAN) {
toCell.setCellValue(fromCell.getBooleanCellValue());
} else if (fromCellType == XSSFCell.CELL_TYPE_ERROR) {
toCell.setCellErrorValue(fromCell.getErrorCellValue());
} else if (fromCellType == XSSFCell.CELL_TYPE_FORMULA) {
toCell.setCellFormula(fromCell.getCellFormula());
} else { // nothing29
}
}
public static void copyRow(XSSFWorkbook wb,XSSFRow oldRow,XSSFRow toRow){
toRow.setHeight(oldRow.getHeight());
for (Iterator cellIt = oldRow.cellIterator(); cellIt.hasNext();) {
XSSFCell tmpCell = (XSSFCell) cellIt.next();
XSSFCell newCell = toRow.createCell(tmpCell.getColumnIndex());
copyCell(wb,tmpCell, newCell);
}
}
public static void copySheet(XSSFWorkbook wb,XSSFSheet fromSheet, XSSFSheet toSheet) {
mergeSheetAllRegion(fromSheet, toSheet);
//设置列宽
for(int i=0;i<=fromSheet.getRow(fromSheet.getFirstRowNum()).getLastCellNum();i++){
toSheet.setColumnWidth(i,fromSheet.getColumnWidth(i));
}
for (Iterator rowIt = fromSheet.rowIterator(); rowIt.hasNext();) {
XSSFRow oldRow = (XSSFRow) rowIt.next();
XSSFRow newRow = toSheet.createRow(oldRow.getRowNum());
copyRow(wb,oldRow,newRow);
}
}
}
业务层处理:
//将所有类型的尽调excel文件合并成一个excel文件
XSSFWorkbook newExcelCreat = new XSSFWorkbook();
for(String fromExcelName:fileNameList) {//遍历每个源excel文件,fileNameList为源文件的名称集合
InputStream in = new FileInputStream(tempUrl+ File.separator +fromExcelName);
XSSFWorkbook fromExcel = new XSSFWorkbook(in);
for(int i = 0; i < fromExcel.getNumberOfSheets(); i++) {//遍历每个sheet
XSSFSheet oldSheet = fromExcel.getSheetAt(i);
XSSFSheet newSheet = newExcelCreat.createSheet(oldSheet.getSheetName());
POIUtils.copySheet(newExcelCreat, oldSheet, newSheet);
}
}
String allFileName=tempUrl+File.separator+"总文件_"+format.format(new Date())+".xlsx";
FileOutputStream fileOut = new FileOutputStream(allFileName);
newExcelCreat.write(fileOut);
fileOut.flush();
fileOut.close();
//删除各个源文件
for(String fromExcelName:fileNameList) {//遍历每个源excel文件
File file=new File(tempUrl+File.separator+fromExcelName);
if(file.exists()){
file.delete();
}
}
2020.05.14更新博文
首先不好意思,现在才补充当时的另外一种实现思路。
因为年代久远,翻了下以前的代码,不知道当时的逻辑是不是解决了效率的问题,各位同学暂且试一下吧。
思路:
以上弃用的逻辑是遍历读取每个源excel文件,这样肯定耗时。以下的逻辑是只打开读取一次excel源文件,然后将数据塞入,再写出来。
1.首先定义一个总Excel的模板:allFiles.xlsx,里面每个sheet名字事先定义好,每个sheet里的内容也和各自对应的子Excel文件内容对应好。
2.拿到业务数据,遍历每条业务记录,根据目标记录的业务类型+在allFiles.xlsx中对应的sheet,调用各自业务的’下载生成Excel’方法,各自业务操作时处理的都是同一个对象XSSFWorkbook
3.最后将XSSFWorkbook对象写出
代码如下:
//1.拿到目标业务数据,封装ddType tableId
if (fileList != null && fileList.size() > 0) {
for (int i = 0; i < fileList.size(); i++) {
String ddType = fileList.get(i).getProfileType();
String tableId = fileList.get(i).getCognateTableId();
Map map=Maps.newHashMap();
map.put("ddType", ddType);//ddType:业务类型
map.put("tableId", tableId);//tableId:数据库表某条记录的主键id
mapList.add(i,map);
}
}
...
//2.遍历每条记录,根据不同的业务类型进行处理
if (mapList != null && mapList.size() > 0) {
//2-1.指定总excel的模板文件
String pathFrom = "/exceltemplates/allFiles.xlsx";
@SuppressWarnings("resource")
XSSFWorkbook fromWorkbook=new XSSFWorkbook(当前类.class.getResourceAsStream(pathFrom));
XSSFWorkbook toWorkbook=new XSSFWorkbook();
XSSFSheet fromSheet=null;
//2-2.遍历,开始生成excle文件的sheet页
Map map=new HashMap();
for (int i = 0; i < mapList.size(); i++) {
String ddType = mapList.get(i).get("ddType");
String tableId = mapList.get(i).get("tableId");
if (ddType.equals("A")) {
fromSheet=fromWorkbook.getSheetAt(0);
toWorkbook=xxxService.createFile(toWorkbook,fromSheet,tableId);
} else if (ddType.equals("B")) {
...
}
...//省略其他十几个业务类型
}
}
//3.输出总excle文件到tempurl下
String allDdFilesName = "总文件_" + format.format(new Date()) + ".xlsx";
FileOutputStream workbookOut = new FileOutputStream(tempUrl + allDdFilesName);
toWorkbook.write(workbookOut);
workbookOut.flush();
workbookOut.close();
...
其中某一个业务类的生成excle的方法实现:
public XSSFWorkbook createFile(XSSFWorkbook toWorkbook,XSSFSheet fromSheet,String tableId) throws IOException{
//1.对sheet进行命名
XSSFSheet toSheet=toWorkbook.createSheet();
int sheetAmount=toWorkbook.getNumberOfSheets();
int sheetMatchAmount=0;
for(int i=0;i paramMap = this.putData(true, tableId);
//4.填充数据
boolean isData=(boolean)paramMap.get("isData");
if (isData) {
toWorkbook=this.createFile(toWorkbook, toSheet, paramMap);
}
return toWorkbook;
}