Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.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 复制时Apache POI更新公式引用_Java_Excel_Excel Formula_Apache Poi - Fatal编程技术网

Java 复制时Apache POI更新公式引用

Java 复制时Apache POI更新公式引用,java,excel,excel-formula,apache-poi,Java,Excel,Excel Formula,Apache Poi,在Apache POI中复制公式时,是否有更新公式引用的方法 在Excel中,假设第1行有公式=A1/B1。如果你复制粘贴它,比如在第5行,公式变成=A5/B5. 在ApachePOI中,如果运行 r5.getCell(2).setCellType(CellType.FORMULA); r5.getCell(2).setCellFormula(r1.getCell(2).getCellFormula()); 公式仍然是=A1/B1您的代码没有复制/粘贴内容,而是从一个单元格获取公式字符串,并将

在Apache POI中复制公式时,是否有更新公式引用的方法

在Excel中,假设第1行有公式
=A1/B1
。如果你复制粘贴它,比如在第5行,公式变成
=A5/B5.

在ApachePOI中,如果运行

r5.getCell(2).setCellType(CellType.FORMULA);
r5.getCell(2).setCellFormula(r1.getCell(2).getCellFormula());

公式仍然是
=A1/B1

您的代码没有复制/粘贴内容,而是从一个单元格获取公式字符串,并将该公式字符串精确地设置到另一个单元格。这不会更改公式字符串。它应该怎么做呢

因此,需要从一个单元格中获取公式字符串,然后将该公式字符串调整到目标单元格

由于ApachePOI能够计算公式,因此它还必须能够解析公式。解析类位于包和中

因此,我们可以使用这些类将公式字符串调整到目标单元格

例如:

以下Excel工作簿:

和以下代码:

import java.io.FileInputStream;

import org.apache.poi.ss.formula.*;
import org.apache.poi.ss.formula.ptg.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;

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

public class ExcelCopyFormula {

 private static String copyFormula(XSSFSheet sheet, String formula, int coldiff, int rowdiff) {

  XSSFEvaluationWorkbook workbookWrapper = 
   XSSFEvaluationWorkbook.create((XSSFWorkbook) sheet.getWorkbook());
  Ptg[] ptgs = FormulaParser.parse(formula, workbookWrapper, FormulaType.CELL
   , sheet.getWorkbook().getSheetIndex(sheet));

  for (int i = 0; i < ptgs.length; i++) {
   if (ptgs[i] instanceof RefPtgBase) { // base class for cell references
    RefPtgBase ref = (RefPtgBase) ptgs[i];
    if (ref.isColRelative())
     ref.setColumn(ref.getColumn() + coldiff);
    if (ref.isRowRelative())
     ref.setRow(ref.getRow() + rowdiff);
   }
   else if (ptgs[i] instanceof AreaPtgBase) { // base class for range references
    AreaPtgBase ref = (AreaPtgBase) ptgs[i];
    if (ref.isFirstColRelative())
     ref.setFirstColumn(ref.getFirstColumn() + coldiff);
    if (ref.isLastColRelative())
     ref.setLastColumn(ref.getLastColumn() + coldiff);
    if (ref.isFirstRowRelative())
     ref.setFirstRow(ref.getFirstRow() + rowdiff);
    if (ref.isLastRowRelative())
     ref.setLastRow(ref.getLastRow() + rowdiff);
   }
  }

  formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs);
  return formula;
 }

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

  XSSFWorkbook workbook = (XSSFWorkbook)WorkbookFactory.create(new FileInputStream("test.xlsx"));  
  XSSFSheet sheet = workbook.getSheetAt(0);
  for (Row row : sheet) {
   for (Cell cell : row) {
    //if (cell.getCellTypeEnum() == CellType.FORMULA) { // up to apache poi version 3
    if (cell.getCellType() == CellType.FORMULA) { // since apache poi version 4
     CellAddress source = cell.getAddress();
     String formula = cell.getCellFormula();
     System.out.print(source + "=" + formula);
     int rowdiff = 3;
     int coldiff = -2;
     CellAddress target = new CellAddress(source.getRow() + rowdiff, source.getColumn() + coldiff);
     String newformula = copyFormula(sheet, formula, coldiff, rowdiff);
     System.out.println("->" + target + "=" + newformula);
    }
   }
  }

  workbook.close();
 }
}

