Another way to copy formula relatively, tested with 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));
}
Update shared formula as needed:
sharedFormula.convertSharedFormulas(sharedFormulaPtg, rowIndexOffset, columnIndexOffset);
As of poi 3.12, SharedFormula doesn't support cell reference/formula from other sheets (='Sheet1'!A1). Here's an update to 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;
}
}