gpt4 book ai didi

java - 使用 Apache POI 在 Excel 工作簿之间复制单元格

转载 作者:行者123 更新时间:2023-12-04 01:32:05 26 4
gpt4 key购买 nike

我正在尝试使用最新版本的 Apache POI (4.1.2) 从一个工作簿的单元格复制到另一个工作簿。

如果两个工作簿都是 .xlsx 文件,则一切正常。但是如果源工作簿是一个(旧的).xls 文件而目标工作簿是一个.xlsx 文件,则以下代码将失败

// Copy style from old cell and apply to new cell
CellStyle newCellStyle = targetWorkbook.createCellStyle();
newCellStyle.cloneStyleFrom(sourceCell.getCellStyle());
targetCell.setCellStyle(newCellStyle);

抛出的异常是:

java.lang.IllegalArgumentException: Can only clone from one XSSFCellStyle to another, not between HSSFCellStyle and XSSFCellStyle

如果当文件(或Workbook 对象)是不同类型时我们不能使用cloneStyleFrom,我们如何转换一个HSSFCellStyle反对 XSSFCellStyle

最佳答案

您的问题“我们如何将 HSSFCellStyle 对象转换为 XSSFCellStyle?”的答案是:我们不能使用 apache poi 4.1.2 来做到这一点。正如 CellStyle.cloneStyleFrom 中明确指出的那样,这根本不受支持: “但是,两个 CellStyle 都需要属于同一类型(HSSFCellStyle 或 XSSFCellStyle)。”

另一个问题是:是否应该我们将一种单元格样式转换为另一种?或者 CellStyle.cloneStyleFrom 有哪些用例?在我看来没有。 Excel 对唯一单元格格式/单元格样式的计数有限制。参见 Excel specifications and limits .所以我们不应该为每个单元格创建一个单元格样式,因为那样会很快达到这些限制。因此,我们应该从源样式 style1 中获取样式属性,而不是克隆单元格样式,然后使用 CellUtil.setCellStyleProperties将这些样式属性设置为有问题的其他单元格。此方法尝试查找与单元格当前样式以及 properties 中的样式属性相匹配的现有 CellStyle。仅当工作簿不包含匹配样式时才会创建新样式。

由于您的问题标题是“使用 Apache POI 在 Excel 工作簿之间复制单元格”,我已经创建了一份工作草案,说明我将如何执行此操作。

下面的代码首先获取一个存在的Workbook.xls作为HSSFWorkbookwb1并创建一个新的XSSFWorkbookwb2。然后它遍历 wb1 第一张纸的所有单元格,并尝试将这些单元格复制到 wb2 第一张纸中。为此,有一种方法 copyCells(Cell cell1, Cell cell2) 使用 copyStyles(Cell cell1, Cell cell2)。后者从 cell1 获取的源样式 style1 获取样式属性,然后使用 CellUtil.setCellStyleProperties 将这些样式属性设置为 cell2 。对于复制字体,使用 copyFont(Font font1, Workbook wb2)。仅当该工作簿中尚不存在此类字体时,才会尝试在 wb2 中创建新字体。这是必要的,因为 Excel 中每个工作簿的唯一字体类型也有限制。

工作示例:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.util.CellUtil;

import java.io.FileInputStream;
import java.io.FileOutputStream;

import java.util.*;

