private static CellRangeAddress ShiftRange(FormulaShifter shifter, CellRangeAddress cra, int currentExternSheetIx)
        {
            // FormulaShifter works well in terms of Ptgs - so convert CellRangeAddress to AreaPtg (and back) here
            AreaPtg aptg = new AreaPtg(cra.FirstRow, cra.LastRow, cra.FirstColumn, cra.LastColumn, false, false, false, false);
            Ptg[] ptgs = { aptg, };

            if (!shifter.AdjustFormula(ptgs, currentExternSheetIx))
            {
                return cra;
            }
            Ptg ptg0 = ptgs[0];
            if (ptg0 is AreaPtg)
            {
                AreaPtg bptg = (AreaPtg)ptg0;
                return new CellRangeAddress(bptg.FirstRow, bptg.LastRow, bptg.FirstColumn, bptg.LastColumn);
            }
            if (ptg0 is AreaErrPtg)
            {
                return null;
            }
            throw new InvalidCastException("Unexpected shifted ptg class (" + ptg0.GetType().Name + ")");
        }
 public void UpdateFormulasAfterRowShift(FormulaShifter shifter, int currentExternSheetIndex)
 {
     for (int i = 0; i < records.Length; i++)
     {
         CellValueRecordInterface[] rowCells = records[i];
         if (rowCells == null)
         {
             continue;
         }
         for (int j = 0; j < rowCells.Length; j++)
         {
             CellValueRecordInterface cell = rowCells[j];
             if (cell is FormulaRecordAggregate)
             {
                 FormulaRecord fr = ((FormulaRecordAggregate)cell).FormulaRecord;
                 Ptg[] ptgs = fr.ParsedExpression; // needs clone() inside this getter?
                 if (shifter.AdjustFormula(ptgs, currentExternSheetIndex))
                 {
                     fr.ParsedExpression = (ptgs);
                 }
             }
         }
     }
 }
        /**
         * @return <c>false</c> if this whole {@link CFHeaderRecord} / {@link CFRuleRecord}s should be deleted
         */
        public bool UpdateFormulasAfterCellShift(FormulaShifter shifter, int currentExternSheetIx)
        {
            CellRangeAddress[] cellRanges = header.CellRanges;
            bool changed = false;
            ArrayList temp = new ArrayList();
            for (int i = 0; i < cellRanges.Length; i++)
            {
                CellRangeAddress craOld = cellRanges[i];
                CellRangeAddress craNew = ShiftRange(shifter, craOld, currentExternSheetIx);
                if (craNew == null)
                {
                    changed = true;
                    continue;
                }
                temp.Add(craNew);
                if (craNew != craOld)
                {
                    changed = true;
                }
            }

            if (changed)
            {
                int nRanges = temp.Count;
                if (nRanges == 0)
                {
                    return false;
                }
                CellRangeAddress[] newRanges = new CellRangeAddress[nRanges];
                newRanges = (CellRangeAddress[])temp.ToArray(typeof(CellRangeAddress));
                header.CellRanges = (newRanges);
            }

            for (int i = 0; i < rules.Count; i++)
            {
                CFRuleRecord rule = (CFRuleRecord)rules[i];
                Ptg[] ptgs;
                ptgs = rule.ParsedExpression1;
                if (ptgs != null && shifter.AdjustFormula(ptgs, currentExternSheetIx))
                {
                    rule.ParsedExpression1 = (ptgs);
                }
                ptgs = rule.ParsedExpression2;
                if (ptgs != null && shifter.AdjustFormula(ptgs, currentExternSheetIx))
                {
                    rule.ParsedExpression2 = (ptgs);
                }
            }
            return true;
        }