/**
 *
 * @param sheetIden may be <code>null</code>
 * @param part1
 * @param part2 may be <code>null</code>
 */
        private ParseNode CreateAreaRefParseNode(SheetIdentifier sheetIden, SimpleRangePart part1,
                SimpleRangePart part2)
        {

            int extIx;
            if (sheetIden == null)
            {
                extIx = Int32.MinValue;
            }
            else
            {
                String sName = sheetIden.SheetID.Name;
                if (sheetIden.BookName == null)
                {
                    extIx = _book.GetExternalSheetIndex(sName);
                }
                else
                {
                    extIx = _book.GetExternalSheetIndex(sheetIden.BookName, sName);
                }
            }
            Ptg ptg;
            if (part2 == null)
            {
                CellReference cr = part1.getCellReference();
                if (sheetIden == null)
                {
                    ptg = new RefPtg(cr);
                }
                else
                {
                    ptg = new Ref3DPtg(cr, extIx);
                }
            }
            else
            {
                AreaReference areaRef = CreateAreaRef(part1, part2);

                if (sheetIden == null)
                {
                    ptg = new AreaPtg(areaRef);
                }
                else
                {
                    ptg = new Area3DPtg(areaRef, extIx);
                }
            }
            return new ParseNode(ptg);
        }
        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 + ")");
        }