首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >POI / Excel :以“相对”方式应用公式

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

Stack Overflow用户
提问于 2009-10-28 19:46:26
回答 6查看 14.8K关注 0票数 17

我正在使用Apache和Java操作.xls文件。

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

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

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

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

不幸的是,我无法通过编程获得相同的结果。我找到的唯一解决方案就是对公式进行标记化,然后自己来做这些繁琐的工作,但我真的很怀疑这是否应该这样做。我在指南或API中找不到我想要的东西。

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

诚挚的问候,

Nils

EN

回答 6

Stack Overflow用户

发布于 2014-03-12 22:03:12

在我看来,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);
}

我仍然不知道我是否对所有的单元格公式都是正确的,但它对我来说是有效的,快速可靠。

票数 12
EN

Stack Overflow用户

发布于 2009-10-28 20:15:08

我也认为没有一种简单的方法可以做到这一点。

即使是POI网站上的HSSF and XSSD examples,例如TimesheetDemo,也会手动构建公式。例如在110行附近

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

Stack Overflow用户

发布于 2013-07-30 21:46:54

我查看了FormulaEvaluator类,发现了一些可以为我们做这项工作的POI内部类。

FormulaParser,它将字符串解析为"parse things“数组:

String formula = cell.getCellFormula();
XSSFEvaluationWorkbook workbookWrapper = 
             XSSFEvaluationWorkbook.create((XSSFWorkbook) workbook);  
/* parse formula */
Ptg[] ptgs = FormulaParser.parse(formula, workbookWrapper, 
             FormulaType.CELL, 0 /*sheet index*/ );

ptgs现在是我们用反向波兰语表示的公式。现在遍历所有元素,并根据需要逐个修改引用:

/* re-calculate cell references */
for( Ptg ptg  : ptgs )
    if( ptg instanceof RefPtgBase )    //base class for cell reference "things"
    {
        RefPtgBase ref = (RefPtgBase)ptg;
        if( ref.isColRelative() )
            ref.setColumn( ref.getColumn() + 0 );
        if( ref.isRowRelative() )
            ref.setRow( ref.getRow() + 1 );
    }

现在就可以将"parse thing“返回给String了:

formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs);
cell.setCellFormula( formula );
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1636759

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档