poi合并多个excel文件,并且排序

package com.envisioniot.reportds.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor;

import java.io.*;
import java.util.*;

/**
 * @author YangHaojie
 * @date 2021/8/30
 */
@Slf4j
public class ExcelUtils {

    public static void main(String[] args) {
        File[] files = new File[3];
        files[0] = new File("C:\\Users\\TemplatePreview_20210830 (1).xlsx");
        files[1] = new File("C:\\Users\\TemplatePreview_20210830.xlsx");
        files[2] = new File("C:\\Users\\\\新建 Microsoft Excel 工作表.xlsx");
        mergexcel(files,"test.xlsx","C:\\Users\\\\excel_test\\");
        System.out.println("OJBK");
    }

    /**
     * * 合并多个ExcelSheet
     *
     * @param files 文件字符串(file.toString)集合,按顺序进行合并,合并的Excel中Sheet名称不可重复
     * @param excelName 合并后Excel名称(包含后缀.xslx)
     * @param dirPath 存储目录
     */
    public static boolean mergexcel(File[] files, String excelName, String dirPath) {
        if(files == null){
            return false;
        }
        Arrays.sort(files, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                if (o1.isDirectory() && o2.isFile()) {
                    return -1;
                }
                if (o1.isFile() && o2.isDirectory()) {
                    return 1;
                }
                String o1Name = o1.getName().substring(0, o1.getName().lastIndexOf(".") > 0 ?
                        o1.getName().lastIndexOf(".") : o1.getName().length());
                String o2Name = o2.getName().substring(0, o2.getName().lastIndexOf(".") > 0 ?
                        o2.getName().lastIndexOf(".") : o2.getName().length());
                return o1Name.compareTo(o2Name);
            }
        });
        XSSFWorkbook newExcelCreat = new XSSFWorkbook();
        Map<String, Integer> names = new HashMap<>();
        // 遍历每个源excel文件,TmpList为源文件的名称集合
        for (File fromExcelFile : files) {
            if(fromExcelFile == null){
                continue;
            }
            String fromExcelName = fromExcelFile.toString();
            String name = fromExcelFile.getName();
            if(StringUtils.isNotEmpty(name)){
                name = name.substring(0, name.lastIndexOf(".") != 0 ? name.lastIndexOf(".") : name.length());
            }
            try (InputStream in = new FileInputStream(fromExcelName)) {
                XSSFWorkbook fromExcel = new XSSFWorkbook(in);
                int length = fromExcel.getNumberOfSheets();
                if (length == 1) {       //长度为1时
                    XSSFSheet oldSheet = fromExcel.getSheetAt(0);
                    if(names.containsKey(name)){
                        int cnt = names.get(name) + 1;
                        name = name.concat("(").concat(String.valueOf(cnt)).concat(")");
                    }
                    names.put(name, names.getOrDefault(name, 0) + 1);
                    XSSFSheet newSheet = newExcelCreat.createSheet(name);
                    copySheet(newExcelCreat, oldSheet, newSheet);
                    copyPicture(newExcelCreat, oldSheet, newSheet);
                } else {
                    for (int i = 0; i < length; i++) {// 遍历每个sheet
                        XSSFSheet oldSheet = fromExcel.getSheetAt(i);
                        if(names.containsKey(name)){
                            int cnt = names.get(name) + 1;
                            name = name.concat("(").concat(String.valueOf(cnt)).concat(")");
                        }
                        names.put(name, names.getOrDefault(name, 0) + 1);
                        XSSFSheet newSheet = newExcelCreat.createSheet(name);
                        copySheet(newExcelCreat, oldSheet, newSheet);
                        copyPicture(newExcelCreat, oldSheet, newSheet);
                    }
                }
            } catch (Exception e) {
                log.error("excel merge failed", e);
                return false;
            }
        }
        // 定义新生成的xlxs表格文件
        String allFileName = dirPath + excelName;
        try (FileOutputStream fileOut = new FileOutputStream(allFileName)) {
            newExcelCreat.write(fileOut);
            fileOut.flush();
        } catch (Exception e) {
            log.error("excel merge failed", e);
            return false;
        } finally {
            try {
                newExcelCreat.close();
            } catch (IOException e) {
                log.error("excel merge failed", e);
                return false;
            }
        }
        return true;
    }

    /**
     * 合并单元格
     *
     * @param fromSheet
     * @param toSheet
     */
    private 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);
        }
    }

    /**
     * 复制单元格
     *
     * @param wb
     * @param fromCell
     * @param toCell
     */
    private static void copyCell(XSSFWorkbook wb, XSSFCell fromCell, XSSFCell toCell) {
        XSSFCellStyle newstyle = wb.createCellStyle();
        // 复制单元格样式
        newstyle.cloneStyleFrom(fromCell.getCellStyle());
        // 样式
        toCell.setCellStyle(newstyle);
        if (fromCell.getCellComment() != null) {
            toCell.setCellComment(fromCell.getCellComment());
        }
        // 不同数据类型处理
        CellType fromCellType = fromCell.getCellType();
        toCell.setCellType(fromCellType);
        if (fromCellType == CellType.NUMERIC) {
            if (DateUtil.isCellDateFormatted(fromCell)) {
                toCell.setCellValue(fromCell.getDateCellValue());
            } else {
                toCell.setCellValue(fromCell.getNumericCellValue());
            }
        } else if (fromCellType == CellType.STRING) {
            toCell.setCellValue(fromCell.getRichStringCellValue());
        } else if (fromCellType == CellType.BLANK) {
            // nothing21
        } else if (fromCellType == CellType.BOOLEAN) {
            toCell.setCellValue(fromCell.getBooleanCellValue());
        } else if (fromCellType == CellType.ERROR) {
            toCell.setCellErrorValue(fromCell.getErrorCellValue());
        } else if (fromCellType == CellType.FORMULA) {
            toCell.setCellFormula(fromCell.getCellFormula());
        } else {
            // nothing
        }
    }

    /**
     * 行复制功能
     *
     * @param wb
     * @param oldRow
     * @param toRow
     */
    private 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);
        }
    }

    /**
     * Sheet复制
     *
     * @param wb
     * @param fromSheet
     * @param toSheet
     */
    private static void copySheet(XSSFWorkbook wb, XSSFSheet fromSheet, XSSFSheet toSheet) {
        mergeSheetAllRegion(fromSheet, toSheet);
        int maxColumnNum = 0;
        for (Iterator rowIt = fromSheet.rowIterator(); rowIt.hasNext(); ) {
            XSSFRow oldRow = (XSSFRow) rowIt.next();
            XSSFRow newRow = toSheet.createRow(oldRow.getRowNum());
            copyRow(wb, oldRow, newRow);
            if(oldRow.getLastCellNum() > maxColumnNum){
                maxColumnNum = oldRow.getLastCellNum();
            }
        }
        //设置列宽
        if(fromSheet != null && toSheet != null) {
            for (int i = 0; i <= maxColumnNum; i++) {
                toSheet.setColumnWidth(i, fromSheet.getColumnWidth(i));
            }
        }
    }

    /**
     * 获取图片和位置 (xlsx),会复原图片大小
     * @param sheet
     * @return
     * @throws IOException
     */
    public static Map<String, XSSFPictureData> getPictures (XSSFSheet sheet) throws IOException {
        Map<String, XSSFPictureData> map = new HashMap<String, XSSFPictureData>();
        List<POIXMLDocumentPart> list = sheet.getRelations();
        for (POIXMLDocumentPart part : list) {
            if (part instanceof XSSFDrawing) {
                XSSFDrawing drawing = (XSSFDrawing) part;
                List<XSSFShape> shapes = drawing.getShapes();
                for (XSSFShape shape : shapes) {
                    XSSFPicture picture = (XSSFPicture) shape;
                    XSSFClientAnchor anchor = picture.getPreferredSize();
                    CTMarker marker = anchor.getFrom();
                    String key = marker.getRow() + "-" + marker.getCol();
                    map.put(key, picture.getPictureData());
                }
            }
        }
        return map;
    }

    /**
     * 获得原始sheet中图片的信息、位置 todo:解决图片的格式以及属性
     * @param sheet
     * @return
     * @throws IOException
     */
    public static List<Map<String,Object>> getPicturesFromXSSFSheet (XSSFSheet sheet) throws IOException {
        List<Map<String,Object>> res = new ArrayList<>();
        List<POIXMLDocumentPart> list = sheet.getRelations();
        for (POIXMLDocumentPart part : list) {
            if (part instanceof XSSFDrawing) {
                XSSFDrawing drawing = (XSSFDrawing) part;
                List<XSSFShape> shapes = drawing.getShapes();
                for (XSSFShape shape : shapes) {
                    Map<String,Object> map = new HashMap<>();
                    XSSFPicture picture = (XSSFPicture) shape;
                    XSSFClientAnchor anchor = picture.getClientAnchor();
                    map.put("pictureAnchor", anchor);
                    map.put("pictureByteArray", picture.getPictureData().getData());
                    map.put("pictureType", picture.getPictureData().getPictureType());
                    res.add(map);
                    picture.getCTPicture();
                }
            }
        }
        return res;
    }

    /**
     * 复制图片
     * @param workbook
     * @param sourceSheet
     * @param targetSheet
     * @throws IOException
     */
    public static void copyPicture(XSSFWorkbook workbook,XSSFSheet sourceSheet,XSSFSheet targetSheet) throws IOException {
        XSSFDrawing drawing = targetSheet.createDrawingPatriarch();
        List< Map<String,Object>> sourceSheetPictures=getPicturesFromXSSFSheet(sourceSheet);
        if(CollectionUtils.isNotEmpty(sourceSheetPictures)){
            for(Map<String, Object> sourceSheetPicture : sourceSheetPictures) {
                if(sourceSheetPicture == null || sourceSheetPicture.size() == 0){
                    continue;
                }
                XSSFPicture picture = drawing.createPicture((XSSFClientAnchor) sourceSheetPicture.get("pictureAnchor"),
                        workbook.addPicture((byte[]) sourceSheetPicture.get("pictureByteArray"),
                                Integer.parseInt(sourceSheetPicture.get("pictureType").toString())));

            }
        }
    }

    /**
     * 复制图片方法2
     * @param newSheet
     * @param sheet
     */
    private static void copyPictures(Sheet newSheet, Sheet sheet) {
        Drawing drawingOld = sheet.createDrawingPatriarch();
        Drawing drawingNew = newSheet.createDrawingPatriarch();
        CreationHelper helper = newSheet.getWorkbook().getCreationHelper();
        // if (drawingNew instanceof HSSFPatriarch) {
        if (drawingOld instanceof HSSFPatriarch) {
            List<HSSFShape> shapes = ((HSSFPatriarch) drawingOld).getChildren();
            for (int i = 0; i < shapes.size(); i++) {
                if (shapes.get(i) instanceof HSSFPicture) {
                    HSSFPicture pic = (HSSFPicture) shapes.get(i);
                    HSSFPictureData picdata = pic.getPictureData();
                    int pictureIndex = newSheet.getWorkbook().addPicture(picdata.getData(), picdata.getFormat());
                    ClientAnchor anchor = null;
                    if (pic.getAnchor() != null) {
                        anchor = helper.createClientAnchor();
                        anchor.setDx1(((HSSFClientAnchor) pic.getAnchor()).getDx1());
                        anchor.setDx2(((HSSFClientAnchor) pic.getAnchor()).getDx2());
                        anchor.setDy1(((HSSFClientAnchor) pic.getAnchor()).getDy1());
                        anchor.setDy2(((HSSFClientAnchor) pic.getAnchor()).getDy2());
                        anchor.setCol1(((HSSFClientAnchor) pic.getAnchor()).getCol1());
                        anchor.setCol2(((HSSFClientAnchor) pic.getAnchor()).getCol2());
                        anchor.setRow1(((HSSFClientAnchor) pic.getAnchor()).getRow1());
                        anchor.setRow2(((HSSFClientAnchor) pic.getAnchor()).getRow2());
                        anchor.setAnchorType(((HSSFClientAnchor) pic.getAnchor()).getAnchorType());
                    }
                    drawingNew.createPicture(anchor, pictureIndex);
                }
            }
        } else {
            if (drawingNew instanceof XSSFDrawing) {
                List<XSSFShape> shapes = ((XSSFDrawing) drawingOld).getShapes();
                for (int i = 0; i < shapes.size(); i++) {
                    if (shapes.get(i) instanceof XSSFPicture) {
                        XSSFPicture pic = (XSSFPicture) shapes.get(i);
                        XSSFPictureData picdata = pic.getPictureData();
                        int pictureIndex = newSheet.getWorkbook().addPicture(picdata.getData(),
                                picdata.getPictureType());
                        XSSFClientAnchor anchor = null;
                        CTTwoCellAnchor oldAnchor = ((XSSFDrawing) drawingOld).getCTDrawing().getTwoCellAnchorArray(i);
                        if (oldAnchor != null) {
                            anchor = (XSSFClientAnchor) helper.createClientAnchor();
                            CTMarker markerFrom = oldAnchor.getFrom();
                            CTMarker markerTo = oldAnchor.getTo();
                            anchor.setDx1((int) markerFrom.getColOff());
                            anchor.setDx2((int) markerTo.getColOff());
                            anchor.setDy1((int) markerFrom.getRowOff());
                            anchor.setDy2((int) markerTo.getRowOff());
                            anchor.setCol1(markerFrom.getCol());
                            anchor.setCol2(markerTo.getCol());
                            anchor.setRow1(markerFrom.getRow());
                            anchor.setRow2(markerTo.getRow());
                        }
                        drawingNew.createPicture(anchor, pictureIndex);
                    }
                }
            }
        }
    }

}

