Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java POI公式计算器_Java_Apache Poi - Fatal编程技术网

Java POI公式计算器

Java POI公式计算器,java,apache-poi,Java,Apache Poi,我正在使用POI 3.8来读取excel我正在使用POI的用户模型api,该api能够读取HSSF和XSSF,但在评估公式时存在一些问题POI 3.8不支持Excle的IFEROR函数。是否有任何替代方法,我不想将公式转换为旧版本excel不支持的ISERROR caz 我知道POI 3.8不支持IFERROR,但我能做些什么来实现它呢?提前感谢 以下是例外 线程“main”org.apache.poi.ss.formula.eval.NotImplementedException中出现异常:计

我正在使用POI 3.8来读取excel我正在使用POI的用户模型api,该api能够读取HSSF和XSSF,但在评估公式时存在一些问题POI 3.8不支持Excle的IFEROR函数。是否有任何替代方法,我不想将公式转换为旧版本excel不支持的ISERROR caz

我知道POI 3.8不支持IFERROR,但我能做些什么来实现它呢?提前感谢

以下是例外 线程“main”org.apache.poi.ss.formula.eval.NotImplementedException中出现异常:计算单元格Sheet1时出错!一层楼 位于org.apache.poi.ss.formula.WorkbookEvaluator.addExceptionInfo(WorkbookEvaluator.java:356) 位于org.apache.poi.ss.formula.WorkbookEvaluator.evaluateAny(WorkbookEvaluator.java:297) 位于org.apache.poi.ss.formula.WorkbookEvaluator.evaluate(WorkbookEvaluator.java:229) 位于org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator.evaluateFormulaCellValue(XSSFFormulaEvaluator.java:264) 位于org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator.evaluate(XSSFFormulaEvaluator.java:117) 位于TestFormula.cellValue(TestFormula.java:48) 位于TestFormula.loadCell(TestFormula.java:37) 在TestFormula.loadRows(TestFormula.java:29)中 TestFormula.testRun(TestFormula.java:22) 位于fisvalidater.main(fisvalidater.java:27) 原因:org.apache.poi.ss.formula.eval.NotImplementedException:IFERROR 位于org.apache.poi.ss.formula.atp.AnalysisToolPak$NotImplemented.evaluate(AnalysisToolPak.java:40) 位于org.apache.poi.ss.formula.UserDefinedFunction.evaluate(UserDefinedFunction.java:64) 在org.apache.poi.ss.formula.operationevaluationFactory.evaluate(operationevaluationFactory.java:129)上 位于org.apache.poi.ss.formula.WorkbookEvaluator.evaluateFormula(WorkbookEvaluator.java:491)
在org.apache.poi.ss.formula.WorkbookEvaluator.evaluateAny(WorkbookEvaluator.java:287)

编辑:我的答案已经过时,因为更新的ApachePOIAPI支持IFERROR()


我最近也有这个问题。 所以我为它写了一篇小文章。希望这有助于:

注意 IFERROR(值,如果出错则为值) 工作原理与 IF(iError(值),value\u IF\u error,value)

所以我在计算这些公式之前先替换了它们。 您只需调用replaceiferrorformals(),它将自动遍历整个工作表

public static final int SIZE = "IFERROR(".length();   

private void replaceIfErrorFormulas(Sheet pSheet)
{
   for (Row row : pSheet)
   {
      for (Cell cell : row)
      {
         if ((cell != null) && 
             (cell.getCellType() == Cell.CELL_TYPE_FORMULA) &&
             (cell.getCellFormula().indexOf("IFERROR") != -1))
         {
            cell.setCellFormula(buildFormulaString(cell.getCellFormula()));
         }
      }
   }
}

