poi 不自动计算 设置单元格公式_java-Apache POI-读取由TEXT()公式格式化的单元格

仅当使用的Excel不是英语时,才会出现此问题.那么该公式实际上不是例如= TEXT(A2,“ yyyy-MM-dd”),而是例如在我的德语Excel中为= TEXT(A2,“ JJJJ-MM-TT”).

如您所见,尽管所有其他公式部分始终都是en_US语言环境,但TEXT函数中的format部分将始终与语言环境相关.这是因为格式部分位于公式内的字符串中,不会更改.因此,德语为= TEXT(A2,“ JJJJ-MM-TT”)(年份= Jahr,Day =标记),法语为= TEXT(A2,“ AAAA-MM-JJ”)(年份=Année,Day = Jour).

而且由于apache poi的FormulaEvaluator到目前为止还没有语言环境设置,因此该公式无法正确评估.

然后,我们有两种可能性.

首先,我们希望存储的单元格值应该是所需的字符串.因此,如果单元格公式以“ TEXT”开头并且包含“ JJJJ-MM-TT”,则不要进行评估,因为这样做不合适.而是从Excel的上一次评估中获取字符串单元格值.

其次,我们可以在公式中用en_US替换语言环境相关的格式部分,然后让apache poi求值.至少如果我们只想读取而不是重写Excel文件,则不会破坏Excel文件中的内容.

import org.apache.poi.ss.usermodel.*;

import org.apache.poi.ss.usermodel.CellType;

import org.apache.poi.ss.util.*;

import org.apache.poi.ss.formula.eval.ErrorEval;

import java.io.FileInputStream;

class ReadExcelExample {

private static String getString(Cell cell,FormulaEvaluator evaluator) {

if (cell == null) return "null";

String text = "";

switch (cell.getCellType()) {

//switch (cell.getCellTypeEnum()) {

case STRING:

text = cell.getRichStringCellValue().getString();

break;

case NUMERIC:

if (DateUtil.isCellDateFormatted(cell)) {

text = String.valueOf(cell.getDateCellValue());

} else {

text = String.valueOf(cell.getNumericCellValue());

}

break;

case BOOLEAN:

text = String.valueOf(cell.getBooleanCellValue());

break;

case FORMULA:

text = cell.getCellFormula();

//if formula is TEXT(...,"JJJJ-MM-TT") then do not evaluating:

if (cell.getCellFormula().startsWith("TEXT") && cell.getCellFormula().contains("JJJJ-MM-TT")) {

text = text + ": value got from cell = " + cell.getRichStringCellValue().getString();

} else {

CellValue cellValue = evaluator.evaluate(cell);

switch (cellValue.getCellType()) {

//switch (cellValue.getCellTypeEnum()) {

case STRING:

text = text + ": " + cellValue.getStringValue();

break;

case NUMERIC:

if (DateUtil.isCellDateFormatted(cell)) {

text = text + ": " + String.valueOf(DateUtil.getJavaDate(cellValue.getNumberValue()));

} else {

text = text + ": " + String.valueOf(cellValue.getNumberValue());

}

break;

case BOOLEAN:

text = text + ": " + String.valueOf(cellValue.getBooleanValue());

break;

case ERROR:

throw new RuntimeException("from CellValue: " + ErrorEval.getText(cellValue.getErrorValue()));

default:

throw new RuntimeException("unexpected cellValue type " + cellValue.getCellType());

}

}

break;

case ERROR:

throw new RuntimeException("from Cell: " + ErrorEval.getText(cell.getErrorCellValue()));

case BLANK:

text = "";

break;

default:

throw new RuntimeException("unexpected cell type " + cell.getCellType());

}

return text;

}

public static void main(String[] args) throws Exception {

//Workbook wb = WorkbookFactory.create(new FileInputStream("SAMPLE.xls"));

Workbook wb = WorkbookFactory.create(new FileInputStream("SAMPLE.xlsx"));

DataFormatter formatter = new DataFormatter(new java.util.Locale("en","US"));

FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();

Sheet sheet = wb.getSheetAt(0);

for (Row row : sheet) {

for (Cell cell : row) {

CellReference cellRef = new CellReference(row.getRowNum(),cell.getColumnIndex());

System.out.print(cellRef.formatAsString());

System.out.print(" - ");

String text = "";

try {

text = getString(cell,evaluator);

} catch (Exception ex) {

text = ex.toString();

}

System.out.println(text);

}

}

wb.close();

}

}

