当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《POI/Excel:以"相对"方式应用公式》经验,为你挑选了3个好方法。

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

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

为了使自己更清楚,这里有一个简单的例子:Cell A1包含"1",B1包含"2",A2包含"3",B2包含"4".单元格A3包含以下公式"= A1 + B1".如果我将公式复制到excel下的A4单元格,它将变为"= A2 + B2":excel正在动态调整公式的内容.

不幸的是,我无法以编程方式获得相同的结果.我找到的唯一解决方案是将公式标记化并自己完成脏工作,但我真的怀疑这应该是这样做的.我无法在指南或API中找到我想要的内容.

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

最好的祝福,

尼尔斯



1> jitter..:

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

甚至POI站点上的HSSF和XSSD示例(例如TimesheetDemo)也可以手动执行公式构建.例如,在110号线附近

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



2> julien.giban..:

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

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



3> user2622016..:

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

FormulaParser,它将String解析为"解析事物"数组:

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 );
    }

而且你已准备好将"解析的东西"渲染回String:

formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs);
cell.setCellFormula( formula );

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有