当前位置: 首页 > 面试题库 >

如何在Java中的Excel工作簿之间复制工作表

袁运锋
2023-03-14
问题内容

如何在Apache poi的两个不同的工作簿之间复制工作表?

该方法缺少引用此线程。没有这样的解决方案。


问题答案:

经过研究和尝试,这里是我的解决方案。我已经通过Java 1.6和apache-poi 3.8进行了测试

在这里,我将不提供适用于我的解决方案,特别是在这种情况下,我将粘贴工作表和输入流列表(我要合并的不同工作簿)。

我的解决方案是一个合并的解决方案,我从这里合并了整个源代码,我想与所有人共享此代码,但都遇到了同样的问题。

/**
* Original version available from:
* http://www.coderanch.com/t/420958/open-source/Copying-sheet-excel-file-another
**/
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;
}

/** 
 * @param newSheet the sheet to create from the copy. 
 * @param sheet the sheet to copy. 
 */  
public static void copySheets(Sheet newSheet, Sheet sheet){     
    copySheets(newSheet, sheet, true);     
}

/** 
 * @param newSheet the sheet to create from the copy. 
 * @param sheet the sheet to copy. 
 * @param copyStyle true copy the style. 
 */  
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));     
    }     
}

/** 
 * @param srcSheet the sheet to copy. 
 * @param destSheet the sheet to create. 
 * @param srcRow the row to copy. 
 * @param destRow the row to create. 
 * @param styleMap - 
 */  
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 cell   
        if (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);     
                }     
            }     
        }     
    }                
}

/** 
 * @param oldCell 
 * @param newCell 
 * @param styleMap 
 */  
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;     
    }

}

/** 
 * Récupère les informations de fusion des cellules dans la sheet source pour les appliquer 
 * à la sheet destination... 
 * Récupère toutes les zones merged dans la sheet source et regarde pour chacune d'elle si 
 * elle se trouve dans la current row que nous traitons. 
 * Si oui, retourne l'objet CellRangeAddress. 
 *  
 * @param sheet the sheet containing the data. 
 * @param rowNum the num of the row to copy. 
 * @param cellNum the num of the cell to copy. 
 * @return the CellRangeAddress created. 
 */  
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;     
}

/** 
 * Check that the merged region has been created in the destination sheet. 
 * @param newMergedRegion the merged region to copy or not in the destination sheet. 
 * @param mergedRegions the list containing all the merged region. 
 * @return true if the merged region is already in the list or not. 
 */  
private static boolean isNewMergedRegion(CellRangeAddressWrapper newMergedRegion, Set<CellRangeAddressWrapper> mergedRegions) {  
  return !mergedRegions.contains(newMergedRegion);     
}

}
class CellRangeAddressWrapper implements Comparable<CellRangeAddressWrapper> {

public CellRangeAddress range;

/** 
 * @param theRange the CellRangeAddress object to wrap. 
 */  
public CellRangeAddressWrapper(CellRangeAddress theRange) {  
      this.range = theRange;  
}

/** 
 * @param o the object to compare. 
 * @return -1 the current instance is prior to the object in parameter, 0: equal, 1: after... 
 */  
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;  
            }

}

}


 类似资料:
  • 所以在问这个之前,我搜索并发现了一些与我在这里想要做的相似的事情。 基本上我有工作簿AlphaMaster。这个工作簿是一个模板,我想用它来创建每周的新工作簿。 在本工作簿中,有名为“周一至周六”的工作表,以及带有相应日期的周一、周二等其他工作表。 我创建了一个在打开工作簿时加载的表单。我想要的是当我单击表单运行时,它将: > 将代码保存模板作为新工作簿运行 根据userform1的输入重命名工作

  • 问题内容: 我有一个带有源文件路径的字符串和另一个带有destfile路径的字符串,它们都指向Excel工作簿。 我想获取源文件的第一张纸并将其作为新选项卡复制到destfile(与destfile中的位置无关),然后保存它。 在or或or中找不到简单的方法。我想念什么吗? 问题答案: 解决方案1 使用该软件包的仅Python解决方案。仅数据值将被复制。 解决方案2 使用该程序包将复制操作委派给E

  • 我无法使用 apache poi eclipse 在我创建的 java excel 中创建工作表

  • 我有一本有工作表的工作簿。为了简单起见,假设我的工作簿有一个工作表。在我的工作表中,它被称为“SHEET1”,在单元格A1到A4中有数据。 我希望我的VBA代码做的是: 将工作簿“A”的第1行(或特别是单元格A1至A4)复制到范围变量“我的范围”中 创建一个新的工作簿,我们将此工作簿称为'B' 为工作簿'B'的默认“sheet1”指定一个新名称为“测试名称” 打开工作簿'B'(尽管我意识到VBA代

  • 我正在尝试使用最新版本的ApachePOI(4.1.2)将单元格从一个工作簿复制到另一个工作簿。 如果两个工作簿都是.xlsx文件,则一切正常。但是,如果源工作簿是一个(旧的).xls文件,而目标工作簿是一个.xlsx文件,则以下代码将失败 引发的异常是: java.lang.IllegalArgumentException:只能从一个XSSFCellStyle克隆到另一个,不能在HSSFCell

  • 2,3和6-12被跳过。下面是我的代码: 我认为这个问题与行“wb1.sheets(1).Range(”a“&Range(”a1“).end(xlDown).row+1)”有关,但我不知道如何解决这个问题。有什么建议吗?谢谢!