德文Excel:

XRYAG.png

结果:

A1 - Value

B1 - Formula

A2 - Fri Jan 11 00:00:00 CET 2019

B2 - TEXT(A2,"JJJJ-MM-TT"): value got from cell = 2019-01-11

A3 - 123.45

B3 - A3*2: 246.9

B4 - java.lang.RuntimeException: from CellValue: #DIV/0!

B5 - TODAY(): Fri Jan 11 00:00:00 CET 2019

B6 - B5=A2: true

A7 - java.lang.RuntimeException: from CellValue: #N/A

B8 - TEXT(TODAY(),"JJJJ-MM-TT"): value got from cell = 2019-01-11

英文Calc:

yk7Ll.png

结果:

A1 - Value

B1 - Formula

A2 - Fri Jan 11 00:00:00 CET 2019

B2 - TEXT(A2,"yyyy-MM-dd"): 2019-01-11

A3 - 123.45

B3 - A3*2: 246.9

B4 - java.lang.RuntimeException: from CellValue: #DIV/0!

B5 - TODAY(): Fri Jan 11 00:00:00 CET 2019

B6 - B5=A2: true

A7 - java.lang.RuntimeException: from CellValue: #N/A

B8 - TEXT(TODAY(),"yyyy-MM-dd"): 2019-01-11

代码第二种方法(将与语言环境相关的格式部分替换为en_US一种):

import org.apache.poi.ss.usermodel.*;

import org.apache.poi.ss.usermodel.CellType;

import org.apache.poi.ss.util.*;

import java.io.FileInputStream;

import java.util.Locale;

class ExcelEvaluateTEXTDiffLocales {

private static String getString(Cell cell,DataFormatter formatter,FormulaEvaluator evaluator,Locale locale) {

String text = "";

if (cell.getCellType() == CellType.FORMULA) {

String cellFormula = cell.getCellFormula();

text += cellFormula + ":= ";

if (cellFormula.startsWith("TEXT")) {

int startFormatPart = cellFormula.indexOf('"');

int endFormatPart = cellFormula.lastIndexOf('"') + 1;

String formatPartOld = cellFormula.substring(startFormatPart,endFormatPart);

String formatPartNew = formatPartOld;

if ("de".equals(locale.getLanguage())) {

formatPartNew = formatPartNew.replace("T","D"); // Tag = Day

// Monat = Month

formatPartNew = formatPartNew.replace("J","Y"); // Jahr = Year

//...

} else if ("fr".equals(locale.getLanguage())) {

formatPartNew = formatPartNew.replace("J","D"); // Jour = Day

// Mois = Month

formatPartNew = formatPartNew.replace("A","Y"); // Année = Year

//...

} //...

cellFormula = cellFormula.replace(formatPartOld,formatPartNew);

cell.setCellFormula(cellFormula);

}

}

try {

text += formatter.formatCellValue(cell,evaluator);

} catch (org.apache.poi.ss.formula.eval.NotImplementedException ex) {

text += ex.toString();

}

return text;

}

public static void main(String[] args) throws Exception {

//Workbook wb = WorkbookFactory.create(new FileInputStream("SAMPLE.xls"));

Workbook wb = WorkbookFactory.create(new FileInputStream("SAMPLE.xlsx"));

Locale locale = new Locale("fr","CH");

DataFormatter formatter = new DataFormatter(locale);

FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();

Sheet sheet = wb.getSheetAt(0);

for (Row row : sheet) {

for (Cell cell : row) {

CellReference cellRef = new CellReference(row.getRowNum(),cell.getColumnIndex());

System.out.print(cellRef.formatAsString());

System.out.print(" - ");

String text = "";

text = getString(cell,formatter,evaluator,locale);

System.out.println(text);

}

}

wb.close();

}

}

法语Calc:

xNwTK.png

结果:

A1 - Value

B1 - Formula

A2 - 1/11/2019

B2 - TEXT(A2,"AAAA-MM-JJ"):= 2019-01-11

A3 - 123.45

B3 - A3*2:= 246.9

B4 - 1/A4:= #DIV/0!

B5 - TODAY():= 1/12/2019

B6 - B5=A2:= FALSE

A7 - NA():= #N/A

B8 - TEXT(TODAY(),"AAAA-MM-JJ"):= 2019-01-12

提示:这里使用的apache poi版本是4.0.1.较低的版本可能会有进一步的评估问题.


版权声明:本文为weixin_39989688原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。