private String buildFormulaString(String pFormula)
{
   if (pFormula.indexOf("IFERROR") == -1)
   {
      return pFormula;
   }

   String[] values = new String[2]; // will hold value, value_if_error
   char[] tokens = pFormula.toCharArray();
   int length = computeLength(pFormula); // length of IFERROR substring
   int iBegin = pFormula.indexOf("IFERROR");
   int iEnd = iBegin + length - 1;
   assert (iEnd < pFormula.length());      
   int iParam = 0;  // 0: value; 1: value_if_error
   int numPar = 0;  // number of parentheses

   // Split the parameters into VALUE and VALUE_IF_ERROR in values[]
   for (int i = iBegin; i < (length + iBegin) ; i++)
   {
      if (tokens[i] == '(')
      {
         values[iParam] += tokens[i];
         numPar++;
      }
      else if (tokens[i] == ')')
      {
         if (iParam < 1)
         {
            values[iParam] += tokens[i];
         }
         numPar--;
      }
      else if (Character.getType(tokens[i]) == Character.MATH_SYMBOL)
      {
         values[iParam] += tokens[i];
      }
      else if (tokens[i] == ',')
      {
         if (numPar > 1)
         {
            values[iParam] += tokens[i];
         }
         else
         {
            values[iParam++] += ')';
            numPar--;
         }
      }
      else
      {
         values[iParam] += tokens[i];
      }
      if (numPar < 0 && iParam == 1)
      {
         break;
      }
   }

   // Re-assign those parameters back to strings, removing the null character 
   String value        = values[0];
   String valueIfError = values[1];
   value        = value.substring(4 + SIZE - 1);
   valueIfError = valueIfError.substring(4);


   // Build new Formula that is equivalent to the old one.
   String newFormula = "IF(ISERROR(" + value + ")," 
                                     + valueIfError + ","
                                     + value +")";

   // Concatenate the untouched parts of the old formula to the new one      
   String left = pFormula.substring(0, iBegin);
   String right = pFormula.substring(iEnd + 1, pFormula.length());
   newFormula = left + newFormula + right;

   return buildFormulaString(newFormula);
}

// by checking the parentheses proceededing IFERROR, this method
// determines what is the size of the IFERROR substring
private int computeLength(String pFormula) 
{
   int length = SIZE;
   int numPar = 1; // Number of parentheses
   int iStart = pFormula.indexOf("IFERROR");
   char [] tokens = pFormula.toCharArray();

   for (int i = length + iStart; i < pFormula.length(); i++)
   {
      if (numPar == 0)
          break;
      if (tokens[i] == '(')
          numPar++;
      else if (tokens[i] == ')')
          numPar--;
      length++;
   }
   return length;
}
public static final int SIZE=“IFERROR”(.length();
专用void replaceErrorFormulas(表pSheet)
{
用于(行:pSheet)
{
用于(单元格:行)
{
如果((单元格!=null)和
(cell.getCellType()==cell.cell\u类型\u公式)&&
(cell.getCellFormula().indexOf(“IFERROR”)!=-1))
{
setCellFormula(buildFormulaString(cell.getCellFormula());
}
}
}
}
私有字符串buildFormulaString(字符串pFormula)
{
if(公式索引(“IFERROR”)=-1)
{
返回公式;
}
String[]values=新字符串[2];//将保留值,如果值出错,则值为
char[]tokens=pFormula.toCharArray();
int length=computeLength(pFor公式);//错误子串的长度
int iBegin=公式索引(“IFERROR”);
int iEnd=iBegin+长度-1;
断言(iEnd1)
{
值[ipram]+=tokens[i];
}
其他的
{
值[IPRAM++]+=');
努帕尔--;
}
}
其他的
{
值[ipram]+=tokens[i];
}
如果(numPar<0&&iParam==1)
{
打破
}
}
//将这些参数重新分配回字符串,删除空字符
字符串值=值[0];
字符串valueIfError=值[1];
value=value.substring(4+SIZE-1);
valueIfError=valueIfError.子字符串(4);
//建立与旧公式等效的新公式。
字符串newFormula=“如果(ISERROR(“+value+”)”
+值错误+“,”
+值+”;
//将旧公式的未触及部分连接到新公式
字符串left=pFormula.substring(0,iBegin);
String right=pFormula.substring(iEnd+1,pFormula.length());
新公式=左+新公式+右;
返回buildFormulaString(newFormula);
}
//通过检查括号PROCEEDING IFERROR,此方法
//确定IFERROR子字符串的大小
专用整数计算长度(字符串公式)
{
整数长度=大小;
int numPar=1;//括号数
int iStart=公式索引(“IFERROR”);
char[]tokens=pFormula.toCharArray();
对于(int i=length+iStart;i

更新:我已将公式修改得更好=D Before:仅当公式位于字符串开头,并且除此之外没有任何其他公式或参数时,它才会替换公式。 After:现在它搜索整个字符串中的IFERROR实例,并将它们全部替换为=D

IFERROR