npoi
npoi copied to clipboard
XSSF ShiftRows cause shared formula mismatch.
NPOI version: 2.5.6
Reproduce:
测试如下图1,B2:B17共享公式,当执行ShiftRows 1行B2共享公式范围应更新为"B3:B18",B2本身的CT_CellFormula更新了(图2),而sharedFormulas中未进行对应的更新(图3),导致公式计算错误。
[图1]
[图2]
[图3]
Test case:
static void Main(string[] args)
{
string filename = "C:/test_case.xlsx";
var bytes = File.ReadAllBytes(filename);
IWorkbook m_excelbook;
using (MemoryStream ms = new MemoryStream(bytes))
{
int insertRow = 1;
m_excelbook = new XSSFWorkbook(ms);
var sheet = m_excelbook.GetSheetAt(0);
sheet.ShiftRows(insertRow, sheet.LastRowNum, 1);
var _ = sheet.CreateRow(insertRow);
var cell = sheet.GetRow(insertRow + 1).GetCell(1);
var f = cell.CellFormula;
ms.Close();
}
}
NPOI 2.6 also has this bug, I have resolved it: https://github.com/nissl-lab/npoi/blob/master/ooxml/XSSF/UserModel/Helpers/XSSFRowColShifter.cs#L69 NPOI.OOXML.XSSF.UserModel.Helpers.XSSFRowColShifter =>UpdateRowFormulas (line 69)
public static void UpdateRowFormulas(IRow row, FormulaShifter Shifter)
{
XSSFSheet sheet = (XSSFSheet)row.Sheet;
foreach (ICell c in row)
{
XSSFCell cell = (XSSFCell)c;
CT_Cell ctCell = cell.GetCTCell();
if (ctCell.IsSetF())
{
CT_CellFormula f = ctCell.f;
String formula = f.Value;
if (formula.Length > 0)
{
String ShiftedFormula = ShiftFormula(row, formula, Shifter);
if (ShiftedFormula != null)
{
f.Value = (ShiftedFormula);
if (f.t == ST_CellFormulaType.shared)
{
int si = (int)f.si;
CT_CellFormula sf = sheet.GetSharedFormula(si);
sf.Value = (ShiftedFormula);
//--------------------------------------------------------
//NPOI bug fix, add the following code
//when change then value of SharedFormula, must change ref of it at the same time
sf.@ref = ShiftFormula(row, sf.@ref, Shifter);
//--------------------------------------------------------
}
}
}
if (f.isSetRef())
{ //Range of cells which the formula applies to.
String ref1 = f.@ref;
String ShiftedRef = ShiftFormula(row, ref1, Shifter);
if (ShiftedRef != null) f.@ref = ShiftedRef;
}
}
}
}
@tonyqus
same problem