Java 复制时Apache POI更新公式引用
在Apache POI中复制公式时,是否有更新公式引用的方法 在Excel中,假设第1行有公式Java 复制时Apache POI更新公式引用,java,excel,excel-formula,apache-poi,Java,Excel,Excel Formula,Apache Poi,在Apache POI中复制公式时,是否有更新公式引用的方法 在Excel中,假设第1行有公式=A1/B1。如果你复制粘贴它,比如在第5行,公式变成=A5/B5. 在ApachePOI中,如果运行 r5.getCell(2).setCellType(CellType.FORMULA); r5.getCell(2).setCellFormula(r1.getCell(2).getCellFormula()); 公式仍然是=A1/B1您的代码没有复制/粘贴内容,而是从一个单元格获取公式字符串,并将
=A1/B1
。如果你复制粘贴它,比如在第5行,公式变成=A5/B5.
在ApachePOI中,如果运行
r5.getCell(2).setCellType(CellType.FORMULA);
r5.getCell(2).setCellFormula(r1.getCell(2).getCellFormula());
公式仍然是
=A1/B1
您的代码没有复制/粘贴内容,而是从一个单元格获取公式字符串,并将该公式字符串精确地设置到另一个单元格。这不会更改公式字符串。它应该怎么做呢
因此,需要从一个单元格中获取公式字符串,然后将该公式字符串调整到目标单元格
由于ApachePOI能够计算公式,因此它还必须能够解析公式。解析类位于包和中
因此,我们可以使用这些类将公式字符串调整到目标单元格
例如:
以下Excel工作簿:
和以下代码:
import java.io.FileInputStream;
import org.apache.poi.ss.formula.*;
import org.apache.poi.ss.formula.ptg.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.CellAddress;
public class ExcelCopyFormula {
private static String copyFormula(XSSFSheet sheet, String formula, int coldiff, int rowdiff) {
XSSFEvaluationWorkbook workbookWrapper =
XSSFEvaluationWorkbook.create((XSSFWorkbook) sheet.getWorkbook());
Ptg[] ptgs = FormulaParser.parse(formula, workbookWrapper, FormulaType.CELL
, sheet.getWorkbook().getSheetIndex(sheet));
for (int i = 0; i < ptgs.length; i++) {
if (ptgs[i] instanceof RefPtgBase) { // base class for cell references
RefPtgBase ref = (RefPtgBase) ptgs[i];
if (ref.isColRelative())
ref.setColumn(ref.getColumn() + coldiff);
if (ref.isRowRelative())
ref.setRow(ref.getRow() + rowdiff);
}
else if (ptgs[i] instanceof AreaPtgBase) { // base class for range references
AreaPtgBase ref = (AreaPtgBase) ptgs[i];
if (ref.isFirstColRelative())
ref.setFirstColumn(ref.getFirstColumn() + coldiff);
if (ref.isLastColRelative())
ref.setLastColumn(ref.getLastColumn() + coldiff);
if (ref.isFirstRowRelative())
ref.setFirstRow(ref.getFirstRow() + rowdiff);
if (ref.isLastRowRelative())
ref.setLastRow(ref.getLastRow() + rowdiff);
}
}
formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs);
return formula;
}
public static void main(String[] args) throws Exception {
XSSFWorkbook workbook = (XSSFWorkbook)WorkbookFactory.create(new FileInputStream("test.xlsx"));
XSSFSheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
for (Cell cell : row) {
//if (cell.getCellTypeEnum() == CellType.FORMULA) { // up to apache poi version 3
if (cell.getCellType() == CellType.FORMULA) { // since apache poi version 4
CellAddress source = cell.getAddress();
String formula = cell.getCellFormula();
System.out.print(source + "=" + formula);
int rowdiff = 3;
int coldiff = -2;
CellAddress target = new CellAddress(source.getRow() + rowdiff, source.getColumn() + coldiff);
String newformula = copyFormula(sheet, formula, coldiff, rowdiff);
System.out.println("->" + target + "=" + newformula);
}
}
}
workbook.close();
}
}
更新了
String copyFormula(Sheet Sheet,String formula,int coldiff,int rowdiff)
方法,该方法适用于SS
,即HSSF
以及XSSF
:
private static String copyFormula(Sheet sheet, String formula, int coldiff, int rowdiff) {
Workbook workbook = sheet.getWorkbook();
EvaluationWorkbook evaluationWorkbook = null;
if (workbook instanceof HSSFWorkbook) {
evaluationWorkbook = HSSFEvaluationWorkbook.create((HSSFWorkbook) workbook);
} else if (workbook instanceof XSSFWorkbook) {
evaluationWorkbook = XSSFEvaluationWorkbook.create((XSSFWorkbook) workbook);
}
Ptg[] ptgs = FormulaParser.parse(formula, (FormulaParsingWorkbook)evaluationWorkbook,
FormulaType.CELL, sheet.getWorkbook().getSheetIndex(sheet));
for (int i = 0; i < ptgs.length; i++) {
if (ptgs[i] instanceof RefPtgBase) { // base class for cell references
RefPtgBase ref = (RefPtgBase) ptgs[i];
if (ref.isColRelative())
ref.setColumn(ref.getColumn() + coldiff);
if (ref.isRowRelative())
ref.setRow(ref.getRow() + rowdiff);
}
else if (ptgs[i] instanceof AreaPtgBase) { // base class for range references
AreaPtgBase ref = (AreaPtgBase) ptgs[i];
if (ref.isFirstColRelative())
ref.setFirstColumn(ref.getFirstColumn() + coldiff);
if (ref.isLastColRelative())
ref.setLastColumn(ref.getLastColumn() + coldiff);
if (ref.isFirstRowRelative())
ref.setFirstRow(ref.getFirstRow() + rowdiff);
if (ref.isLastRowRelative())
ref.setLastRow(ref.getLastRow() + rowdiff);
}
}
formula = FormulaRenderer.toFormulaString((FormulaRenderingWorkbook)evaluationWorkbook, ptgs);
return formula;
}
私有静态字符串复制公式(工作表、字符串公式、int coldiff、int rowdiff){
工作簿=sheet.get工作簿();
EvaluationWorkbook EvaluationWorkbook=null;
if(HSSF工作簿的工作簿实例){
evaluationWorkbook=HSSFEEvaluationWorkbook.create((HSSFWWorkbook)工作簿);
}else if(XSSF工作簿的工作簿实例){
evaluationWorkbook=XSSFEvaluationWorkbook.create((XSSFWorkbook)工作簿);
}
Ptg[]ptgs=FormulaParser.parse(公式,(FormulaParsingWorkbook)评估工作簿,
FormulaType.CELL,sheet.get工作簿().getSheetIndex(sheet));
对于(int i=0;i
如果您想要NPOI的答案,我已经根据@AxelRichter更新的答案创建了C版本:
public static string CopyFormula(ISheet sheet, string formula, int coldiff, int rowdiff)
{
var workbook = sheet.Workbook;
IFormulaParsingWorkbook evaluationWorkbook = null;
if (sheet is XSSFWorkbook)
{
evaluationWorkbook = XSSFEvaluationWorkbook.Create(workbook);
}
else if (sheet is HSSFWorkbook)
{
evaluationWorkbook = HSSFEvaluationWorkbook.Create(workbook);
}
else if (sheet is SXSSFWorkbook)
{
evaluationWorkbook = SXSSFEvaluationWorkbook.Create((SXSSFWorkbook)workbook);
}
var ptgs = FormulaParser.Parse(formula, evaluationWorkbook,FormulaType.Cell, sheet.Workbook.GetSheetIndex(sheet));
for (int i = 0; i < ptgs.Length; i++)
{
if (ptgs[i] is RefPtgBase) {
RefPtgBase ref2 = (RefPtgBase)ptgs[i];
if (ref2.IsColRelative)
ref2.Column = ref2.Column + coldiff;
if (ref2.IsRowRelative)
ref2.Row = ref2.Row + rowdiff;
}
else if (ptgs[i] is AreaPtgBase) {
AreaPtgBase ref2 = (AreaPtgBase)ptgs[i];
if (ref2.IsFirstColRelative)
ref2.FirstColumn += coldiff;
if (ref2.IsLastColRelative)
ref2.LastColumn += coldiff;
if (ref2.IsFirstRowRelative)
ref2.FirstRow += rowdiff;
if (ref2.IsLastRowRelative)
ref2.LastRow += rowdiff;
}
}
formula = FormulaRenderer.ToFormulaString((IFormulaRenderingWorkbook)evaluationWorkbook, ptgs);
return formula;
}
公共静态字符串复制公式(ISHET表、字符串公式、int-coldiff、int-rowdiff)
{
var工作簿=sheet.workbook;
IFormulaParsingWorkbook evaluationWorkbook=null;
如果(工作表为XSSF工作簿)
{
evaluationWorkbook=XSSFEvaluationWorkbook.Create(工作簿);
}
否则,如果(工作表为HSSF工作手册)
{
evaluationWorkbook=HSSFEEvaluationWorkbook.Create(工作簿);
}
else if(图纸为SXSSFWorkbook)
{
evaluationWorkbook=SXSSFEvaluationWorkbook.Create((SXSSFWorkbook)工作簿);
}
var ptgs=FormulaParser.Parse(formula,evaluation工作簿,FormulaType.Cell,sheet.Workbook.GetSheetIndex(sheet));
对于(int i=0;i
@Axel Richter,这里的coldiff和rowdiff是什么?@Nirmal Prajapat:coldiff=columnofnewformacell-columnOfOldFormulaCell
和rowdiff=rowofnewformacell-rowOfOldFormulaCell
。在Apache POI 4.1.2上试用。工作!如果我有像这样的INDIRECT({“I5:I5”;“K5:M5”;“P5:S5”})的范围,这对我不起作用,可能吗?@Martinez:不,这是INDIRECT
的问题,因为INDIRECT
不使用直接单元格引用,而是使用文本字符串,然后这些字符串被解释为间接的。这就是为什么这个名字。而且,如前所述,Excel
的GUI也不会在这种间接的公式中调整某些内容。
public static string CopyFormula(ISheet sheet, string formula, int coldiff, int rowdiff)
{
var workbook = sheet.Workbook;
IFormulaParsingWorkbook evaluationWorkbook = null;
if (sheet is XSSFWorkbook)
{
evaluationWorkbook = XSSFEvaluationWorkbook.Create(workbook);
}
else if (sheet is HSSFWorkbook)
{
evaluationWorkbook = HSSFEvaluationWorkbook.Create(workbook);
}
else if (sheet is SXSSFWorkbook)
{
evaluationWorkbook = SXSSFEvaluationWorkbook.Create((SXSSFWorkbook)workbook);
}
var ptgs = FormulaParser.Parse(formula, evaluationWorkbook,FormulaType.Cell, sheet.Workbook.GetSheetIndex(sheet));
for (int i = 0; i < ptgs.Length; i++)
{
if (ptgs[i] is RefPtgBase) {
RefPtgBase ref2 = (RefPtgBase)ptgs[i];
if (ref2.IsColRelative)
ref2.Column = ref2.Column + coldiff;
if (ref2.IsRowRelative)
ref2.Row = ref2.Row + rowdiff;
}
else if (ptgs[i] is AreaPtgBase) {
AreaPtgBase ref2 = (AreaPtgBase)ptgs[i];
if (ref2.IsFirstColRelative)
ref2.FirstColumn += coldiff;
if (ref2.IsLastColRelative)
ref2.LastColumn += coldiff;
if (ref2.IsFirstRowRelative)
ref2.FirstRow += rowdiff;
if (ref2.IsLastRowRelative)
ref2.LastRow += rowdiff;
}
}
formula = FormulaRenderer.ToFormulaString((IFormulaRenderingWorkbook)evaluationWorkbook, ptgs);
return formula;
}