http://blog.sina.com.cn/s/blog_6151984a0100sczi.html

  • 测试环境:

当前EXCEL文件: workbook.xls

假设一个CELL的计算式如下:

='C:\testFB\[workbook1.xls]Test2'!B2+'C:\testFB\[workbook1.xls]测试1'!C3



  • 调用步骤:

1.不仅要打开当前EXCEL文档(本例是workbook.xls),也要打开所有计算式FORMULA引用的EXCEL文档(workbook1.xls)

不仅要为当前EXCEL文档建立HSSFFormulaEvaluator对象,也要为所有计算式FORMULA引用的EXCEL文档建立HSSFFormulaEvaluator对象

String ROOT = "d:\\testFB\\"; 


 HSSFWorkbook[] wbs = new HSSFWorkbook[files.length];
   HSSFFormulaEvaluator[] evaluators =new HSSFFormulaEvaluator[files.length]; 
 FileInputStream fileIn = null;
   FileOutputStream fileOut = null;       
   for(int i=0;i<files.length;i++){
      fileIn = new FileInputStream(files[i]);
      POIFSFileSystem fs = new POIFSFileSystem(fileIn);
     wbs[i] = new HSSFWorkbook(fs);     evaluators[i] = new HSSFFormulaEvaluator(wbs[i]);  }


2. 设置Evaluator对象环境

HSSFFormulaEvaluator.setupEnvironment(files, evaluators);


3. 对计算式进行Evalutor计算


for(int i=0;i<wbs[0].getNumberOfSheets();i++){
         sheet1 = wbs[0].getSheetAt(i);
         for (Cell cell : row) {
             switch(cell.getCellType()) {
                 case Cell.CELL_TYPE_STRING:
                   System.out.println("CELL_TYPE_STRING |"+cell.getRichStringCellValue().getString());
                   break;
                 case Cell.CELL_TYPE_NUMERIC:
                   if(DateUtil.isCellDateFormatted(cell)) {
                     System.out.println("CELL_TYPE_NUMERIC |"+cell.getDateCellValue());
                   } else {
                     System.out.println("CELL_TYPE_NUMERIC |"+cell.getNumericCellValue());
                   }
                   break;
                 case Cell.CELL_TYPE_BOOLEAN:
                   System.out.println("CELL_TYPE_BOOLEAN |"+cell.getBooleanCellValue());
                   break;
                                 System.out.print("Cell.CELL_TYPE_FORMULA |"+cell.getCellFormula()+"|");  
                   CellValue cellValue = evaluators[0].evaluate(cell);                  // 或者evaluators[0].evaluateFormulaCell(cell);                  switch (cellValue.getCellType()) {
                    case Cell.CELL_TYPE_BOOLEAN:
                        System.out.println(cellValue.getBooleanValue());
                        break;
                    case Cell.CELL_TYPE_NUMERIC:
                        System.out.println(cellValue.getNumberValue());
                        break;
                    case Cell.CELL_TYPE_STRING:
                        System.out.println(cellValue.getStringValue());
                        break;
                    case Cell.CELL_TYPE_BLANK:
                        break;
                    case Cell.CELL_TYPE_ERROR:
                        break;
    
                    // CELL_TYPE_FORMULA will never happen
                    case Cell.CELL_TYPE_FORMULA:
                        break;
                                    break;
                 default:
                   System.out.println();
             }// end of switch
        }
        
       }



  • 原理  

    采用APACHE <wbr>POI操作EXCEL文件--计算式调用另一文件

  • 所以问题的关键是:

从CELL的FORMULA计算式获得何种格式的文件名,而POI系统会以该格式的文件名从 Formula Evaluator Environment获取对应的Evaluator



现在存在的问题是,EXCEL CELL的计算式与POI 解析出的计算式是不同的

现象1:

当前文件和计算式调用文件在同一路径下时,POI是忽略路径的

EXCEL文件

POI解析出的FORMULA

='C:\testFB\[workbook1.xls]Test2'!B2+'C:\testFB\[workbook1.xls]测试1'!C3
'[workbook1.xls]Test2'!B2+'[workbook1.xls]测试1'!C3

现象2:

当前文件和计算式调用文件不在同一路径下时,POI会获取路径,但路径显示方式比较特殊

POI没解析出'C:'

POI没解析出'\'或'/',而代之以ASCII码2()和3()

EXCEL文件

POI解析出的FORMULA

='C:\testFB1\[workbook1.xls]Test2'!B2+'C:\testFB1\[workbook1.xls]测试1'!C3
'[testFB1workbook1.xls]Test2'!B2+'[testFB1workbook1.xls]测试1'!C3

由于新浪博客有些特殊字符不能显示,下面附上截图.

采用APACHE <wbr>POI操作EXCEL文件--计算式调用另一文件之II


现象1的解决办法:

因为POI解析出的文件名是不含路径的,根据原理,那么在Formula Evaluator Environment中的文件名必须与之匹配,不含路径

String[] files = {"workbook.xls","workbook1.xls"};
...
HSSFFormulaEvaluator.setupEnvironment(files, evaluators);


现象2的解决办法:

因为POI解析出的文件名包含路径,但不包含驱动器名,且路径斜杠变成ASCII码2和3

根据原理,那么在Formula Evaluator Environment中的文件名必须与之匹配,所以最好先通过cell.getCellFormula()获知POI解析出FORMULA,然后把文件名设置入Environment.

例我们System.out.println(cell.getCellFormula())得到如下:

'[testFB1workbook1.xls]Test2'!B2+'[testFB1workbook1.xls]测试1'!C3

则我们需要设置Environment如下:

String[] filePaths = {"[testFBworkbook.xls","[testFB1workbook1.xls"};
...
HSSFFormulaEvaluator.setupEnvironment(filePaths,evaluators);

而且我们要把文件存在C:盘下,不要存在其他盘下


由于新浪博客有些特殊字符不能显示,下面附上截图.

采用APACHE <wbr>POI操作EXCEL文件--计算式调用另一文件之II