Java POI/Excel:在“a”中应用公式;相对的;方式
我使用Apache的POI使用Java操作Excel(.xls)文件 我试图创建一个新的单元格,其内容是公式的结果,就像用户复制/粘贴了公式一样(我称之为“相对”方式,与“绝对”方式相反) 为了让我更清楚,这里有一个简单的例子:Java POI/Excel:在“a”中应用公式;相对的;方式,java,excel,apache-poi,poi-hssf,Java,Excel,Apache Poi,Poi Hssf,我使用Apache的POI使用Java操作Excel(.xls)文件 我试图创建一个新的单元格,其内容是公式的结果,就像用户复制/粘贴了公式一样(我称之为“相对”方式,与“绝对”方式相反) 为了让我更清楚,这里有一个简单的例子: 单元格A1包含“1”,B1包含“2”,A2包含“3”,B2包含“4” 单元格A3包含以下公式“=A1+B1” 如果我将公式复制到excel下的A4单元格,它将变成“=A2+B2”:excel正在动态调整公式的内容 不幸的是,我无法通过编程获得相同的结果。我找到的唯一
- 单元格A1包含“1”,B1包含“2”,A2包含“3”,B2包含“4”
- 单元格A3包含以下公式“=A1+B1”
“=A2+B2”
:excel正在动态调整公式的内容
不幸的是,我无法通过编程获得相同的结果。我找到的唯一解决办法是将公式标记化,自己动手做脏活,但我真的怀疑这是否应该这样做。我无法在指南或API中找到我要查找的内容
有没有更简单的方法来解决这个问题?如果是这样的话,你能告诉我正确的方向吗
致以最良好的祝愿
零我想没有。POI必须解析公式(考虑A1对$A$1对$A1等),我认为它没有这种能力。当我过去做这件事的时候,我总是要自己处理。对不起,这不是你希望的答案 我也认为这不是一个简单的方法 即使是在POI现场,例如手动进行公式构建。e、 g.110号线附近
String ref = (char)('A' + j) + "3:" + (char)('A' + j) + "12";
cell.setCellFormula("SUM(" + ref + ")");
您可以尝试一些第三方excel库,其中大多数都可以处理相对/绝对范围公式。我查看了FormulaEvaluator类内部,发现一些POI内部类可以为我们完成这项工作 FormulaParser,将字符串解析为“解析事物”数组: 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 );
}
您已经准备好将“解析内容”渲染回字符串:
formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs);
cell.setCellFormula( formula );
在我看来,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);
}
我仍然不知道它是否适用于所有细胞公式,但它对我有效,快速可靠。另一种相对复制公式的方法,用poi 3.12测试
public static void copyCellFormula(Workbook workbook, int sheetIndex, int rowIndex, int sourceColumnIndex, int destinationColumnIndex){
XSSFEvaluationWorkbook formulaParsingWorkbook = XSSFEvaluationWorkbook.create((XSSFWorkbook) workbook);
SharedFormula sharedFormula = new SharedFormula(SpreadsheetVersion.EXCEL2007);
Sheet sheet = workbook.getSheetAt(sheetIndex);
Row lookupRow = sheet.getRow(rowIndex);
Cell sourceCell = lookupRow.getCell(sourceColumnIndex);
Ptg[] sharedFormulaPtg = FormulaParser.parse(sourceCell.getCellFormula(), formulaParsingWorkbook, FormulaType.CELL, sheetIndex);
Ptg[] convertedFormulaPtg = sharedFormula.convertSharedFormulas(sharedFormulaPtg, 0, 1);
Cell destinationCell = lookupRow.createCell(destinationColumnIndex);
destinationCell.setCellFormula(FormulaRenderer.toFormulaString(formulaParsingWorkbook, convertedFormulaPtg));
}
根据需要更新共享公式:
sharedFormula.convertSharedFormulas(sharedFormulaPtg, rowIndexOffset, columnIndexOffset);
从poi 3.12开始,SharedFormula不支持其他表格中的单元格引用/公式(‘Sheet1’!A1)。以下是SharedFormula的更新:
public class SharedFormula {
private final int _columnWrappingMask;
private final int _rowWrappingMask;
public SharedFormula(SpreadsheetVersion ssVersion) {
this._columnWrappingMask = ssVersion.getLastColumnIndex();
this._rowWrappingMask = ssVersion.getLastRowIndex();
}
public Ptg[] convertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn) {
Ptg[] newPtgStack = new Ptg[ptgs.length];
RefPtgBase areaNPtg = null;
AreaPtgBase var9 = null;
Object ptg = null;
byte originalOperandClass = 0;
for(int k = 0; k < ptgs.length; ++k) {
ptg = ptgs[k];
originalOperandClass = -1;
if(!((Ptg)ptg).isBaseToken()) {
originalOperandClass = ((Ptg)ptg).getPtgClass();
}
if(ptg instanceof RefPtgBase) {
if(ptg instanceof Ref3DPxg) {
areaNPtg = (Ref3DPxg)ptg;
this.fixupRefRelativeRowAndColumn(areaNPtg, formulaRow, formulaColumn);
ptg = areaNPtg;
}else if(ptg instanceof Ref3DPtg) {
areaNPtg = (Ref3DPtg)ptg;
this.fixupRefRelativeRowAndColumn(areaNPtg, formulaRow, formulaColumn);
ptg = areaNPtg;
}else {
areaNPtg = (RefPtgBase)ptg;
ptg = new RefPtg(this.fixupRelativeRow(formulaRow, areaNPtg.getRow(), areaNPtg.isRowRelative()), this.fixupRelativeColumn(formulaColumn, areaNPtg.getColumn(), areaNPtg.isColRelative()), areaNPtg.isRowRelative(), areaNPtg.isColRelative());
}
((Ptg)ptg).setClass(originalOperandClass);
}else if(ptg instanceof AreaPtgBase) {
if(ptg instanceof Area3DPxg) {
var9 = (Area3DPxg)ptg;
this.fixupAreaRelativeRowAndColumn(var9, formulaRow, formulaColumn);
ptg = var9;
}else if(ptg instanceof Area3DPxg) {
var9 = (Area3DPtg)ptg;
this.fixupAreaRelativeRowAndColumn(var9, formulaRow, formulaColumn);
ptg = var9;
}else {
var9 = (AreaPtgBase)ptg;
ptg = new AreaPtg(this.fixupRelativeRow(formulaRow, var9.getFirstRow(), var9.isFirstRowRelative()), this.fixupRelativeRow(formulaRow, var9.getLastRow(), var9.isLastRowRelative()), this.fixupRelativeColumn(formulaColumn, var9.getFirstColumn(), var9.isFirstColRelative()), this.fixupRelativeColumn(formulaColumn, var9.getLastColumn(), var9.isLastColRelative()), var9.isFirstRowRelative(), var9.isLastRowRelative(), var9.isFirstColRelative(), var9.isLastColRelative());
}
((Ptg)ptg).setClass(originalOperandClass);
}else if(ptg instanceof OperandPtg) {
ptg = ((OperandPtg)ptg).copy();
}
newPtgStack[k] = (Ptg)ptg;
}
return newPtgStack;
}
protected void fixupRefRelativeRowAndColumn(RefPtgBase areaNPtg, int formulaRow, int formulaColumn){
areaNPtg.setRow(this.fixupRelativeRow(formulaRow, areaNPtg.getRow(), areaNPtg.isRowRelative()));
areaNPtg.setColumn(this.fixupRelativeColumn(formulaColumn, areaNPtg.getColumn(), areaNPtg.isColRelative()));
areaNPtg.setRowRelative(areaNPtg.isRowRelative());
areaNPtg.setColRelative(areaNPtg.isColRelative());
}
protected void fixupAreaRelativeRowAndColumn(AreaPtgBase var9, int formulaRow, int formulaColumn){
var9.setFirstRow(this.fixupRelativeRow(formulaRow, var9.getFirstRow(), var9.isFirstRowRelative()));
var9.setLastRow(this.fixupRelativeRow(formulaRow, var9.getLastRow(), var9.isLastRowRelative()));
var9.setFirstColumn(this.fixupRelativeColumn(formulaColumn, var9.getFirstColumn(), var9.isFirstColRelative()));
var9.setLastColumn(this.fixupRelativeColumn(formulaColumn, var9.getLastColumn(), var9.isLastColRelative()));
var9.setFirstRowRelative(var9.isFirstRowRelative());
var9.setLastRowRelative(var9.isLastRowRelative());
var9.setFirstColRelative(var9.isFirstColRelative());
var9.setLastColRelative(var9.isLastColRelative());
}
protected int fixupRelativeColumn(int currentcolumn, int column, boolean relative) {
return relative?column + currentcolumn & this._columnWrappingMask:column;
}
protected int fixupRelativeRow(int currentrow, int row, boolean relative) {
return relative?row + currentrow & this._rowWrappingMask:row;
}
}
公共类共享公式{
私人最终整容专栏包装;
私人最终整容包装任务;
公共共享公式(电子表格版本ssVersion){
这是._columnWrappingMask=ssVersion.getLastColumnIndex();
这是._rowWrappingMask=ssVersion.getLastRowIndex();
}
公共Ptg[]转换共享公式(Ptg[]Ptg,int formulaRow,int formulaColumn){
Ptg[]newPtgStack=新Ptg[ptgs.length];
RefPtgBase AREA NPTG=null;
AreaPtgBase var9=null;
对象ptg=null;
字节originalOperandClass=0;
对于(int k=0;kpublic class SharedFormula {
private final int _columnWrappingMask;
private final int _rowWrappingMask;
public SharedFormula(SpreadsheetVersion ssVersion) {
this._columnWrappingMask = ssVersion.getLastColumnIndex();
this._rowWrappingMask = ssVersion.getLastRowIndex();
}
public Ptg[] convertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn) {
Ptg[] newPtgStack = new Ptg[ptgs.length];
RefPtgBase areaNPtg = null;
AreaPtgBase var9 = null;
Object ptg = null;
byte originalOperandClass = 0;
for(int k = 0; k < ptgs.length; ++k) {
ptg = ptgs[k];
originalOperandClass = -1;
if(!((Ptg)ptg).isBaseToken()) {
originalOperandClass = ((Ptg)ptg).getPtgClass();
}
if(ptg instanceof RefPtgBase) {
if(ptg instanceof Ref3DPxg) {
areaNPtg = (Ref3DPxg)ptg;
this.fixupRefRelativeRowAndColumn(areaNPtg, formulaRow, formulaColumn);
ptg = areaNPtg;
}else if(ptg instanceof Ref3DPtg) {
areaNPtg = (Ref3DPtg)ptg;
this.fixupRefRelativeRowAndColumn(areaNPtg, formulaRow, formulaColumn);
ptg = areaNPtg;
}else {
areaNPtg = (RefPtgBase)ptg;
ptg = new RefPtg(this.fixupRelativeRow(formulaRow, areaNPtg.getRow(), areaNPtg.isRowRelative()), this.fixupRelativeColumn(formulaColumn, areaNPtg.getColumn(), areaNPtg.isColRelative()), areaNPtg.isRowRelative(), areaNPtg.isColRelative());
}
((Ptg)ptg).setClass(originalOperandClass);
}else if(ptg instanceof AreaPtgBase) {
if(ptg instanceof Area3DPxg) {
var9 = (Area3DPxg)ptg;
this.fixupAreaRelativeRowAndColumn(var9, formulaRow, formulaColumn);
ptg = var9;
}else if(ptg instanceof Area3DPxg) {
var9 = (Area3DPtg)ptg;
this.fixupAreaRelativeRowAndColumn(var9, formulaRow, formulaColumn);
ptg = var9;
}else {
var9 = (AreaPtgBase)ptg;
ptg = new AreaPtg(this.fixupRelativeRow(formulaRow, var9.getFirstRow(), var9.isFirstRowRelative()), this.fixupRelativeRow(formulaRow, var9.getLastRow(), var9.isLastRowRelative()), this.fixupRelativeColumn(formulaColumn, var9.getFirstColumn(), var9.isFirstColRelative()), this.fixupRelativeColumn(formulaColumn, var9.getLastColumn(), var9.isLastColRelative()), var9.isFirstRowRelative(), var9.isLastRowRelative(), var9.isFirstColRelative(), var9.isLastColRelative());
}
((Ptg)ptg).setClass(originalOperandClass);
}else if(ptg instanceof OperandPtg) {
ptg = ((OperandPtg)ptg).copy();
}
newPtgStack[k] = (Ptg)ptg;
}
return newPtgStack;
}
protected void fixupRefRelativeRowAndColumn(RefPtgBase areaNPtg, int formulaRow, int formulaColumn){
areaNPtg.setRow(this.fixupRelativeRow(formulaRow, areaNPtg.getRow(), areaNPtg.isRowRelative()));
areaNPtg.setColumn(this.fixupRelativeColumn(formulaColumn, areaNPtg.getColumn(), areaNPtg.isColRelative()));
areaNPtg.setRowRelative(areaNPtg.isRowRelative());
areaNPtg.setColRelative(areaNPtg.isColRelative());
}
protected void fixupAreaRelativeRowAndColumn(AreaPtgBase var9, int formulaRow, int formulaColumn){
var9.setFirstRow(this.fixupRelativeRow(formulaRow, var9.getFirstRow(), var9.isFirstRowRelative()));
var9.setLastRow(this.fixupRelativeRow(formulaRow, var9.getLastRow(), var9.isLastRowRelative()));
var9.setFirstColumn(this.fixupRelativeColumn(formulaColumn, var9.getFirstColumn(), var9.isFirstColRelative()));
var9.setLastColumn(this.fixupRelativeColumn(formulaColumn, var9.getLastColumn(), var9.isLastColRelative()));
var9.setFirstRowRelative(var9.isFirstRowRelative());
var9.setLastRowRelative(var9.isLastRowRelative());
var9.setFirstColRelative(var9.isFirstColRelative());
var9.setLastColRelative(var9.isLastColRelative());
}
protected int fixupRelativeColumn(int currentcolumn, int column, boolean relative) {
return relative?column + currentcolumn & this._columnWrappingMask:column;
}
protected int fixupRelativeRow(int currentrow, int row, boolean relative) {
return relative?row + currentrow & this._rowWrappingMask:row;
}
}