经过研究和尝试,这里是我的解决方案。我已经通过Java 1.6和apache-poi 3.8进行了测试
在这里,我将不提供适用于我的解决方案,特别是在这种情况下,我将粘贴工作表和输入流列表(我要合并的不同工作簿)。
我的解决方案是一个合并的解决方案,我从这里合并了整个源代码,我想与所有人共享此代码,但都遇到了同样的问题。
import java.io.FileInputStream;import java.io.IOException;import java.util.List;import java.util.HashMap;import java.util.Map;import java.util.Set;import java.util.TreeSet;import org.apache.poi.ss.usermodel.Cell;import org.apache.poi.ss.usermodel.CellStyle;import org.apache.poi.ss.usermodel.Row;import org.apache.poi.ss.usermodel.Sheet;import org.apache.poi.ss.usermodel.Workbook;import org.apache.poi.ss.usermodel.WorkbookFactory;import org.apache.poi.ss.util.CellRangeAddress;public class CopySheets {public Workbook mergeExcelFiles(Workbook book, List<InputStream> inList) throws IOException { for (InputStream fin : inList) { Workbook b = WorkbookFactory.create(fin); for (int i = 0; i < b.getNumberOfSheets(); i++) { // not entering sheet name, because of duplicated names copySheets(book.createSheet(),b.getSheetAt(i)); } } return book;} public static void copySheets(Sheet newSheet, Sheet sheet){ copySheets(newSheet, sheet, true); } public static void copySheets(Sheet newSheet, Sheet sheet, boolean copyStyle){ int maxColumnNum = 0; Map<Integer, CellStyle> styleMap = (copyStyle) ? new HashMap<Integer, CellStyle>() : null; for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) { Row srcRow = sheet.getRow(i); Row destRow = newSheet.createRow(i); if (srcRow != null) { copyRow(sheet, newSheet, srcRow, destRow, styleMap); if (srcRow.getLastCellNum() > maxColumnNum) { maxColumnNum = srcRow.getLastCellNum(); } } } for (int i = 0; i <= maxColumnNum; i++) { newSheet.setColumnWidth(i, sheet.getColumnWidth(i)); } } public static void copyRow(Sheet srcSheet, Sheet destSheet, Row srcRow, Row destRow, Map<Integer, CellStyle> styleMap) { // manage a list of merged zone in order to not insert two times a merged zone Set<CellRangeAddressWrapper> mergedRegions = new TreeSet<CellRangeAddressWrapper>(); destRow.setHeight(srcRow.getHeight()); // reckoning delta rows int deltaRows = destRow.getRowNum()-srcRow.getRowNum(); // pour chaque row for (int j = srcRow.getFirstCellNum(); j <= srcRow.getLastCellNum(); j++) { Cell oldCell = srcRow.getCell(j); // ancienne cell Cell newCell = destRow.getCell(j); // new cellif (oldCell != null) { if (newCell == null) { newCell = destRow.createCell(j); } // copy chaque cell copyCell(oldCell, newCell, styleMap); // copy les informations de fusion entre les cellules //System.out.println("row num: " + srcRow.getRowNum() + " , col: " + (short)oldCell.getColumnIndex()); CellRangeAddress mergedRegion = getMergedRegion(srcSheet, srcRow.getRowNum(), (short)oldCell.getColumnIndex()); if (mergedRegion != null) { //System.out.println("Selected merged region: " + mergedRegion.toString()); CellRangeAddress newMergedRegion = new CellRangeAddress(mergedRegion.getFirstRow()+deltaRows, mergedRegion.getLastRow()+deltaRows, mergedRegion.getFirstColumn(), mergedRegion.getLastColumn()); //System.out.println("New merged region: " + newMergedRegion.toString()); CellRangeAddressWrapper wrapper = new CellRangeAddressWrapper(newMergedRegion); if (isNewMergedRegion(wrapper, mergedRegions)) {mergedRegions.add(wrapper);destSheet.addMergedRegion(wrapper.range); } } } } } public static void copyCell(Cell oldCell, Cell newCell, Map<Integer, CellStyle> styleMap) { if(styleMap != null) { if(oldCell.getSheet().getWorkbook() == newCell.getSheet().getWorkbook()){ newCell.setCellStyle(oldCell.getCellStyle()); } else{ int stHashCode = oldCell.getCellStyle().hashCode(); CellStyle newCellStyle = styleMap.get(stHashCode); if(newCellStyle == null){ newCellStyle = newCell.getSheet().getWorkbook().createCellStyle(); newCellStyle.cloneStyleFrom(oldCell.getCellStyle()); styleMap.put(stHashCode, newCellStyle); } newCell.setCellStyle(newCellStyle); } } switch(oldCell.getCellType()) { case Cell.CELL_TYPE_STRING: newCell.setCellValue(oldCell.getStringCellValue()); break;case Cell.CELL_TYPE_NUMERIC: newCell.setCellValue(oldCell.getNumericCellValue()); break;case Cell.CELL_TYPE_BLANK: newCell.setCellType(HSSFCell.CELL_TYPE_BLANK); break;case Cell.CELL_TYPE_BOOLEAN: newCell.setCellValue(oldCell.getBooleanCellValue()); break;case Cell.CELL_TYPE_ERROR: newCell.setCellErrorValue(oldCell.getErrorCellValue()); break;case Cell.CELL_TYPE_FORMULA: newCell.setCellFormula(oldCell.getCellFormula()); break;default: break; }} public static CellRangeAddress getMergedRegion(Sheet sheet, int rowNum, short cellNum) { for (int i = 0; i < sheet.getNumMergedRegions(); i++) {CellRangeAddress merged = sheet.getMergedRegion(i); if (merged.isInRange(rowNum, cellNum)) { return merged; } } return null; } private static boolean isNewMergedRegion(CellRangeAddressWrapper newMergedRegion, Set<CellRangeAddressWrapper> mergedRegions) { return !mergedRegions.contains(newMergedRegion); }}class CellRangeAddressWrapper implements Comparable<CellRangeAddressWrapper> {public CellRangeAddress range; public CellRangeAddressWrapper(CellRangeAddress theRange) { this.range = theRange; } public int compareTo(CellRangeAddressWrapper o) { if (range.getFirstColumn() < o.range.getFirstColumn() && range.getFirstRow() < o.range.getFirstRow()) { return -1; } else if (range.getFirstColumn() == o.range.getFirstColumn() && range.getFirstRow() == o.range.getFirstRow()) { return 0; } else { return 1; }}}