class ExcelCopyCells {

static Font copyFont(Font font1, Workbook wb2) {
boolean isBold = font1.getBold();
short color = font1.getColor();
short fontHeight = font1.getFontHeight();
String fontName = font1.getFontName();
boolean isItalic = font1.getItalic();
boolean isStrikeout = font1.getStrikeout();
short typeOffset = font1.getTypeOffset();
byte underline = font1.getUnderline();

Font font2 = wb2.findFont(isBold, color, fontHeight, fontName, isItalic, isStrikeout, typeOffset, underline);
if (font2 == null) {
font2 = wb2.createFont();
font2.setBold(isBold);
font2.setColor(color);
font2.setFontHeight(fontHeight);
font2.setFontName(fontName);
font2.setItalic(isItalic);
font2.setStrikeout(isStrikeout);
font2.setTypeOffset(typeOffset);
font2.setUnderline(underline);
}

return font2;
}

static void copyStyles(Cell cell1, Cell cell2) {
CellStyle style1 = cell1.getCellStyle();
Map<String, Object> properties = new HashMap<String, Object>();

//CellUtil.DATA_FORMAT
short dataFormat1 = style1.getDataFormat();
if (BuiltinFormats.getBuiltinFormat(dataFormat1) == null) {
String formatString1 = style1.getDataFormatString();
DataFormat format2 = cell2.getSheet().getWorkbook().createDataFormat();
dataFormat1 = format2.getFormat(formatString1);
}
properties.put(CellUtil.DATA_FORMAT, dataFormat1);

//CellUtil.FILL_PATTERN
//CellUtil.FILL_FOREGROUND_COLOR
FillPatternType fillPattern = style1.getFillPattern();
short fillForegroundColor = style1.getFillForegroundColor(); //gets only indexed colors, no custom HSSF or XSSF colors
properties.put(CellUtil.FILL_PATTERN, fillPattern);
properties.put(CellUtil.FILL_FOREGROUND_COLOR, fillForegroundColor);

//CellUtil.FONT
Font font1 = cell1.getSheet().getWorkbook().getFontAt(style1.getFontIndexAsInt());
Font font2 = copyFont(font1, cell2.getSheet().getWorkbook());
properties.put(CellUtil.FONT, font2.getIndexAsInt());

//BORDERS
BorderStyle borderStyle = null;
short borderColor = -1;
//CellUtil.BORDER_LEFT
//CellUtil.LEFT_BORDER_COLOR
borderStyle = style1.getBorderLeft();
properties.put(CellUtil.BORDER_LEFT, borderStyle);
borderColor = style1.getLeftBorderColor();
properties.put(CellUtil.LEFT_BORDER_COLOR, borderColor);
//CellUtil.BORDER_RIGHT
//CellUtil.RIGHT_BORDER_COLOR
borderStyle = style1.getBorderRight();
properties.put(CellUtil.BORDER_RIGHT, borderStyle);
borderColor = style1.getRightBorderColor();
properties.put(CellUtil.RIGHT_BORDER_COLOR, borderColor);
//CellUtil.BORDER_TOP
//CellUtil.TOP_BORDER_COLOR
borderStyle = style1.getBorderTop();
properties.put(CellUtil.BORDER_TOP, borderStyle);
borderColor = style1.getTopBorderColor();
properties.put(CellUtil.TOP_BORDER_COLOR, borderColor);
//CellUtil.BORDER_BOTTOM
//CellUtil.BOTTOM_BORDER_COLOR
borderStyle = style1.getBorderBottom();
properties.put(CellUtil.BORDER_BOTTOM, borderStyle);
borderColor = style1.getBottomBorderColor();
properties.put(CellUtil.BOTTOM_BORDER_COLOR, borderColor);

CellUtil.setCellStyleProperties(cell2, properties);
}

static void copyCells(Cell cell1, Cell cell2) {
switch (cell1.getCellType()) {
case STRING:
/*
//TODO: copy HSSFRichTextString to XSSFRichTextString
RichTextString rtString1 = cell1.getRichStringCellValue();
cell2.setCellValue(rtString1); // this fails if cell2 is XSSF and rtString1 is HSSF
*/
String string1 = cell1.getStringCellValue();
cell2.setCellValue(string1);
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell1)) {
Date date1 = cell1.getDateCellValue();
cell2.setCellValue(date1);
} else {
double cellValue1 = cell1.getNumericCellValue();
cell2.setCellValue(cellValue1);
}
break;
case FORMULA:
String formula1 = cell1.getCellFormula();
cell2.setCellFormula(formula1);
break;

//case : //TODO: further cell types

}

copyStyles(cell1, cell2);

}

public static void main(String[] args) throws Exception {
Workbook wb1 = WorkbookFactory.create(new FileInputStream("Workbook.xls"));
Workbook wb2 = new XSSFWorkbook();

Sheet sheet1 = wb1.getSheetAt(0);
Sheet sheet2 = wb2.createSheet();

Set<Integer> columns = new HashSet<Integer>();
Row row2 = null;
Cell cell2 = null;
for (Row row1 : sheet1) {
row2 = sheet2.createRow(row1.getRowNum());
for (Cell cell1 : row1) {
columns.add(cell1.getColumnIndex());
cell2 = row2.createCell(cell1.getColumnIndex());
copyCells(cell1, cell2);
}
}

wb1.close();

for (Integer column : columns) {
sheet2.autoSizeColumn(column);
}

FileOutputStream out = new FileOutputStream("Workbook.xlsx");
wb2.write(out);
out.close();
wb2.close();
}
}

如果 Workbook.xls 如下所示:

enter image description here

然后生成的 Workbook.xlsx 如下所示:

enter image description here

注意:这是一个工作草案,需要完成。请参阅代码中的 TODO 注释。 RichTextString 需要考虑单元格值。需要考虑更多的细胞类型。

方法copyStyles 只提供复制数据格式、填充图案和填充前景色(仅针对索引颜色)、字体和边框。需要考虑更多的单元格样式属性。

关于java - 使用 Apache POI 在 Excel 工作簿之间复制单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60745266/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com