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
}
}
|
- 原理
- 所以问题的关键是:
从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
|
由于新浪博客有些特殊字符不能显示,下面附上截图.
现象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:盘下,不要存在其他盘下
由于新浪博客有些特殊字符不能显示,下面附上截图.