POI / Excel:以“相对”方式应用公式

2022-09-02 23:59:28

我正在使用Apache的POI来操作Java的Excel(.xls)文件。

我正在尝试创建一个新单元格,其内容是公式的结果,就好像用户复制/粘贴了公式一样(我称之为“相对”方式,与“绝对”相反)。

为了让自己更清楚,这里有一个简单的例子:

  • 单元格A1包含“1”,B1包含“2”,A2包含“3”,B2包含“4”。
  • 单元格 A3 包含以下公式“=A1+B1”。

如果我将公式复制到excel下的A4单元格,它就会变成:excel正在动态调整公式的内容。"=A2+B2"

不幸的是,我无法在程序上获得相同的结果。我发现的唯一解决方案是标记公式并自己做肮脏的工作,但我真的怀疑这应该以这种方式完成。我无法在指南或API中找到要查找的内容。

有没有更简单的方法来解决这个问题?如果是这样的话,你能给我指出正确的方向吗?

此致敬意

尼尔斯


答案 1

在我看来,user2622016是正确的,除了他的解决方案只管理单元格引用,而不是区域引用(例如,它不起作用)。=SUM(A1:B8)

以下是我如何解决这个问题:

private void copyFormula(Sheet sheet, Cell org, Cell dest) {
    if (org == null || dest == null || sheet == null 
            || org.getCellType() != Cell.CELL_TYPE_FORMULA)
        return;
    if (org.isPartOfArrayFormulaGroup())
        return;
    String formula = org.getCellFormula();
    int shiftRows = dest.getRowIndex() - org.getRowIndex();
    int shiftCols = dest.getColumnIndex() - org.getColumnIndex();
    XSSFEvaluationWorkbook workbookWrapper = 
            XSSFEvaluationWorkbook.create((XSSFWorkbook) sheet.getWorkbook());
    Ptg[] ptgs = FormulaParser.parse(formula, workbookWrapper, FormulaType.CELL
            , sheet.getWorkbook().getSheetIndex(sheet));
    for (Ptg ptg : ptgs) {
        if (ptg instanceof RefPtgBase) // base class for cell references
        {
            RefPtgBase ref = (RefPtgBase) ptg;
            if (ref.isColRelative())
                ref.setColumn(ref.getColumn() + shiftCols);
            if (ref.isRowRelative())
                ref.setRow(ref.getRow() + shiftRows);
        } else if (ptg instanceof AreaPtg) // base class for range references
        {
            AreaPtg ref = (AreaPtg) ptg;
            if (ref.isFirstColRelative())
                ref.setFirstColumn(ref.getFirstColumn() + shiftCols);
            if (ref.isLastColRelative())
                ref.setLastColumn(ref.getLastColumn() + shiftCols);
            if (ref.isFirstRowRelative())
                ref.setFirstRow(ref.getFirstRow() + shiftRows);
            if (ref.isLastRowRelative())
                ref.setLastRow(ref.getLastRow() + shiftRows);
        }
    }
    formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs);
    dest.setCellFormula(formula);
}

我仍然不知道我是否对所有细胞配方都是正确的,但它对我有用,快速可靠。


答案 2

我也认为没有一个简单的方法来做到这一点。

即使是POI网站上的HSSF和XSSD示例,例如TimesheetDemo,也可以手动进行公式构建。例如,在110号线附近

String ref = (char)('A' + j) + "3:" + (char)('A' + j) + "12";
cell.setCellFormula("SUM(" + ref + ")");

推荐