我的Java应用程序读取一个xls文件并将其显示在JTable上。到目前为止,一切都很好。

当我尝试保存工作表时,我遍历了JTable中的row,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);


这是可行的,但是我丢失了单元的原始布局,例如它的颜色。

如果单元格是带有评估错误的公式,如何正确setCellType

最佳答案

我在poi-apache的邮件列表中找到了这个:


  设置公式的值时有两种可能的情况
  细胞;
  
  
  更新公式的预先计算的值。如果单元格包含公式,则cell.setCellValue只会更新预先计算的
  (缓存的)公式值,公式本身保留,并且单元格类型
  不变
  删除公式并将单元格类型更改为字符串或数字:
  
  
  cell.setCellFormula(null); //删除公式
  
  然后cell.setCellValue(“我改变了!我的类型现在是CELL_TYPE_STRING”“);
  或cell.setCellValue(200); // NA()不存在,实际值为200
  
  我认为我们可以针对情况(1)改善cell.setCellValue。如果新
  值与公式类型冲突,则IllegalArgumentException应该
  被抛出。
  
  此致Yegor


不过,对我来说,这确实是一种解决方法。但是现在一切正常。

在任何cell.setCellFormula(null)之前的setCellType应防止转换失败,因为第一个将丢弃缓存的内容。

08-16 04:24