我的Java应用程序读取xls文件并将其呈现在JTable上。到现在为止还挺好。
当我尝试保存我的工作表时,我在我的JTable中迭代行,col并且:
String str = (String) Table.getValueAt(row, col);
HSSFRow thisrow = sheet.getRow(row);
HSSFCell thiscell = thisrow.getCell(col);
if(thiscell==null) thiscell = thisrow.createCell(col);
switch(inferType(str)) {
case "formula":
thiscell.setCellType(Cell.CELL_TYPE_FORMULA);
thiscell.setCellFormula(str.substring(1));
break;
case "numeric":
thiscell.setCellType(Cell.CELL_TYPE_NUMERIC);
thiscell.setCellValue(Double.parseDouble(str));
break;
case "text":
thiscell.setCellType(Cell.CELL_TYPE_STRING);
thiscell.setCellValue(str);
break;
}
但是当我跑过一个最初是公式的细胞时,比如A1/B1
,那就是#DIV/0!
,setCellType
失败了。
通过大量调查,我发现当调用setCellType
时,它会尝试将旧内容转换为新类型。但是,这对我来说似乎不是问题,因为每个表格公式单元格都已经是xls中的公式。因此,我从来没有真正改变类型。
即便如此,当我在一个已经是公式的单元格上调用setCellType(Cell.CELL_TYPE_FORMULA)
,但它被评估为#DIV/0!
时,我得到转换异常。
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Cannot get a numeric value from a error formula cell
at org.apache.poi.hssf.usermodel.HSSFCell.typeMismatch(HSSFCell.java:648)
at org.apache.poi.hssf.usermodel.HSSFCell.checkFormulaCachedValueType(HSSFCell.java:653)
at org.apache.poi.hssf.usermodel.HSSFCell.getNumericCellValue(HSSFCell.java:678)
at org.apache.poi.hssf.usermodel.HSSFCell.setCellType(HSSFCell.java:317)
at org.apache.poi.hssf.usermodel.HSSFCell.setCellType(HSSFCell.java:283)
实际上我唯一的解决方法是,在setCellType
之前:
if(thiscell.getCachedFormulaResultType()==Cell.CELL_TYPE_ERROR)
thiscell = thisrow.createCell(col);
这是工作,但我失去了细胞的原始布局,例如这是颜色。
如果Cell是一个评估错误的公式,我怎么能正确地setCellType
?
我在poi-apache的邮件列表中找到了这个:
为公式单元格设置值时有两种可能的情况;
- 更新公式的预先计算的值。如果单元格包含公式,则cell.setCellValue只更新预先计算的(缓存的)公式值,公式本身保留,单元格类型不会更改
- 删除公式并将单元格类型更改为String或Number:
cell.setCellFormula(NULL); //删除公式
然后是cell.setCellValue(“我改了!我的类型现在是CELL_TYPE_STRING”“);或者是cell.setCellValue(200); // NA()消失了,实际值是200
我认为我们可以为case(1)改进cell.setCellValue。如果新值与公式类型冲突,则应抛出IllegalArgumentException。
问候,叶戈尔
不过,它确实感觉像是一种解决方法。但现在一切正常。
在任何cell.setCellFormula(null)
之前setCellType
应该防止转换失败,因为第一个将丢弃缓存的内容。