npoi icon indicating copy to clipboard operation
npoi copied to clipboard

XSSF ShiftRows cause shared formula mismatch.

Open 1000111001 opened this issue 1 year ago • 3 comments

NPOI version: 2.5.6

Reproduce: 测试如下图1,B2:B17共享公式,当执行ShiftRows 1行B2共享公式范围应更新为"B3:B18",B2本身的CT_CellFormula更新了(图2),而sharedFormulas中未进行对应的更新(图3),导致公式计算错误。 image [图1] image [图2] image [图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();
            }
        }

test_case.xlsx

1000111001 avatar Aug 05 '22 03:08 1000111001

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

            }
        }

TimLee88 avatar Feb 20 '23 07:02 TimLee88

@tonyqus

TimLee88 avatar Feb 20 '23 07:02 TimLee88

same problem

Magentaize avatar Apr 28 '23 03:04 Magentaize