Dón*_*nal 3 java excel apache-poi apache-poi-4
我正在尝试使用最新版本的 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);
Run Code Online (Sandbox Code Playgroud)
抛出的异常是:
java.lang.IllegalArgumentException:只能从一个 XSSFCellStyle 克隆到另一个 XSSFCellStyle,不能在 HSSFCellStyle 和 XSSFCellStyle 之间克隆
cloneStyleFrom如果当文件(或Workbook对象)具有不同类型时我们无法使用,那么我们如何将HSSFCellStyle对象转换为XSSFCellStyle?
HSSFCellStyle您的问题“我们如何将对象转换为XSSFCellStyle?”的答案 是:我们不能使用apache poi 4.1.2. 正如CellStyle.cloneStyleFrom中明确指出的那样,这根本不受支持:“但是,两个 CellStyle 都需要具有相同的类型(HSSFCellStyle 或 XSSFCellStyle)。”
另一个问题是:我们是否应该将一种单元格样式转换为另一种单元格样式?CellStyle.cloneStyleFrom或者到底有哪些用例?我认为没有。Excel独特的单元格格式/单元格样式的计数存在限制。请参阅Excel 规范和限制。因此,我们不应该为每个单元格创建单个单元格样式,因为这样很快就会达到这些限制。因此,我们不应该克隆单元格样式,而应该从源样式获取样式属性style1,然后使用CellUtil.setCellStyleProperties将这些样式属性设置为相关的其他单元格。此方法尝试查找与CellStyle单元格当前样式以及 中的样式属性相匹配的现有样式properties。仅当工作簿不包含匹配的样式时才会创建新样式。
由于您的问题标题是“使用 Apache POI 在 Excel 工作簿之间复制单元格”,因此我创建了一份关于如何执行此操作的工作草案。
以下代码首先获取现有的Workbook.xlsasHSSFWorkbook wb1并创建一个新的XSSFWorkbook wb2. 然后,它循环遍历 的第一张纸的所有单元格wb1,并尝试将这些单元格复制到 的第一张纸中wb2。为此,有一种方法copyCells(Cell cell1, Cell cell2)使用copyStyles(Cell cell1, Cell cell2). 后者从style1获取的源样式中获取样式属性cell1,然后用于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();
}
}
Run Code Online (Sandbox Code Playgroud)
如果Workbook.xls看起来像这样:
然后结果Workbook.xlsx看起来像这样:
注:这是一份工作草案,需要完成。请参阅TODO代码中的注释。RichTextString需要考虑单元格值。需要考虑更多的细胞类型。
方法copyStyles仅提供复制数据格式、填充图案和填充前景色(仅适用于索引颜色)、字体和边框。需要考虑更多的单元样式属性。
| 归档时间: |
|
| 查看次数: |
4489 次 |
| 最近记录: |