1. 打开POI项目主页(https://poi.apache.org)并下载POI jar包。 2. 创建一个新的Java项目,将下载的POI jar包添加到项目的构建路径中。 3. 创建一个新的Java类,用于合并多个Excel文件。 4. 导入所需的POI类: ``` import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.poi.ss.usermodel.Cell; 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; ``` 5. 创建一个方法,该方法将接受一个文件夹的路径,该文件夹包含要合并的所有Excel文件。该方法将返回一个Workbook对象,其中包含所有Excel文件的数据: ``` public static Workbook mergeExcelFiles(String folderPath) throws IOException { List<File> files = getAllExcelFiles(folderPath); Workbook mergedWorkbook = WorkbookFactory.create(); for (File file : files) { Workbook workbook = WorkbookFactory.create(file); for (int i = 0; i < workbook.getNumberOfSheets(); i++) { Sheet sheet = workbook.getSheetAt(i); Sheet mergedSheet = mergedWorkbook.createSheet(sheet.getSheetName()); copySheet(sheet, mergedSheet); } } return mergedWorkbook; } ``` 6. 创建一个辅助方法,该方法将接受一个文件夹路径,并返回一个包含所有Excel文件的列表: ``` private static List<File> getAllExcelFiles(String folderPath) { File folder = new File(folderPath); File[] files = folder.listFiles(); List<File> excelFiles = new ArrayList<File>(); for (File file : files) { if (file.isFile() && file.getName().endsWith(".xlsx")) { excelFiles.add(file); } } return excelFiles; } ``` 7. 创建另一个辅助方法,该方法将接受两个Sheet对象,并将第一个Sheet的数据复制到第二个Sheet中: ``` private static void copySheet(Sheet sourceSheet, Sheet targetSheet) { int rowCount = sourceSheet.getLastRowNum(); for (int i = 0; i <= rowCount; i++) { Row sourceRow = sourceSheet.getRow(i); Row targetRow = targetSheet.createRow(i); int columnCount = sourceRow.getLastCellNum(); for (int j = 0; j < columnCount; j++) { Cell sourceCell = sourceRow.getCell(j); Cell targetCell = targetRow.createCell(j); switch (sourceCell.getCellType()) { case STRING: targetCell.setCellValue(sourceCell.getStringCellValue()); break; case NUMERIC: targetCell.setCellValue(sourceCell.getNumericCellValue()); break; case BOOLEAN: targetCell.setCellValue(sourceCell.getBooleanCellValue()); break; case FORMULA: targetCell.setCellFormula(sourceCell.getCellFormula()); break; default: targetCell.setCellValue(""); } } } } ``` 8. 创建一个main方法,该方法将调用mergeExcelFiles方法,并将合并的Workbook对象写入一个新的Excel文件: ``` public static void main(String[] args) { String folderPath = "C:/ExcelFiles"; Workbook mergedWorkbook; try { mergedWorkbook = mergeExcelFiles(folderPath); FileOutputStream outputStream = new FileOutputStream("C:/MergedExcelFile.xlsx"); mergedWorkbook.write(outputStream); outputStream.close(); System.out.println("Excel文件合并完成!"); } catch (IOException e) { e.printStackTrace(); } } ``` 9. 运行程序,合并Excel文件将保存在C:/MergedExcelFile.xlsx中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值