Java后端实现合并多个excel页签
多个标签页合并
utils层
public static XSSFWorkbook mergeMultiExcel2MultiSheet(String sourceFilePath, String outputPath, String outputFileName) throws Exception {
long beginTime = System.currentTimeMillis();
// 将所有类型的尽调excel文件合并成一个excel文件
// 源文件
File file = new File(sourceFilePath);
File[] tempList = file.listFiles();
//根据文件名排序
Arrays.sort(tempList, (f1, f2) -> f1.getName().compareTo(f2.getName()));
String fileNameList[] = new String[tempList.length];
LOGGER.info("该目录下对象个数:{}", tempList.length);
for (int i = 0; i < tempList.length; i++) {
if (tempList[i].isFile()) {
fileNameList[i] = tempList[i].toString();
}
}
XSSFWorkbook newExcelCreat = new XSSFWorkbook();
// 遍历每个excel源文件,fileNameList为源文件的名称集合
for (String fromExcelName : fileNameList) {
InputStream in = new FileInputStream(fromExcelName);
XSSFWorkbook fromExcel = new XSSFWorkbook(in);
int length = fromExcel.getNumberOfSheets();
//长度为1时
if (length <= 1) {
XSSFSheet oldSheet = fromExcel.getSheetAt(0);
XSSFSheet newSheet = newExcelCreat.createSheet(oldSheet.getSheetName());
copySheet(newExcelCreat, oldSheet, newSheet);
} else {
// 遍历每个sheet
for (int i = 0; i < length; i++) {
XSSFSheet oldSheet = fromExcel.getSheetAt(i);
XSSFSheet newSheet = newExcelCreat.createSheet(oldSheet.getSheetName());
copySheet(newExcelCreat, oldSheet, newSheet);
}
}
in.close();
}
//定义新生成的xlx表格文件
//生成目录
String filePath = outputPath + System.getProperty("file.separator") + outputFileName;
FileOutputStream fileOut = new FileOutputStream(filePath);
newExcelCreat.write(fileOut);
fileOut.flush();
fileOut.close();
// 删除各个源文件
// 遍历每个源excel文件
for (String fromExcelName : fileNameList) {
File Existfile = new File(fromExcelName);
if (Existfile.exists()) {
Existfile.delete();
}
}
long endTime = System.currentTimeMillis();
LOGGER.info("合并文件执行时长:{} 毫秒.", (endTime - beginTime));
return newExcelCreat;
}
该Java函数的主要功能是合并指定目录下的多个Excel文件,将其中的所有工作表(Sheet)整合到一个新的Excel文件中,并且在完成后可以选择性地删除原文件。以下是详细步骤:
- 获取源文件列表:根据sourceFilePath参数定位到的目录路径,使用File.listFiles()方法获取所有子文件,并将其存储在一个File数组tempList中。
- 排序文件名:对tempList中的文件按照文件名进行升序排序,确保合并顺序一致。
- 提取文件名集合:遍历文件列表,只保留文件对象并将其对应的文件路径存入到字符串数组fileNameList中。
- 创建新Excel工作簿:通过new XSSFWorkbook()创建一个空的工作簿对象newExcelCreat,用于存放合并后的内容。
- 遍历并合并每个源Excel文件:
- 对于fileNameList中的每个Excel文件,打开输入流读取内容并创建对应的工作簿对象fromExcel。
- 获取fromExcel中的工作表数量,如果只有一个工作表,则直接复制该工作表到新工作簿中;如果有多个工作表,则逐个复制每个工作表。
- 使用copySheet方法将每个旧工作表的内容复制到新工作簿的新工作表中,保持原工作表名称不变。
- 保存合并后的Excel文件:
- 根据outputPath和outputFileName参数构建输出文件的完整路径filePath。
- 创建FileOutputStream对象指向目标文件路径,并调用newExcelCreat.write(fileOut)将合并后的工作簿写入到新的Excel文件中。
- 关闭输出流,确保数据已完全写入磁盘。
- 删除源Excel文件:再次遍历fileNameList,对于每一个源Excel文件,检查其是否存在,若存在则删除。
- 记录执行时间和返回合并后的工作簿:计算函数执行时间并记录日志,最后返回合并后的新Excel工作簿对象newExcelCreat。
其中copySheet
方法具体如下:
public static void copySheet(XSSFWorkbook wb, XSSFSheet fromSheet, XSSFSheet toSheet) {
mergeSheetAllRegion(fromSheet, toSheet);
// 设置列宽
int length = fromSheet.getRow(fromSheet.getFirstRowNum()).getLastCellNum();
for (int i = 0; i <= length; 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工作表(XSSFSheet类型,名为fromSheet)到另一个同类型工作表(名为toSheet)的完整内容复制,包括单元格数据、样式以及列宽等信息。下面是详细步骤:
- 合并区域:首先调用自定义方法mergeSheetAllRegion(fromSheet, toSheet),是将fromSheet中的所有合并单元格区域复制并应用到toSheet。
- 设置列宽:
- 获取fromSheet的第一行的所有单元格数量,以此得到工作表的列数。
- 遍历0到列数(包含列数),使用getColumnWidth(i)获取fromSheet的第i列的宽度,并通过setColumnWidth(i, width)方法将相同宽度设置给toSheet的对应列,确保列宽保持一致。
- 复制行内容:
- 使用迭代器遍历fromSheet的所有行。
- 对于每行,将其转换为XSSFRow对象(即oldRow),并根据其在原表中的行号,在toSheet中创建一个新的对应行(即newRow)。
- 调用copyRow(wb, oldRow, newRow)方法来逐个复制和粘贴行内单元格的内容及样式。这里需要传入整个Excel工作簿(XSSFWorkbook类型,名为wb)作为参数,因为可能涉及到引用其他表格或样式时需要用到工作簿上下文。
这个函数实现了两个Excel工作表之间的深度复制,不仅复制了单元格的值,还复制了列宽以及可能涉及的行内样式和其他相关信息。
其中mergeSheetAllRegion
方法具体如下:
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);
}
}
该方法其主要功能是从一个Apache POI库处理的Excel工作表(XSSFSheet)中复制所有合并区域的信息,并将其添加到另一个XSSFSheet中。具体实现步骤如下:
首先,通过调用fromSheet.getNumMergedRegions()方法获取源工作表(fromSheet)中的合并单元格区域总数。
使用一个for循环遍历所有的合并区域。循环变量i从0开始,小于num(即合并区域的数量)为止。
在每次循环迭代中,通过调用fromSheet.getMergedRegion(i)方法获取指定索引i处的合并单元格区域信息,并将其存储在CellRangeAddress类型的变量cellR中。CellRangeAddress对象包含了合并区域的起始行、结束行、起始列和结束列等信息。
最后,在目标工作表(toSheet)中使用toSheet.addMergedRegion(cellR)方法将从源工作表获取的合并单元格区域信息添加进去,实现了合并区域信息的复制。
总之,此函数用于在两个Excel工作表之间复制合并单元格设置,保持目标工作表的合并单元格布局与源工作表一致。
copyRow
方法具体如下:
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);
}
}
该方法用于将一个Apache POI库中定义的XSSF类型的Excel行(oldRow)的内容完整复制到另一个同样为XSSF类型的Excel行(toRow)中。具体实现过程如下:
- 设置目标行的高度:首先,函数通过调用toRow.setHeight(oldRow.getHeight())来设置目标行(toRow)的高度与源行(oldRow)相同,确保在样式和布局上保持一致。
- 遍历源行单元格:接着,使用迭代器遍历源行的所有单元格。这里调用oldRow.cellIterator()获取一个迭代器,并在循环中逐个取出每个单元格(类型为XSSFCell)。
- 创建并初始化新单元格:对于源行中的每一个单元格(tmpCell),在目标行中创建一个新的单元格(newCell),通过调用toRow.createCell(tmpCell.getColumnIndex())实现,其中tmpCell.getColumnIndex()用于获取当前单元格在原行中的列索引,确保新单元格在目标行中的位置与原单元格对应。
- 复制单元格内容及样式:然后,调用名为copyCell(wb, tmpCell, newCell)的辅助函数,这个函数未在此代码段中显示具体内容,但根据函数名推测其功能是将tmpCell的内容(包括但不限于数值、字符串、公式等)以及样式信息(如字体、颜色、填充、边框等)复制到新创建的newCell中。
- 重复上述过程直至完成所有单元格的复制:循环继续执行,直到遍历完源行的所有单元格,从而完成整个行数据的复制操作。
总之,此函数的主要目的是在两个Excel行之间进行深度复制,不仅复制单元格的内容,还包括单元格的高度以及可能存在的样式信息。
copyCell
方法具体如下:
public static void copyCell(XSSFWorkbook wb, XSSFCell fromCell, XSSFCell toCell) {
XSSFCellStyle newstyle = wb.createCellStyle();
copyCellStyle(fromCell.getCellStyle(), newstyle);
// 样式
toCell.setCellStyle(newstyle);
if (fromCell.getCellComment() != null) {
toCell.setCellComment(fromCell.getCellComment());
}
// 不同数据类型处理
CellType fromCellType = fromCell.getCellTypeEnum();
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 { // nothing29
}
}
该函数 copyCell 是一个Java方法,用于将一个基于Apache POI库的XSSF类型(表示.xlsx格式的Excel工作簿)的单元格(fromCell)的内容和样式完全复制到另一个同样类型的单元格(toCell)中。具体实现步骤如下:
创建新样式:首先,使用传入的工作簿(wb)创建一个新的XSSFCellStyle对象(newstyle),这个新样式将会被用来复制源单元格(fromCell)的样式。
复制样式:调用 copyCellStyle 方法(未在给出的代码片段中详细定义),将fromCell的样式复制到新创建的newstyle中。这一步确保目标单元格(toCell)将具有与源单元格相同的字体、填充、边框、对齐方式等样式信息。
设置目标单元格样式:将newstyle应用到目标单元格(toCell)上,通过调用 setCellStyle 方法完成。
复制注释:如果源单元格(fromCell)包含注释(cellComment),则将其复制到目标单元格(toCell),通过调用 setCellComment 方法实现。
处理不同数据类型:
对于数值型单元格,首先判断是否为日期格式(通过DateUtil.isCellDateFormatted方法)。若是日期,则调用 getDateCellValue 获取并设置日期值;若不是,则调用 getNumericCellValue 获取并设置数值值。
字符串型单元格,调用 getRichStringCellValue 获取并设置字符串值。
空白型单元格不做任何操作。
布尔型单元格,调用 getBooleanCellValue 获取并设置布尔值。
错误型单元格,调用 getErrorCellValue 获取并设置错误值。
公式型单元格,调用 getCellFormula 获取并设置公式。
对于除上述已处理的所有其他未知或未列举的CellType类型,此函数不执行任何操作。
总之,这个函数主要用于精确地克隆Excel单元格的所有内容和属性,包括但不限于样式、注释以及各种类型的数据。
copyCellStyle
方法具体如下:
public static void copyCellStyle(XSSFCellStyle fromStyle, XSSFCellStyle toStyle) {
toStyle.cloneStyleFrom(fromStyle);
}
该函数public static void copyCellStyle(XSSFCellStyle fromStyle, XSSFCellStyle toStyle)的功能是实现Excel样式单元格的样式复制。在Apache POI库中,XSSFCellStyle对象用于表示xlsx格式Excel文件中的单元格样式,包括但不限于字体、填充颜色、边框样式和颜色、对齐方式、数字格式等属性。
函数接受两个参数:
XSSFCellStyle fromStyle:源样式对象,包含了需要被复制的所有样式信息。
XSSFCellStyle toStyle:目标样式对象,将接收并应用从fromStyle复制过来的所有样式属性。
controller层调用
String outFileName = dwxh+"-"+nf+"年"+yf+"月.xlsx";
ExcelUtil.mergeMultiExcel2MultiSheet(ybOutPath,ybSynthesisPath,outFileName);