更新了
String copyFormula(Sheet Sheet,String formula,int coldiff,int rowdiff)
方法,该方法适用于
SS
,即
HSSF
以及
XSSF

 private static String copyFormula(Sheet sheet, String formula, int coldiff, int rowdiff) {

  Workbook workbook = sheet.getWorkbook();
  EvaluationWorkbook evaluationWorkbook = null;
  if (workbook instanceof HSSFWorkbook) {
   evaluationWorkbook = HSSFEvaluationWorkbook.create((HSSFWorkbook) workbook);
  } else if (workbook instanceof XSSFWorkbook) {
   evaluationWorkbook = XSSFEvaluationWorkbook.create((XSSFWorkbook) workbook);
  }

  Ptg[] ptgs = FormulaParser.parse(formula, (FormulaParsingWorkbook)evaluationWorkbook, 
   FormulaType.CELL, sheet.getWorkbook().getSheetIndex(sheet));

  for (int i = 0; i < ptgs.length; i++) {
   if (ptgs[i] instanceof RefPtgBase) { // base class for cell references
    RefPtgBase ref = (RefPtgBase) ptgs[i];
    if (ref.isColRelative())
     ref.setColumn(ref.getColumn() + coldiff);
    if (ref.isRowRelative())
     ref.setRow(ref.getRow() + rowdiff);
   }
   else if (ptgs[i] instanceof AreaPtgBase) { // base class for range references
    AreaPtgBase ref = (AreaPtgBase) ptgs[i];
    if (ref.isFirstColRelative())
     ref.setFirstColumn(ref.getFirstColumn() + coldiff);
    if (ref.isLastColRelative())
     ref.setLastColumn(ref.getLastColumn() + coldiff);
    if (ref.isFirstRowRelative())
     ref.setFirstRow(ref.getFirstRow() + rowdiff);
    if (ref.isLastRowRelative())
     ref.setLastRow(ref.getLastRow() + rowdiff);
   }
  }

  formula = FormulaRenderer.toFormulaString((FormulaRenderingWorkbook)evaluationWorkbook, ptgs);
  return formula;
 }
