package com.zhgd.xmgl.util; import com.zhgd.jeecg.common.mybatis.EntityMap; import com.zhgd.xmgl.modules.car.entity.CarType; import com.zhgd.xmgl.modules.exam.entity.ExamSubject; import com.zhgd.xmgl.modules.safetyhat.entity.SafetyHatFence; import com.zhgd.xmgl.modules.worker.entity.EnterpriseInfo; import com.zhgd.xmgl.modules.worker.entity.WorkerSafeEducationWorker; import com.zhgd.xmgl.modules.worker.entity.WorkerType; import com.zhgd.xmgl.modules.worker.entity.dto.WorkerAttendanceDto; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.poi.hssf.usermodel.HSSFClientAnchor; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.usermodel.*; import org.springframework.core.io.ClassPathResource; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.util.*; /** * @program: wisdomSite * @description: excel处理工具类 * @author: Mr.Peng * @create: 2021-08-16 17:42 **/ @Slf4j public class ExcelUtils { public static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) throws IOException { response.setCharacterEncoding("UTF-8"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); workbook.write(response.getOutputStream()); } public static List> jxlExlToList(InputStream is, int index) throws Exception { Workbook book = null; List> list = null; String companyId = null; //Map map=new HashMap<>(16); try { book = WorkbookFactory.create(is); //book = new XSSFWorkbook(is);// 创建一个新的写入工作簿 Sheet sheet = book.getSheetAt(0); //int totalRows = sheet.getLastRowNum(); int totalRows = sheet.getPhysicalNumberOfRows(); //int totalColumns = sheet.getColumns(); Row xssfRow = sheet.getRow(index); int totalColumns = xssfRow.getLastCellNum(); if (totalColumns <= 0) { return null; } //读取指定行作为Map中的key List tableHeaderlist = new ArrayList<>(); for (int i = 0; i < totalColumns; i++) { String value = getCellValue(sheet, xssfRow.getCell(i)); if (tableHeaderlist.contains(value)) { value = value + "(1)"; } if (StringUtils.isNotEmpty(value)) { value = value.replaceAll("[\\t\\n\\r]", ""); } tableHeaderlist.add(value); } //将指定行后面每一行存为Map集合,然后存为list list = new ArrayList<>(); Map rowData = new LinkedHashMap<>(); int start = 1 + index; for (int i = start; i < totalRows; i++) { xssfRow = sheet.getRow(i); rowData = new LinkedHashMap<>(totalColumns); for (int j = 0; j < xssfRow.getLastCellNum(); j++) { if (j < totalColumns) { if (StringUtils.isNotEmpty(tableHeaderlist.get(j).toString())) { if (xssfRow.getCell(j) != null) { String value = getCellValue(sheet, xssfRow.getCell(j)); rowData.put(tableHeaderlist.get(j).toString(), value); } else { rowData.put(tableHeaderlist.get(j).toString(), ""); } } } } if (rowData.size() > 0) { list.add(rowData); } } log.info("工作簿读取数据成功!"); } catch (Exception e) { log.error("error:", e); } return list; } public static String getMergedRegionValue(Sheet sheet, int row, int column) { int sheetMergeCount = sheet.getNumMergedRegions(); for (int i = 0; i < sheetMergeCount; i++) { CellRangeAddress ca = sheet.getMergedRegion(i); int firstColumn = ca.getFirstColumn(); int lastColumn = ca.getLastColumn(); int firstRow = ca.getFirstRow(); int lastRow = ca.getLastRow(); if (row >= firstRow && row <= lastRow) { if (column >= firstColumn && column <= lastColumn) { Row fRow = sheet.getRow(firstRow); Cell fCell = fRow.getCell(firstColumn); return getValue(fCell); } } } return null; } /** * 判断指定的单元格是否是合并单元格 * * @param sheet 工作表 * @param row 行下标 * @param column 列下标 * @return */ private static boolean isMergedRegion(Sheet sheet, int row, int column) { int sheetMergeCount = sheet.getNumMergedRegions(); for (int i = 0; i < sheetMergeCount; i++) { CellRangeAddress range = sheet.getMergedRegion(i); int firstColumn = range.getFirstColumn(); int lastColumn = range.getLastColumn(); int firstRow = range.getFirstRow(); int lastRow = range.getLastRow(); if (row >= firstRow && row <= lastRow) { if (column >= firstColumn && column <= lastColumn) { return true; } } } return false; } public static String getValue(Cell hssfCell) { if (hssfCell.getCellTypeEnum() == CellType.BOOLEAN) { return String.valueOf(hssfCell.getBooleanCellValue()); } else if (hssfCell.getCellTypeEnum() == CellType.NUMERIC) { //if (HSSFDateUtil.isCellDateFormatted(hssfCell)) { if (CellDateUtil.isCellDateFormatted(hssfCell)) { Date date = hssfCell.getDateCellValue(); return DateFormatUtils.format(date, "yyyy-MM-dd HH:mm:ss"); } else { hssfCell.setCellType(CellType.STRING); return String.valueOf(hssfCell.getStringCellValue()); } } else if (hssfCell.getCellTypeEnum() == CellType.STRING) { return String.valueOf(hssfCell.getStringCellValue()); } else { hssfCell.setCellType(CellType.STRING); return String.valueOf(hssfCell.getStringCellValue()); } } /** * 获取合并单元格的值 * * @param sheet * @param cell * @return */ public static String getCellValue(Sheet sheet, Cell cell) { String value = ""; if (cell != null) { //log.info("-----------row:" +cell.getRowIndex()+"-------column:"+cell.getColumnIndex()); int row = cell.getRowIndex(); int column = cell.getColumnIndex(); boolean temp = isMergedRegion(sheet, row, column); if (temp) { value = getMergedRegionValue(sheet, row, column); } else { value = getValue(cell); } } return value; } public static void exportAttendanceExcel(HttpServletResponse response) { try { ClassPathResource classPathResource = new ClassPathResource("excel/人员考勤导入模板.xlsx"); InputStream inputStream = classPathResource.getInputStream(); XSSFWorkbook workbook = new XSSFWorkbook(inputStream); downLoadExcel("人员考勤导入模板.xlsx", response, workbook); } catch (IOException e) { log.error("error:", e); } } public static void exportHiddenDangerLibraryExcel(HttpServletResponse response) { try { ClassPathResource classPathResource = new ClassPathResource("excel/安全隐患库_导入模板.xlsx"); InputStream inputStream = classPathResource.getInputStream(); XSSFWorkbook workbook = new XSSFWorkbook(inputStream); downLoadExcel("安全隐患库_导入模板.xlsx", response, workbook); } catch (IOException e) { log.error("error:", e); } } public static void exportInspectTableLibraryExcel(HttpServletResponse response) { try { ClassPathResource classPathResource = new ClassPathResource("excel/检查表导入模板.xlsx"); InputStream inputStream = classPathResource.getInputStream(); XSSFWorkbook workbook = new XSSFWorkbook(inputStream); downLoadExcel("检查表导入模板.xlsx", response, workbook); } catch (IOException e) { log.error("error:", e); } } public static void exporExcelWorkerTemplate(HttpServletResponse response, List teamList, List departmentList) { try { XSSFWorkbook workbook = getExcelWorkerTemplateWorkbook(teamList, departmentList); downLoadExcel("人员导入模板.xlsx", response, workbook); } catch (IOException e) { log.error("error:", e); } } /** * 获取下载人员导入模板workbook * * @param teamList * @param departmentList * @return * @throws IOException */ public static XSSFWorkbook getExcelWorkerTemplateWorkbook(List teamList, List departmentList) throws IOException { ClassPathResource classPathResource = new ClassPathResource("excel/人员导入模板.xlsx"); InputStream inputStream = classPathResource.getInputStream(); XSSFWorkbook workbook = new XSSFWorkbook(inputStream); //部门/班组下拉列 XSSFSheet sheet2 = workbook.getSheet("部门"); if (teamList.size() > 0) { for (int i = 0; i < teamList.size(); i++) { XSSFRow row1 = sheet2.createRow(i); XSSFCell cell1 = row1.createCell(0); cell1.setCellType(CellType.STRING); cell1.setCellValue(MapUtils.getString(teamList.get(i), "enterpriseTeamName")); } } if (departmentList.size() > 0) { for (int i = 0; i < departmentList.size(); i++) { XSSFRow row1 = sheet2.createRow(i + teamList.size()); XSSFCell cell1 = row1.createCell(0); cell1.setCellType(CellType.STRING); cell1.setCellValue(MapUtils.getString(departmentList.get(i), "enterpriseDepartmentName")); } } return workbook; } public static void exporExcelSafeDevTemplate(HttpServletResponse response, List fenceList, List enterpriseInfoList) { try { ClassPathResource classPathResource = new ClassPathResource("excel/安全帽设备导入模板.xlsx"); InputStream inputStream = classPathResource.getInputStream(); XSSFWorkbook workbook = new XSSFWorkbook(inputStream); //围栏下拉列 XSSFSheet sheet2 = workbook.getSheet("围栏"); if (fenceList.size() > 0) { for (int i = 0; i < fenceList.size(); i++) { XSSFRow row1 = sheet2.createRow(i); XSSFCell cell1 = row1.createCell(0); cell1.setCellType(CellType.STRING); cell1.setCellValue(fenceList.get(i).getFenceName()); } } //分包单位下拉列 XSSFSheet sheet3 = workbook.getSheet("分包单位"); if (enterpriseInfoList.size() > 0) { for (int i = 0; i < enterpriseInfoList.size(); i++) { XSSFRow row1 = sheet3.createRow(i); XSSFCell cell1 = row1.createCell(0); cell1.setCellType(CellType.STRING); cell1.setCellValue(enterpriseInfoList.get(i).getEnterpriseName()); } } downLoadExcel("安全帽设备导入模板.xlsx", response, workbook); } catch (IOException e) { log.error("error:", e); } } public static void exporExcelWorkerEducation(HttpServletResponse response, Map map, WorkerSafeEducationWorker workerSafeEducationWorker, WorkerType workerType, String basePath) { try { ClassPathResource classPathResource = new ClassPathResource("excel/工人教育档案.xlsx"); InputStream inputStream = classPathResource.getInputStream(); XSSFWorkbook workbook = new XSSFWorkbook(inputStream); XSSFSheet sheet = workbook.getSheet("教育档案"); map.put("sex", MapUtils.getIntValue(map, "sex") == 1 ? "男" : "女"); Map placeholderMap = new HashMap<>(16); for (String s : map.keySet()) { placeholderMap.put("${" + s + "}", map.get(s)); } placeholderMap.put("${studyTime}", workerSafeEducationWorker.getStudyTime()); placeholderMap.put("${score}", workerSafeEducationWorker.getScore()); placeholderMap.put("${workerTypeName}", workerType.getTypeName()); // 替换占位符 for (Row row : sheet) { for (Cell cell : row) { if (cell.getCellType() == CellType.STRING) { String cellValue = cell.getStringCellValue(); for (String placeholder : placeholderMap.keySet()) { if (cellValue.contains(placeholder)) { cellValue = cellValue.replace(placeholder, placeholderMap.get(placeholder).toString()); cell.setCellValue(cellValue); } } } } } String idCardBigPhotoUrl = MapUtils.getString(map, "idCardBigPhotoUrl"); if (StringUtils.isNotBlank(idCardBigPhotoUrl)) { picture(basePath + idCardBigPhotoUrl, sheet, 9, 15, 13, 15); } String idCardUpPhotoUrl = MapUtils.getString(map, "idCardUpPhotoUrl"); if (StringUtils.isNotBlank(idCardBigPhotoUrl)) { picture(basePath + idCardUpPhotoUrl, sheet, 20, 28, 1, 7); } String idCardDownPhotoUrl = MapUtils.getString(map, "idCardDownPhotoUrl"); if (StringUtils.isNotBlank(idCardDownPhotoUrl)) { picture(basePath + idCardDownPhotoUrl, sheet, 20, 28, 9, 15); } downLoadExcel("工人教育档案.xlsx", response, workbook); } catch (IOException e) { log.error("error:", e); } } private static void picture(String path, XSSFSheet sheet, int startRow, int endRow, int startCol, int endCol) { try { InputStream inputStreamPic = new FileInputStream(path); byte[] imageBytes = IOUtils.toByteArray(inputStreamPic); Drawing drawing = sheet.createDrawingPatriarch();//用于在工作表上创建绘图对象 // 将图片插入单元格 int pictureIdx = sheet.getWorkbook().addPicture(imageBytes, Workbook.PICTURE_TYPE_JPEG); CreationHelper helper = sheet.getWorkbook().getCreationHelper(); ClientAnchor anchor = helper.createClientAnchor();//用于指定图片的位置 anchor.setCol1(startCol);//指定其实位置 anchor.setRow1(startRow); anchor.setCol2(endCol);//指定结束位置 anchor.setRow2(endRow); drawing.createPicture(anchor, pictureIdx);//用于创建图片对象 } catch (IOException e) { log.error("error:", e); } } public static void exporExcelExamQuestionBankTemplate(HttpServletResponse response, List subjectList) { try { ClassPathResource classPathResource = new ClassPathResource("excel/题库导入模版.xlsx"); InputStream inputStream = classPathResource.getInputStream(); XSSFWorkbook workbook = new XSSFWorkbook(inputStream); //部门/班组下拉列 XSSFSheet sheet2 = workbook.getSheet("科目名称"); if (subjectList.size() > 0) { for (int i = 0; i < subjectList.size(); i++) { XSSFRow row1 = sheet2.createRow(i); XSSFCell cell1 = row1.createCell(0); cell1.setCellType(CellType.STRING); cell1.setCellValue(subjectList.get(i).getName()); } } downLoadExcel("题库导入模版.xlsx", response, workbook); } catch (IOException e) { log.error("error:", e); } } public static void exporWorkerAttendByHw(HttpServletResponse response, List pageList, String basePath) { try { ClassPathResource classPathResource = new ClassPathResource("excel/班前教育信息.xlsx"); InputStream inputStream = classPathResource.getInputStream(); XSSFWorkbook workbook = new XSSFWorkbook(inputStream); XSSFSheet sheet = workbook.getSheet("班前教育"); for (int i = 2; i < pageList.size() + 2; i++) { for (int j = 0; j < 12; j++) { if (j == 0) { sheet.getRow(i).getCell(j).setCellValue(i - 1); } if (j == 1) { sheet.getRow(i).getCell(j).setCellValue(pageList.get(i - 2).getWorkerName()); } if (j == 2) { sheet.getRow(i).getCell(j).setCellValue(pageList.get(i - 2).getSexName()); } if (j == 3) { sheet.getRow(i).getCell(j).setCellValue(pageList.get(i - 2).getAge()); } if (j == 4) { sheet.getRow(i).getCell(j).setCellValue(pageList.get(i - 2).getEnterpriseName()); } if (j == 5) { if (StringUtils.isNotBlank(pageList.get(i - 2).getImageUrl())) { String imageUrl = pageList.get(i - 2).getImageUrl(); picture(basePath + imageUrl, sheet, i, i + 1, j, j + 1); } } if (j == 6) { sheet.getRow(i).getCell(j).setCellValue(pageList.get(i - 2).getCreateTime()); } } } downLoadExcel("班前教育信息.xlsx", response, workbook); } catch (IOException e) { log.error("error:", e); } } public static void exportExcelCarTemplate(List enterpriseInfos, List carTypes, File file) { try { ClassPathResource classPathResource = new ClassPathResource("excel/车辆导入模板.xlsx"); InputStream inputStream = classPathResource.getInputStream(); XSSFWorkbook workbook = new XSSFWorkbook(inputStream); //单位 XSSFSheet sheet1 = workbook.getSheet("单位"); if (enterpriseInfos.size() > 0) { for (int i = 0; i < enterpriseInfos.size(); i++) { XSSFRow row1 = sheet1.createRow(i); XSSFCell cell1 = row1.createCell(0); EnterpriseInfo obj = enterpriseInfos.get(i); cell1.setCellType(CellType.STRING); cell1.setCellValue(obj.getEnterpriseName()); } } //车种类型 XSSFSheet sheet2 = workbook.getSheet("车种类型"); if (carTypes.size() > 0) { for (int i = 0; i < carTypes.size(); i++) { XSSFRow row1 = sheet2.createRow(i); XSSFCell cell1 = row1.createCell(0); CarType obj = carTypes.get(i); cell1.setCellType(CellType.STRING); cell1.setCellValue(obj.getCarTypeName()); } } workbook.write(new FileOutputStream(file)); // downLoadExcel("车辆导入模板.xlsx", response, workbook); } catch (IOException e) { log.error("error:", e); } } /*public static void main(String[] args) { try { InputStream instream = new FileInputStream("D:/qqq.xlsx"); XSSFWorkbook workbook = new XSSFWorkbook(instream); XSSFSheet sheet = workbook.getSheetAt(0); XSSFCell cell=sheet.getRow(0).getCell(1, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); log.info("项目:"+cell.getStringCellValue()); XSSFCell cell2=sheet.getRow(3).getCell(8, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); log.info("评估时间:"+getValue(cell2)); XSSFCell cell3=sheet.getRow(10).getCell(10, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); log.info("实测实量得分:"+getValue(cell3)); XSSFCell cell4=sheet.getRow(14).getCell(10, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); log.info("质量风险得分:"+getValue(cell4)); XSSFCell cell5=sheet.getRow(23).getCell(10, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); log.info("安全文明得分:"+getValue(cell5)); XSSFCell cell6=sheet.getRow(32).getCell(2, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); log.info("标段评估结果:"+getValue(cell6)); workbook.close(); instream.close(); } catch (Exception e) { log.error("error:",e); } }*/ /** * 删除excel的列 * * @param workbook * @param sheetIndex * @param deleteColumnIndexes * @throws IOException */ public static void removeColumns(Workbook workbook, int sheetIndex, List deleteColumnIndexes) throws IOException { // 对列索引进行降序排序,以便从右到左删除,避免索引变化问题 deleteColumnIndexes.sort(Collections.reverseOrder()); Sheet sheet = workbook.getSheetAt(sheetIndex); for (int colIndex : deleteColumnIndexes) { removeColumn(sheet, colIndex); } } public static void removeColumns(String excelPath, int sheetIndex, List columnIndexes) throws IOException { // 对列索引进行降序排序,以便从右到左删除,避免索引变化问题 columnIndexes.sort(Collections.reverseOrder()); try (FileInputStream fis = new FileInputStream(excelPath); Workbook workbook = WorkbookFactory.create(fis)) { Sheet sheet = workbook.getSheetAt(sheetIndex); for (int colIndex : columnIndexes) { removeColumn(sheet, colIndex); } try (FileOutputStream fos = new FileOutputStream(excelPath)) { workbook.write(fos); } } } private static void removeColumn(Sheet sheet, int colIndex) { // 处理行数据 for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) { Row row = sheet.getRow(rowIndex); if (row != null) { removeCell(row, colIndex); // 将右侧单元格左移 shiftCellsLeft(row, colIndex); } } // 处理合并区域 processMergedRegions(sheet, colIndex); // 处理列宽 shiftColumnWidths(sheet, colIndex); } private static void removeCell(Row row, int colIndex) { Cell cell = row.getCell(colIndex); if (cell != null) { row.removeCell(cell); } } private static void shiftCellsLeft(Row row, int colIndex) { for (int i = colIndex + 1; i <= row.getLastCellNum(); i++) { Cell oldCell = row.getCell(i); if (oldCell != null) { Cell newCell = row.createCell(i - 1, oldCell.getCellType()); copyCellContent(oldCell, newCell); copyCellStyle(oldCell, newCell); row.removeCell(oldCell); } } } private static void copyCellContent(Cell oldCell, Cell newCell) { switch (oldCell.getCellType()) { case STRING: newCell.setCellValue(oldCell.getStringCellValue()); break; case NUMERIC: newCell.setCellValue(oldCell.getNumericCellValue()); break; case BOOLEAN: newCell.setCellValue(oldCell.getBooleanCellValue()); break; case FORMULA: newCell.setCellFormula(oldCell.getCellFormula()); break; case BLANK: newCell.setCellValue(""); // 将单元格值设置为空字符串 newCell.setCellType(CellType.BLANK); break; case ERROR: newCell.setCellErrorValue(oldCell.getErrorCellValue()); break; default: break; } } private static void copyCellStyle(Cell oldCell, Cell newCell) { Workbook workbook = newCell.getSheet().getWorkbook(); CellStyle newStyle = workbook.createCellStyle(); newStyle.cloneStyleFrom(oldCell.getCellStyle()); newCell.setCellStyle(newStyle); } private static void processMergedRegions(Sheet sheet, int colIndex) { for (int i = sheet.getNumMergedRegions() - 1; i >= 0; i--) { CellRangeAddress region = sheet.getMergedRegion(i); if (colIndex >= region.getFirstColumn() && colIndex <= region.getLastColumn()) { // 如果删除的列在合并区域内 if (region.getFirstColumn() == region.getLastColumn()) { // 如果合并区域只有一列,直接删除 sheet.removeMergedRegion(i); } else { // 缩小合并区域 region.setLastColumn(region.getLastColumn() - 1); sheet.removeMergedRegion(i); sheet.addMergedRegion(region); } } else if (colIndex < region.getFirstColumn()) { // 如果删除的列在合并区域左侧,将合并区域左移 region.setFirstColumn(region.getFirstColumn() - 1); region.setLastColumn(region.getLastColumn() - 1); sheet.removeMergedRegion(i); sheet.addMergedRegion(region); } // 如果删除的列在合并区域右侧,不需要处理 } } private static void shiftColumnWidths(Sheet sheet, int colIndex) { int maxColumn = 255; // Excel的最大列数 for (int i = colIndex; i < maxColumn; i++) { int width = sheet.getColumnWidth(i + 1); sheet.setColumnWidth(i, width); } // 清空最后一列 sheet.setColumnWidth(maxColumn, sheet.getDefaultColumnWidth()); } // 示例用法 public static void main(String[] args) { try { // 假设要删除第1列和第3列(0-based索引) long l = System.currentTimeMillis(); List columnsToRemove = new ArrayList<>(); for (int i = 13; i < 41 + 1; i++) { columnsToRemove.add(i); } removeColumns("C:\\Users\\Administrator\\Desktop\\1.xlsx", 0, columnsToRemove); System.out.println("列删除成功!" + (System.currentTimeMillis() - l)); } catch (IOException e) { e.printStackTrace(); } } /** * 合并Excel中的行 * * @param filePath Excel文件路径 * @param sheetIndex 工作表索引(0-based) * @param startRow 开始行索引(0-based) * @param endRow 结束行索引(0-based) * @throws IOException 文件操作异常 */ public static void mergeRows(String filePath, int sheetIndex, int startRow, int endRow) throws IOException { if (startRow > endRow) { throw new IllegalArgumentException("开始行索引不能大于结束行索引"); } try (FileInputStream fis = new FileInputStream(filePath); Workbook workbook = WorkbookFactory.create(fis)) { Sheet sheet = workbook.getSheetAt(sheetIndex); // 获取工作表的列数 int lastColumn = getLastColumn(sheet, startRow, endRow); // 逐列合并行 for (int colIndex = 0; colIndex <= lastColumn; colIndex++) { mergeCellsInColumn(sheet, colIndex, startRow, endRow); } // 保存修改后的文件 try (FileOutputStream fos = new FileOutputStream(filePath)) { workbook.write(fos); } } } /** * 获取工作表中指定行范围内的最大列数 */ private static int getLastColumn(Sheet sheet, int startRow, int endRow) { int maxColumn = -1; for (int rowIndex = startRow; rowIndex <= endRow; rowIndex++) { Row row = sheet.getRow(rowIndex); if (row != null) { int lastCellNum = row.getLastCellNum(); if (lastCellNum > maxColumn) { maxColumn = lastCellNum; } } } return maxColumn == -1 ? 0 : maxColumn - 1; } /** * 合并指定列中的行单元格 */ private static void mergeCellsInColumn(Sheet sheet, int colIndex, int startRow, int endRow) { // 检查是否需要合并(检查单元格内容是否相同) if (shouldMergeCells(sheet, colIndex, startRow, endRow)) { // 创建合并区域 CellRangeAddress mergeRegion = new CellRangeAddress( startRow, // 起始行 endRow, // 结束行 colIndex, // 起始列 colIndex // 结束列 ); // 添加合并区域到工作表 sheet.addMergedRegion(mergeRegion); // 设置合并后单元格的样式和内容 setMergedCellContentAndStyle(sheet, colIndex, startRow, endRow); } } /** * 检查指定列中的单元格内容是否相同(决定是否需要合并) */ private static boolean shouldMergeCells(Sheet sheet, int colIndex, int startRow, int endRow) { if (startRow == endRow) { return false; // 只有一行,不需要合并 } Object firstValue = null; for (int rowIndex = startRow; rowIndex <= endRow; rowIndex++) { Row row = sheet.getRow(rowIndex); if (row == null) { return false; // 有空行,不合并 } Cell cell = row.getCell(colIndex); Object currentValue = getCellValue(cell); if (firstValue == null) { firstValue = currentValue; } else if (!isEqual(firstValue, currentValue)) { return false; // 值不相同,不合并 } } return firstValue != null; // 所有值相同且不为空,可以合并 } /** * 获取单元格的值 */ private static Object getCellValue(Cell cell) { if (cell == null) { return null; } switch (cell.getCellType()) { case STRING: return cell.getStringCellValue(); case NUMERIC: return cell.getNumericCellValue(); case BOOLEAN: return cell.getBooleanCellValue(); case FORMULA: return cell.getCellFormula(); case BLANK: return ""; case ERROR: return cell.getErrorCellValue(); default: return null; } } /** * 比较两个值是否相等 */ private static boolean isEqual(Object value1, Object value2) { if (value1 == null && value2 == null) { return true; } if (value1 == null || value2 == null) { return false; } return value1.equals(value2); } /** * 设置合并后单元格的内容和样式 */ private static void setMergedCellContentAndStyle(Sheet sheet, int colIndex, int startRow, int endRow) { Row firstRow = sheet.getRow(startRow); if (firstRow == null) { firstRow = sheet.createRow(startRow); } Cell firstCell = firstRow.getCell(colIndex); if (firstCell == null) { firstCell = firstRow.createCell(colIndex); } // 设置合并区域的样式(使用第一个单元格的样式) CellStyle style = firstCell.getCellStyle(); // 为合并区域内的所有单元格设置相同的样式 for (int rowIndex = startRow; rowIndex <= endRow; rowIndex++) { Row row = sheet.getRow(rowIndex); if (row == null) { row = sheet.createRow(rowIndex); } Cell cell = row.getCell(colIndex); if (cell == null) { cell = row.createCell(colIndex); } cell.setCellStyle(style); } } /** * 重载方法:合并指定区域 */ public static void mergeRows(Workbook workbook, int sheetIndex, int startRow, int endRow, int startCol, int endCol) throws IOException { Sheet sheet = workbook.getSheetAt(sheetIndex); // 创建合并区域 CellRangeAddress mergeRegion = new CellRangeAddress( startRow, endRow, startCol, endCol ); // 添加合并区域 sheet.addMergedRegion(mergeRegion); // 设置合并区域样式 setMergedRegionStyle(sheet, mergeRegion); } /** * 设置合并区域的样式 */ private static void setMergedRegionStyle(Sheet sheet, CellRangeAddress region) { Row firstRow = sheet.getRow(region.getFirstRow()); if (firstRow == null) { firstRow = sheet.createRow(region.getFirstRow()); } Cell firstCell = firstRow.getCell(region.getFirstColumn()); if (firstCell == null) { firstCell = firstRow.createCell(region.getFirstColumn()); } CellStyle style = firstCell.getCellStyle(); // 为合并区域内的所有单元格设置相同样式 for (int row = region.getFirstRow(); row <= region.getLastRow(); row++) { Row currentRow = sheet.getRow(row); if (currentRow == null) { currentRow = sheet.createRow(row); } for (int col = region.getFirstColumn(); col <= region.getLastColumn(); col++) { Cell cell = currentRow.getCell(col); if (cell == null) { cell = currentRow.createCell(col); } cell.setCellStyle(style); } } } /** * 导出图片到excel * * @param workbook 工作簿 * @param sheetIndex 工作表索引 * @param bytesList 导出的图片字节数组列表 * @param startRow 开始行 * @param startCol 开始列 * @param direction 方向:1纵向2横向 */ public static void exportPicture(Workbook workbook, int sheetIndex, List bytesList, int startRow, int startCol, int direction) { if (workbook == null || bytesList == null || bytesList.isEmpty()) { return; } Sheet sheet = workbook.getSheetAt(sheetIndex); if (sheet == null) { return; } Drawing drawing = sheet.createDrawingPatriarch(); int rowIndex = startRow; int colIndex = startCol; for (byte[] bytes : bytesList) { if (bytes == null || bytes.length == 0) { continue; } try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) { // 获取图片格式(简单判断,实际可能需要更复杂的检测) int pictureType = getPictureType(bytes); // 添加图片到工作簿 int pictureIndex = workbook.addPicture(bytes, pictureType); // 创建锚点定位图片 ClientAnchor anchor; if (workbook instanceof XSSFWorkbook) { anchor = new XSSFClientAnchor(); } else if (workbook instanceof HSSFWorkbook) { anchor = new HSSFClientAnchor(); } else { anchor = workbook.getCreationHelper().createClientAnchor(); } // 设置图片位置 anchor.setCol1(colIndex); anchor.setRow1(rowIndex); anchor.setCol2(colIndex + 1); // 默认占1列宽度 anchor.setRow2(rowIndex + 1); // 默认占1行高度 // 插入图片 drawing.createPicture(anchor, pictureIndex); // 根据方向调整下一个图片的位置 if (direction == 1) { // 纵向排列:向下移动一行 rowIndex++; } else { // 横向排列:向右移动一列 colIndex++; } } catch (Exception e) { log.error("", e); } } } /** * 根据图片字节数组判断图片类型 */ private static int getPictureType(byte[] bytes) { if (bytes.length < 4) { return Workbook.PICTURE_TYPE_PNG; } // 检查文件头标识 if (bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xD8) { return Workbook.PICTURE_TYPE_JPEG; } else if (bytes[0] == (byte) 0x89 && bytes[1] == (byte) 0x50 && bytes[2] == (byte) 0x4E && bytes[3] == (byte) 0x47) { return Workbook.PICTURE_TYPE_PNG; } else if (bytes[0] == (byte) 0x42 && bytes[1] == (byte) 0x4D) { return Workbook.PICTURE_TYPE_DIB; } else if (bytes[0] == (byte) 0x00 && bytes[1] == (byte) 0x00 && bytes[2] == (byte) 0x01 && bytes[3] == (byte) 0x00) { return Workbook.PICTURE_TYPE_EMF; } else if (bytes[0] == (byte) 0x00 && bytes[1] == (byte) 0x00 && bytes[2] == (byte) 0x02 && bytes[3] == (byte) 0x00) { return Workbook.PICTURE_TYPE_WMF; } // 默认返回PNG类型 return Workbook.PICTURE_TYPE_PNG; } // // 示例用法 // public static void main(String[] args) { // try { // // 示例1:合并第2行到第5行的所有列(0-based索引) // mergeRows("C:\\Users\\Administrator\\Desktop\\heng.xlsx", 0, 0, 7); // // // 示例2:合并第3行到第6行的第2列(0-based索引) //// mergeRows("example.xlsx", 0, 2, 5, 1, 1); // // System.out.println("行合并成功!"); // } catch (IOException e) { // e.printStackTrace(); // } //} }