目 录CONTENT

文章目录

基于Excel POI Sheet复制工具类

BKUN
2025-07-02 / 0 评论 / 0 点赞 / 84 阅读 / 423 字
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import java.util.HashMap;
import java.util.Map;

public class OptimizedSheetCopyUtil {

    public static void copySheet(XSSFWorkbook resultWorkbook, Sheet sourceSheet, XSSFSheet newSheet) {
        // 缓存样式以减少重复创建
        Map<CellStyle, CellStyle> styleCache = new HashMap<>();

        // 复制 Sheet 属性
        newSheet.setDisplayGridlines(sourceSheet.isDisplayGridlines());
        newSheet.setPrintGridlines(sourceSheet.isPrintGridlines());
        newSheet.setFitToPage(sourceSheet.getFitToPage());
        newSheet.setHorizontallyCenter(sourceSheet.getHorizontallyCenter());
        newSheet.setVerticallyCenter(sourceSheet.getVerticallyCenter());

        // 复制打印设置
        PrintSetup sourcePrintSetup = sourceSheet.getPrintSetup();
        PrintSetup newPrintSetup = newSheet.getPrintSetup();
        newPrintSetup.setPaperSize(sourcePrintSetup.getPaperSize());
        newPrintSetup.setScale(sourcePrintSetup.getScale());
        newPrintSetup.setPageStart(sourcePrintSetup.getPageStart());
        newPrintSetup.setFitWidth(sourcePrintSetup.getFitWidth());
        newPrintSetup.setFitHeight(sourcePrintSetup.getFitHeight());

        // 复制边距
        newSheet.setMargin(Sheet.LeftMargin, sourceSheet.getMargin(Sheet.LeftMargin));
        newSheet.setMargin(Sheet.RightMargin, sourceSheet.getMargin(Sheet.RightMargin));
        newSheet.setMargin(Sheet.TopMargin, sourceSheet.getMargin(Sheet.TopMargin));
        newSheet.setMargin(Sheet.BottomMargin, sourceSheet.getMargin(Sheet.BottomMargin));

        // 只处理实际存在的行
        int maxRow = sourceSheet.getLastRowNum();
        for (int i = sourceSheet.getFirstRowNum(); i <= maxRow; i++) {
            Row sourceRow = sourceSheet.getRow(i);
            if (sourceRow == null) continue; // 跳过空行

            Row newRow = newSheet.createRow(i);
            newRow.setHeight(sourceRow.getHeight());

            // 只处理实际存在的单元格
            for (int j = sourceRow.getFirstCellNum(); j < sourceRow.getLastCellNum(); j++) {
                Cell sourceCell = sourceRow.getCell(j, Row.MissingCellPolicy.RETURN_NULL_AND_BLANK);
                if (sourceCell == null) continue; // 跳过空单元格

                Cell newCell = newRow.createCell(j);
                copyCell(sourceCell, newCell, resultWorkbook, styleCache);
            }
        }

        // 批量复制列宽
        int maxColumns = sourceSheet.getRow(sourceSheet.getFirstRowNum()) != null 
            ? sourceSheet.getRow(sourceSheet.getFirstRowNum()).getLastCellNum() : 0;
        for (int i = 0; i < maxColumns; i++) {
            newSheet.setColumnWidth(i, sourceSheet.getColumnWidth(i));
        }

        // 批量复制合并区域
        for (int i = 0; i < sourceSheet.getNumMergedRegions(); i++) {
            newSheet.addMergedRegion(sourceSheet.getMergedRegion(i));
        }
    }

    private static void copyCell(Cell sourceCell, Cell newCell, XSSFWorkbook resultWorkbook, Map<CellStyle, CellStyle> styleCache) {
        // 复用缓存的样式
        CellStyle sourceStyle = sourceCell.getCellStyle();
        CellStyle newCellStyle = styleCache.computeIfAbsent(sourceStyle, k -> {
            CellStyle newStyle = resultWorkbook.createCellStyle();
            newStyle.cloneStyleFrom(sourceStyle);
            return newStyle;
        });
        newCell.setCellStyle(newCellStyle);

        // 复制单元格注释
        if (sourceCell.getCellComment() != null) {
            newCell.setCellComment(sourceCell.getCellComment());
        }

        // 复制单元格值
        switch (sourceCell.getCellType()) {
            case STRING:
                newCell.setCellValue(sourceCell.getStringCellValue());
                break;
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(sourceCell)) {
                    newCell.setCellValue(sourceCell.getDateCellValue());
                } else {
                    newCell.setCellValue(sourceCell.getNumericCellValue());
                }
                break;
            case BOOLEAN:
                newCell.setCellValue(sourceCell.getBooleanCellValue());
                break;
            case FORMULA:
                newCell.setCellFormula(sourceCell.getCellFormula());
                break;
            case BLANK:
                newCell.setCellType(CellType.BLANK);
                break;
            case ERROR:
                newCell.setCellErrorValue(sourceCell.getErrorCellValue());
                break;
            default:
                break;
        }
    }
}
0

评论区