私有静态字符串复制公式(工作表、字符串公式、int coldiff、int rowdiff){
工作簿=sheet.get工作簿();
EvaluationWorkbook EvaluationWorkbook=null;
if(HSSF工作簿的工作簿实例){
evaluationWorkbook=HSSFEEvaluationWorkbook.create((HSSFWWorkbook)工作簿);
}else if(XSSF工作簿的工作簿实例){
evaluationWorkbook=XSSFEvaluationWorkbook.create((XSSFWorkbook)工作簿);
}
Ptg[]ptgs=FormulaParser.parse(公式,(FormulaParsingWorkbook)评估工作簿,
FormulaType.CELL,sheet.get工作簿().getSheetIndex(sheet));
对于(int i=0;i
如果您想要NPOI的答案,我已经根据@AxelRichter更新的答案创建了C版本:

public static string CopyFormula(ISheet sheet, string formula, int coldiff, int rowdiff)
{

    var workbook = sheet.Workbook;
    IFormulaParsingWorkbook evaluationWorkbook = null;
    if (sheet is XSSFWorkbook)
    {
        evaluationWorkbook = XSSFEvaluationWorkbook.Create(workbook);
    }
    else if (sheet is HSSFWorkbook)
    {
        evaluationWorkbook = HSSFEvaluationWorkbook.Create(workbook);
    }
    else if (sheet is SXSSFWorkbook)
    {
        evaluationWorkbook = SXSSFEvaluationWorkbook.Create((SXSSFWorkbook)workbook);
    }


    var ptgs = FormulaParser.Parse(formula, evaluationWorkbook,FormulaType.Cell, sheet.Workbook.GetSheetIndex(sheet));

    for (int i = 0; i < ptgs.Length; i++)
    {
        if (ptgs[i] is RefPtgBase) { 
            RefPtgBase ref2 = (RefPtgBase)ptgs[i];
            if (ref2.IsColRelative)
                ref2.Column = ref2.Column + coldiff;
            if (ref2.IsRowRelative)
                ref2.Row = ref2.Row + rowdiff;
        }
        else if (ptgs[i] is AreaPtgBase) { 
            AreaPtgBase ref2 = (AreaPtgBase)ptgs[i];
            if (ref2.IsFirstColRelative)
                ref2.FirstColumn += coldiff;
            if (ref2.IsLastColRelative)
                ref2.LastColumn += coldiff;
            if (ref2.IsFirstRowRelative)
                ref2.FirstRow += rowdiff;
            if (ref2.IsLastRowRelative)
                ref2.LastRow += rowdiff;
        }
    }

    formula = FormulaRenderer.ToFormulaString((IFormulaRenderingWorkbook)evaluationWorkbook, ptgs);
    return formula;
}
公共静态字符串复制公式(ISHET表、字符串公式、int-coldiff、int-rowdiff)
{
var工作簿=sheet.workbook;
IFormulaParsingWorkbook evaluationWorkbook=null;
如果(工作表为XSSF工作簿)
{
evaluationWorkbook=XSSFEvaluationWorkbook.Create(工作簿);
}
否则,如果(工作表为HSSF工作手册)
{
evaluationWorkbook=HSSFEEvaluationWorkbook.Create(工作簿);
}
else if(图纸为SXSSFWorkbook)
{
evaluationWorkbook=SXSSFEvaluationWorkbook.Create((SXSSFWorkbook)工作簿);
}
var ptgs=FormulaParser.Parse(formula,evaluation工作簿,FormulaType.Cell,sheet.Workbook.GetSheetIndex(sheet));
对于(int i=0;i
@Axel Richter,这里的coldiff和rowdiff是什么?@Nirmal Prajapat:
coldiff=columnofnewformacell-columnOfOldFormulaCell
rowdiff=rowofnewformacell-rowOfOldFormulaCell
。在Apache POI 4.1.2上试用。工作!如果我有像这样的
INDIRECT({“I5:I5”;“K5:M5”;“P5:S5”})的范围,这对我不起作用,可能吗?@Martinez:不,这是
INDIRECT
的问题,因为
INDIRECT
不使用直接单元格引用,而是使用文本字符串,然后这些字符串被解释为间接的。这就是为什么这个名字。而且,如前所述,
Excel
的GUI也不会在这种
间接的
公式中调整某些内容。
public static string CopyFormula(ISheet sheet, string formula, int coldiff, int rowdiff)
{

    var workbook = sheet.Workbook;
    IFormulaParsingWorkbook evaluationWorkbook = null;
    if (sheet is XSSFWorkbook)
    {
        evaluationWorkbook = XSSFEvaluationWorkbook.Create(workbook);
    }
    else if (sheet is HSSFWorkbook)
    {
        evaluationWorkbook = HSSFEvaluationWorkbook.Create(workbook);
    }
    else if (sheet is SXSSFWorkbook)
    {
        evaluationWorkbook = SXSSFEvaluationWorkbook.Create((SXSSFWorkbook)workbook);
    }


    var ptgs = FormulaParser.Parse(formula, evaluationWorkbook,FormulaType.Cell, sheet.Workbook.GetSheetIndex(sheet));

    for (int i = 0; i < ptgs.Length; i++)
    {
        if (ptgs[i] is RefPtgBase) { 
            RefPtgBase ref2 = (RefPtgBase)ptgs[i];
            if (ref2.IsColRelative)
                ref2.Column = ref2.Column + coldiff;
            if (ref2.IsRowRelative)
                ref2.Row = ref2.Row + rowdiff;
        }
        else if (ptgs[i] is AreaPtgBase) { 
            AreaPtgBase ref2 = (AreaPtgBase)ptgs[i];
            if (ref2.IsFirstColRelative)
                ref2.FirstColumn += coldiff;
            if (ref2.IsLastColRelative)
                ref2.LastColumn += coldiff;
            if (ref2.IsFirstRowRelative)
                ref2.FirstRow += rowdiff;
            if (ref2.IsLastRowRelative)
                ref2.LastRow += rowdiff;
        }
    }

    formula = FormulaRenderer.ToFormulaString((IFormulaRenderingWorkbook)evaluationWorkbook, ptgs);
    return formula;
}