- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用最新版本的 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
作为HSSFWorkbook
wb1
并创建一个新的XSSFWorkbook
wb2
。然后它遍历 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
如下所示:
然后生成的 Workbook.xlsx
如下所示:
注意:这是一个工作草案,需要完成。请参阅代码中的 TODO
注释。 RichTextString
需要考虑单元格值。需要考虑更多的细胞类型。
方法copyStyles
只提供复制数据格式、填充图案和填充前景色(仅针对索引颜色)、字体和边框。需要考虑更多的单元格样式属性。
关于java - 使用 Apache POI 在 Excel 工作簿之间复制单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60745266/
我是一名优秀的程序员,十分优秀!