要支持复制图片类型,你可以使用CreationHelper
和Drawing
对象来处理。下面是优化后的代码示例:
private void mergeFileSheet(File originalFile, List<String> fileUrls) throws Exception {
try (FileInputStream fis = new FileInputStream(originalFile);
Workbook originalWorkbook = new XSSFWorkbook(fis)) {
for (String fileUrl : fileUrls) {
// 下载附件
byte[] fileContent = fastDfsClient.download(fileUrl);
String originalFilename = fastDfsClient.getOriginalFilename(fileUrl);
try (ByteArrayInputStream bais = new ByteArrayInputStream(fileContent);
Workbook attachmentWorkbook = new XSSFWorkbook(bais)) {
// 获取附件中sheet数量
int numberOfSheets = attachmentWorkbook.getNumberOfSheets();
int sheetIndex = 0;
for (int i = 0; i < numberOfSheets; i++) {
// 附件sheet
Sheet attachmentSheet = attachmentWorkbook.getSheetAt(i);
// 判断sheet是否为空
boolean sheetEmpty = ExcelUtil.isSheetEmpty(attachmentSheet);
if(sheetEmpty){
continue;
}
sheetIndex++;
String newSheetName = "附件-" + originalFilename.substring(0, originalFilename.lastIndexOf(".")) + "-" + sheetIndex;
// 创建新的sheet页来放置附件内容
Sheet newSheet = originalWorkbook.createSheet(newSheetName);
// 复制行及单元格内容和样式(包括图片)
copyRowsWithImages(attachmentSheet, newSheet, attachmentWorkbook, originalWorkbook);
}
}
}
// 写入修改后的Workbook到文件
try (FileOutputStream fos = new FileOutputStream(originalFile)) {
originalWorkbook.write(fos);
}
}
}
private void copyRowsWithImages(Sheet sourceSheet, Sheet targetSheet, Workbook sourceWorkbook, Workbook targetWorkbook) {
Drawing<?> drawing = targetSheet.createDrawingPatriarch();
for (Row sourceRow : sourceSheet) {
Row targetRow = targetSheet.createRow(sourceRow.getRowNum());
// 遍历源行的每个单元格
for (int i = sourceRow.getFirstCellNum(); i <= sourceRow.getLastCellNum(); i++) {
Cell sourceCell = sourceRow.getCell(i);
// 如果源单元格为null,则不创建新单元格
if (sourceCell != null) {
Cell targetCell = targetRow.createCell(i, sourceCell.getCellType());
// 复制单元格样式
CellStyle sourceCellStyle = sourceCell.getCellStyle();
CellStyle targetCellStyle = targetWorkbook.createCellStyle();
targetCellStyle.cloneStyleFrom(sourceCellStyle);
targetCell.setCellStyle(targetCellStyle);
// 根据单元格类型复制值
switch (sourceCell.getCellTypeEnum()) {
case STRING:
targetCell.setCellValue(sourceCell.getStringCellValue());
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(sourceCell)) {
targetCell.setCellValue(sourceCell.getDateCellValue());
} else {
targetCell.setCellValue(sourceCell.getNumericCellValue());
}
break;
case BOOLEAN:
targetCell.setCellValue(sourceCell.getBooleanCellValue());
break;
case FORMULA:
// 如果单元格是公式,则复制公式本身
targetCell.setCellFormula(sourceCell.getCellFormula());
break;
case BLANK:
// 如果目标单元格为空白,可以直接设置为空白类型
targetCell.setBlank();
break;
default:
// 默认处理
}
// 复制单元格中的图片(如果存在)
if (sourceCell.getCellTypeEnum() == CellType.FORMULA && sourceCell.getCachedFormulaResultTypeEnum() == CellType.STRING) {
String cellValue = sourceCell.getStringCellValue();
List<String> imagePaths = extractImagePaths(cellValue);
for (String imagePath : imagePaths) {
byte[] imageData = getImageData(imagePath); // 根据路径获取图片数据
// 在目标工作簿中创建新的图片,并设置位置和大小
int pictureIndex = targetWorkbook.addPicture(imageData, Workbook.PICTURE_TYPE_PNG);
CreationHelper creationHelper = targetWorkbook.getCreationHelper();
ClientAnchor anchor = creationHelper.createClientAnchor();
anchor.setCol1(targetCell.getColumnIndex());
anchor.setRow1(targetRow.getRowNum());
// 插入图片到目标单元格
Picture picture = drawing.createPicture(anchor, pictureIndex);
picture.resize(); // 调整图片大小
}
}
}
}
}
}
以上代码假设你已经实现了以下辅助方法:
ExcelUtil.isSheetEmpty(Sheet sheet)
:用于判断一个Sheet是否为空。extractImagePaths(String cellValue)
:从公式类型的单元格值中提取包含图片路径的字符串列表。byte[] getImageData(String imagePath)
:根据给定的图片路径获取对应的图像数据。
这样就可以在复制行及单元格内容和样式的同时,将图片也复制到目标文件中了。请注意,上述代码仅适用于XLSX格式的Excel文件(使用XSSFWorkbook
和SXSSFWorkbook
)。
希望以上代码能对你有所帮助!
内容由零声教学AI助手提供,问题来源于学员提问