Exemplo n.º 1
0
        /**
         * Creates a non shared formula from the shared formula counterpart, i.e.
         * Converts the shared formula into the equivalent {@link org.apache.poi.ss.formula.ptg.Ptg} array that it would have,
         * were it not shared.
         *
         * @param ptgs parsed tokens of the shared formula
         * @param formulaRow
         * @param formulaColumn
         */
        public Ptg[] ConvertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn)
        {

            Ptg[] newPtgStack = new Ptg[ptgs.Length];

            for (int k = 0; k < ptgs.Length; k++)
            {
                Ptg ptg = ptgs[k];
                byte originalOperandClass = unchecked((byte)-1);
                if (!ptg.IsBaseToken)
                {
                    originalOperandClass = ptg.PtgClass;
                }
                if (ptg is RefPtgBase)
                {
                    RefPtgBase refNPtg = (RefPtgBase)ptg;
                    ptg = new RefPtg(FixupRelativeRow(formulaRow, refNPtg.Row, refNPtg.IsRowRelative),
                                         FixupRelativeColumn(formulaColumn, refNPtg.Column, refNPtg.IsColRelative),
                                         refNPtg.IsRowRelative,
                                         refNPtg.IsColRelative);
                    ptg.PtgClass = (originalOperandClass);
                }
                else if (ptg is AreaPtgBase)
                {
                    AreaPtgBase areaNPtg = (AreaPtgBase)ptg;
                    ptg = new AreaPtg(FixupRelativeRow(formulaRow, areaNPtg.FirstRow, areaNPtg.IsFirstRowRelative),
                                    FixupRelativeRow(formulaRow, areaNPtg.LastRow, areaNPtg.IsLastRowRelative),
                                    FixupRelativeColumn(formulaColumn, areaNPtg.FirstColumn, areaNPtg.IsFirstColRelative),
                                    FixupRelativeColumn(formulaColumn, areaNPtg.LastColumn, areaNPtg.IsLastColRelative),
                                    areaNPtg.IsFirstRowRelative,
                                    areaNPtg.IsLastRowRelative,
                                    areaNPtg.IsFirstColRelative,
                                    areaNPtg.IsLastColRelative);
                    ptg.PtgClass = (originalOperandClass);
                }
                else if (ptg is OperandPtg)
                {
                    // Any subclass of OperandPtg is mutable, so it's safest to not share these instances.
                    ptg = ((OperandPtg)ptg).Copy();
                }
                else
                {
                    // all other Ptgs are immutable and can be shared
                }
                newPtgStack[k] = ptg;
            }
            return newPtgStack;
        }
Exemplo n.º 2
0
        public ParseNode(Ptg token, ParseNode[] children)
        {
            _token    = token;
            _children = children;
            _isIf     = IsIf(token);
            int tokenCount = 1;

            for (int i = 0; i < children.Length; i++)
            {
                tokenCount += children[i].GetTokenCount();
            }
            if (_isIf)
            {
                // there will be 2 or 3 extra tAttr tokens according to whether the false param is present
                tokenCount += children.Length;
            }
            _tokenCount = tokenCount;
        }
Exemplo n.º 3
0
        public override String ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(GetType().Name).Append(" [ARRAY]\n");
            sb.Append(" range=").Append(Range.ToString()).Append("\n");
            sb.Append(" options=").Append(HexDump.ShortToHex(_options)).Append("\n");
            sb.Append(" notUsed=").Append(HexDump.IntToHex(_field3notUsed)).Append("\n");
            sb.Append(" formula:").Append("\n");
            Ptg[] ptgs = _formula.Tokens;
            for (int i = 0; i < ptgs.Length; i++)
            {
                Ptg ptg = ptgs[i];
                sb.Append(ptg.ToString()).Append(ptg.RVAType).Append("\n");
            }
            sb.Append("]");
            return(sb.ToString());
        }
Exemplo n.º 4
0
        private Ptg AdjustPtgDueToSheetMove(Ptg ptg)
        {
            if (ptg is Ref3DPtg)
            {
                Ref3DPtg ref1          = (Ref3DPtg)ptg;
                int      oldSheetIndex = ref1.ExternSheetIndex;

                // we have to handle a few cases here

                // 1. sheet is outside moved sheets, no change necessary
                if (oldSheetIndex < _srcSheetIndex &&
                    oldSheetIndex < _dstSheetIndex)
                {
                    return(null);
                }
                if (oldSheetIndex > _srcSheetIndex &&
                    oldSheetIndex > _dstSheetIndex)
                {
                    return(null);
                }

                // 2. ptg refers to the moved sheet
                if (oldSheetIndex == _srcSheetIndex)
                {
                    ref1.ExternSheetIndex = (_dstSheetIndex);
                    return(ref1);
                }

                // 3. new index is lower than old one => sheets get moved up
                if (_dstSheetIndex < _srcSheetIndex)
                {
                    ref1.ExternSheetIndex = (oldSheetIndex + 1);
                    return(ref1);
                }

                // 4. new index is higher than old one => sheets get moved down
                if (_dstSheetIndex > _srcSheetIndex)
                {
                    ref1.ExternSheetIndex = (oldSheetIndex - 1);
                    return(ref1);
                }
            }
            return(null);
        }
Exemplo n.º 5
0
        public void TestConvertSharedFormulasOperandClasses_bug45123()
        {
            RecordInputStream in1        = TestcaseRecordInputStream.Create(0, SHARED_FORMULA_WITH_REF_ARRAYS_DATA);
            short             encodedLen = in1.ReadShort();

            Ptg[] sharedFormula = Ptg.ReadTokens(encodedLen, in1);

            Ptg[] convertedFormula = SharedFormulaRecord.ConvertSharedFormulas(sharedFormula, 100, 200);

            RefPtg refPtg = (RefPtg)convertedFormula[1];

            Assert.AreEqual("$C101", refPtg.ToFormulaString());
            if (refPtg.PtgClass == Ptg.CLASS_REF)
            {
                throw new AssertFailedException("Identified bug 45123");
            }

            ConfirmOperandClasses(sharedFormula, convertedFormula);
        }
Exemplo n.º 6
0
        /**
         * print a sort of string representation ([SHARED FORMULA RECORD] id = x [/SHARED FORMULA RECORD])
         */

        public override String ToString()
        {
            StringBuilder buffer = new StringBuilder();

            buffer.Append("[SHARED FORMULA (").Append(HexDump.IntToHex(sid)).Append("]\n");
            buffer.Append("    .range      = ").Append(Range.ToString()).Append("\n");
            buffer.Append("    .reserved    = ").Append(HexDump.ShortToHex(field_5_reserved)).Append("\n");

            Ptg[] ptgs = field_7_parsed_expr.Tokens;
            for (int k = 0; k < ptgs.Length; k++)
            {
                buffer.Append("Formula[").Append(k).Append("]");
                Ptg ptg = ptgs[k];
                buffer.Append(ptg.ToString()).Append(ptg.RVAType).Append("\n");
            }

            buffer.Append("[/SHARED FORMULA]\n");
            return(buffer.ToString());
        }
Exemplo n.º 7
0
 public override String ToString()
 {
     StringBuilder sb = new StringBuilder();
     sb.Append("[EXTERNALNAME]\n");
     sb.Append("    .options      = ").Append(field_1_option_flag).Append("\n");
     sb.Append("    .ix      = ").Append(field_2_ixals).Append("\n");
     sb.Append("    .name    = ").Append(field_4_name).Append("\n");
     if (field_5_name_definition != null)
     {
         Ptg[] ptgs = field_5_name_definition.Tokens;
         for (int i = 0; i < ptgs.Length; i++)
         {
             Ptg ptg = ptgs[i];
             sb.Append(ptg.ToString()).Append(ptg.RVAType).Append("\n");
         }
     }
     sb.Append("[/EXTERNALNAME]\n");
     return sb.ToString();
 }
Exemplo n.º 8
0
        public void TestLinkFormula()
        {
            RecordInputStream is1 = new RecordInputStream(new MemoryStream(linkData));

            is1.NextRecord();
            TextObjectRecord rec = new TextObjectRecord(is1);

            Ptg ptg = rec.LinkRefPtg;

            Assert.IsNotNull(ptg);
            Assert.AreEqual(typeof(RefPtg), ptg.GetType());
            RefPtg rptg = (RefPtg)ptg;

            Assert.AreEqual("T2", rptg.ToFormulaString());

            byte[] data2 = rec.Serialize();
            Assert.AreEqual(linkData.Length, data2.Length);
            Assert.IsTrue(Arrays.Equals(linkData, data2));
        }
Exemplo n.º 9
0
        private static String ShiftAllColumnsBy1(String formula)
        {
            int          letUsShiftColumn1By1Column = 1;
            HSSFWorkbook wb = null;

            Ptg[] ptgs = HSSFFormulaParser.Parse(formula, wb);
            for (int i = 0; i < ptgs.Length; i++)
            {
                Ptg ptg = ptgs[i];
                if (ptg is AreaPtg)
                {
                    AreaPtg aptg = (AreaPtg)ptg;
                    aptg.FirstColumn = ((short)(aptg.FirstColumn + letUsShiftColumn1By1Column));
                    aptg.LastColumn  = ((short)(aptg.LastColumn + letUsShiftColumn1By1Column));
                }
            }
            String newFormula = HSSFFormulaParser.ToFormulaString(wb, ptgs);

            return(newFormula);
        }
Exemplo n.º 10
0
        private ParseNode comparisonExpression()
        {
            ParseNode result = concatExpression();

            while (true)
            {
                SkipWhite();
                switch (look)
                {
                case '=':
                case '>':
                case '<':
                    Ptg       comparisonToken = GetComparisonToken();
                    ParseNode other           = concatExpression();
                    result = new ParseNode(comparisonToken, result, other);
                    continue;
                }
                return(result); // finished with predicate expression
            }
        }
Exemplo n.º 11
0
        private Ptg AdjustPtgDueToShiftMove(Ptg ptg)
        {
            Ptg updatedPtg = null;

            if (ptg is Ref3DPtg)
            {
                Ref3DPtg ref1 = (Ref3DPtg)ptg;
                if (ref1.ExternSheetIndex == _srcSheetIndex)
                {
                    ref1.ExternSheetIndex = (_dstSheetIndex);
                    updatedPtg            = ref1;
                }
                else if (ref1.ExternSheetIndex == _dstSheetIndex)
                {
                    ref1.ExternSheetIndex = (_srcSheetIndex);
                    updatedPtg            = ref1;
                }
            }
            return(updatedPtg);
        }
Exemplo n.º 12
0
        private Ptg AdjustPtg(Ptg ptg, int currentExternSheetIx)
        {
            //return AdjustPtgDueToRowMove(ptg, currentExternSheetIx);
            switch (_mode)
            {
            case ShiftMode.RowMove:
                return(AdjustPtgDueToRowMove(ptg, currentExternSheetIx));

            case ShiftMode.RowCopy:
                // Covered Scenarios:
                // * row copy on same sheet
                // * row copy between different sheetsin the same workbook
                return(AdjustPtgDueToRowCopy(ptg));

            case ShiftMode.SheetMove:
                return(AdjustPtgDueToSheetMove(ptg));

            default:
                throw new InvalidOperationException("Unsupported shift mode: " + _mode);
            }
        }
Exemplo n.º 13
0
 private static bool IsSimpleValueFunction(Ptg token)
 {
     if (token is AbstractFunctionPtg)
     {
         AbstractFunctionPtg aptg = (AbstractFunctionPtg)token;
         if (aptg.DefaultOperandClass != Ptg.CLASS_VALUE)
         {
             return(false);
         }
         int numberOfOperands = aptg.NumberOfOperands;
         for (int i = numberOfOperands - 1; i >= 0; i--)
         {
             if (aptg.GetParameterClass(i) != Ptg.CLASS_VALUE)
             {
                 return(false);
             }
         }
         return(true);
     }
     return(false);
 }
Exemplo n.º 14
0
        public void TestConvertSharedFormulasOperandClasses_bug45123()
        {
            ILittleEndianInput in1 = TestcaseRecordInputStream.CreateLittleEndian(SHARED_FORMULA_WITH_REF_ARRAYS_DATA);
            int encodedLen         = in1.ReadUShort();

            Ptg[] sharedFormula = Ptg.ReadTokens(encodedLen, in1);

            SharedFormula sf = new SharedFormula(SpreadsheetVersion.EXCEL97);

            Ptg[] ConvertedFormula = sf.ConvertSharedFormulas(sharedFormula, 100, 200);

            RefPtg refPtg = (RefPtg)ConvertedFormula[1];

            Assert.AreEqual("$C101", refPtg.ToFormulaString());
            if (refPtg.PtgClass == Ptg.CLASS_REF)
            {
                throw new AssertionException("Identified bug 45123");
            }

            ConfirmOperandClasses(sharedFormula, ConvertedFormula);
        }
Exemplo n.º 15
0
        public override String ToString()
        {
            StringBuilder buffer = new StringBuilder();

            buffer.Append("[AI]\n");
            buffer.Append("    .linkType             = ").Append(HexDump.ByteToHex(LinkType)).Append('\n');
            buffer.Append("    .referenceType        = ").Append(HexDump.ByteToHex(ReferenceType)).Append('\n');
            buffer.Append("    .options              = ").Append(HexDump.ShortToHex(Options)).Append('\n');
            buffer.Append("    .customNumberFormat   = ").Append(IsCustomNumberFormat).Append('\n');
            buffer.Append("    .indexNumberFmtRecord = ").Append(HexDump.ShortToHex(IndexNumberFmtRecord)).Append('\n');
            buffer.Append("    .FormulaOfLink        = ").Append('\n');
            Ptg[] ptgs = field_5_formulaOfLink.Tokens;
            for (int i = 0; i < ptgs.Length; i++)
            {
                Ptg ptg = ptgs[i];
                buffer.Append(ptg.ToString()).Append(ptg.RVAType).Append('\n');
            }

            buffer.Append("[/AI]\n");
            return(buffer.ToString());
        }
Exemplo n.º 16
0
        public void TestShiftSheet2()
        {
            // 4 sheets, move a sheet from pos 1 to pos 2, i.e. current 2 becomes 1, current 1 becomes pos 2
            FormulaShifter shifter = FormulaShifter.CreateForSheetShift(1, 2);

            Ptg[] ptgs = new Ptg[] {
                new Ref3DPtg(new CellReference("first", 0, 0, true, true), 0),
                new Ref3DPtg(new CellReference("second", 0, 0, true, true), 1),
                new Ref3DPtg(new CellReference("third", 0, 0, true, true), 2),
                new Ref3DPtg(new CellReference("fourth", 0, 0, true, true), 3),
            };
            shifter.AdjustFormula(ptgs, -1);

            Assert.AreEqual(0, ((Ref3DPtg)ptgs[0]).ExternSheetIndex,
                            "formula previously pointing to sheet 0 should be unchanged");
            Assert.AreEqual(2, ((Ref3DPtg)ptgs[1]).ExternSheetIndex,
                            "formula previously pointing to sheet 1 should now point to sheet 2");
            Assert.AreEqual(1, ((Ref3DPtg)ptgs[2]).ExternSheetIndex,
                            "formula previously pointing to sheet 2 should now point to sheet 1");
            Assert.AreEqual(3, ((Ref3DPtg)ptgs[3]).ExternSheetIndex,
                            "formula previously pointing to sheet 3 should be unchanged");
        }
Exemplo n.º 17
0
        private static CellRangeAddress ShiftRange(FormulaShifter Shifter, CellRangeAddress cra, int currentExternSheetIx)
        {
            Ptg[] ptgs = new Ptg[1] {
                (Ptg) new AreaPtg(cra.FirstRow, cra.LastRow, cra.FirstColumn, cra.LastColumn, false, false, false, false)
            };
            if (!Shifter.AdjustFormula(ptgs, currentExternSheetIx))
            {
                return(cra);
            }
            Ptg ptg = ptgs[0];

            if (ptg is AreaPtg)
            {
                AreaPtg areaPtg = (AreaPtg)ptg;
                return(new CellRangeAddress(areaPtg.FirstRow, areaPtg.LastRow, areaPtg.FirstColumn, areaPtg.LastColumn));
            }
            if (ptg is AreaErrPtg)
            {
                return((CellRangeAddress)null);
            }
            throw new InvalidOperationException("Unexpected Shifted ptg class (" + ptg.GetType().Name + ")");
        }
Exemplo n.º 18
0
        private static Ptg CreateDeletedRef(Ptg ptg)
        {
            if (ptg is RefPtg)
            {
                return(new RefErrorPtg());
            }
            if (ptg is Ref3DPtg)
            {
                Ref3DPtg rptg = (Ref3DPtg)ptg;
                return(new DeletedRef3DPtg(rptg.ExternSheetIndex));
            }
            if (ptg is AreaPtg)
            {
                return(new AreaErrPtg());
            }
            if (ptg is Area3DPtg)
            {
                Area3DPtg area3DPtg = (Area3DPtg)ptg;
                return(new DeletedArea3DPtg(area3DPtg.ExternSheetIndex));
            }

            throw new ArgumentException("Unexpected ref ptg class (" + ptg.GetType().Name + ")");
        }
Exemplo n.º 19
0
        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 + ")");
        }
Exemplo n.º 20
0
 private void UpdatePtg(Ptg ptg, String oldName, String newName)
 {
     if (ptg is Pxg)
     {
         Pxg pxg = (Pxg)ptg;
         if (pxg.ExternalWorkbookNumber < 1)
         {
             if (pxg.SheetName != null &&
                 pxg.SheetName.Equals(oldName))
             {
                 pxg.SheetName = (newName);
             }
             if (pxg is Pxg3D)
             {
                 Pxg3D pxg3D = (Pxg3D)pxg;
                 if (pxg3D.LastSheetName != null &&
                     pxg3D.LastSheetName.Equals(oldName))
                 {
                     pxg3D.LastSheetName = (/*setter*/ newName);
                 }
             }
         }
     }
 }
Exemplo n.º 21
0
        /**
         * Static method To convert an array of {@link Ptg}s in RPN order
         * To a human readable string format in infix mode.
         * @param book  used for defined names and 3D references
         * @param ptgs  must not be <c>null</c>
         * @return a human readable String
         */
        public static String ToFormulaString(IFormulaRenderingWorkbook book, Ptg[] ptgs)
        {
            if (ptgs == null || ptgs.Length == 0)
            {
                throw new ArgumentException("ptgs must not be null");
            }
            Stack stack = new Stack();

            for (int i = 0; i < ptgs.Length; i++)
            {
                Ptg ptg = ptgs[i];
                // TODO - what about MemNoMemPtg?
                if (ptg is MemAreaPtg || ptg is MemFuncPtg || ptg is MemErrPtg)
                {
                    // marks the start of a list of area expressions which will be naturally combined
                    // by their trailing operators (e.g. UnionPtg)
                    // TODO - Put comment and throw exception in ToFormulaString() of these classes
                    continue;
                }
                if (ptg is ParenthesisPtg)
                {
                    String contents = (String)stack.Pop();
                    stack.Push("(" + contents + ")");
                    continue;
                }
                if (ptg is AttrPtg)
                {
                    AttrPtg attrPtg = ((AttrPtg)ptg);
                    if (attrPtg.IsOptimizedIf || attrPtg.IsOptimizedChoose || attrPtg.IsSkip)
                    {
                        continue;
                    }
                    if (attrPtg.IsSpace)
                    {
                        // POI currently doesn't render spaces in formulas
                        continue;
                        // but if it ever did, care must be taken:
                        // tAttrSpace comes *before* the operand it applies To, which may be consistent
                        // with how the formula text appears but is against the RPN ordering assumed here
                    }
                    if (attrPtg.IsSemiVolatile)
                    {
                        // similar To tAttrSpace - RPN is violated
                        continue;
                    }
                    if (attrPtg.IsSum)
                    {
                        String[] operands = GetOperands(stack, attrPtg.NumberOfOperands);
                        stack.Push(attrPtg.ToFormulaString(operands));
                        continue;
                    }
                    throw new Exception("Unexpected tAttr: " + attrPtg.ToString());
                }

                if (ptg is WorkbookDependentFormula)
                {
                    WorkbookDependentFormula optg = (WorkbookDependentFormula)ptg;
                    stack.Push(optg.ToFormulaString(book));
                    continue;
                }
                if (!(ptg is OperationPtg))
                {
                    stack.Push(ptg.ToFormulaString());
                    continue;
                }

                OperationPtg o         = (OperationPtg)ptg;
                String[]     operands1 = GetOperands(stack, o.NumberOfOperands);
                stack.Push(o.ToFormulaString(operands1));
            }
            if (stack.Count == 0)
            {
                // inspection of the code above reveals that every stack.pop() is followed by a
                // stack.push(). So this is either an internal error or impossible.
                throw new InvalidOperationException("Stack underflow");
            }
            String result = (String)stack.Pop();

            if (stack.Count != 0)
            {
                // Might be caused by some Tokens like AttrPtg and Mem*Ptg, which really shouldn't
                // Put anything on the stack
                throw new InvalidOperationException("too much stuff left on the stack");
            }
            return(result);
        }
Exemplo n.º 22
0
        private void ConfirmCell(ICell formulaCell, String formula, HSSFWorkbook wb)
        {
            Ptg[] excelPtgs    = FormulaExtractor.GetPtgs(formulaCell);
            Ptg[] poiPtgs      = HSSFFormulaParser.Parse(formula, wb);
            int   nExcelTokens = excelPtgs.Length;
            int   nPoiTokens   = poiPtgs.Length;

            if (nExcelTokens != nPoiTokens)
            {
                if (nExcelTokens == nPoiTokens + 1 && excelPtgs[0].GetType() == typeof(AttrPtg))
                {
                    // compensate for missing tAttrVolatile, which belongs in any formula
                    // involving OFFSET() et al. POI currently does not insert where required
                    Ptg[] temp = new Ptg[nExcelTokens];
                    temp[0] = excelPtgs[0];
                    Array.Copy(poiPtgs, 0, temp, 1, nPoiTokens);
                    poiPtgs = temp;
                }
                else
                {
                    throw new Exception("Expected " + nExcelTokens + " tokens but got "
                                        + nPoiTokens);
                }
            }
            bool          hasMismatch = false;
            StringBuilder sb          = new StringBuilder();

            for (int i = 0; i < nExcelTokens; i++)
            {
                Ptg poiPtg   = poiPtgs[i];
                Ptg excelPtg = excelPtgs[i];
                if (excelPtg.GetType() != poiPtg.GetType())
                {
                    hasMismatch = true;
                    sb.Append("  mismatch token type[" + i + "] " + GetShortClassName(excelPtg) + " "
                              + excelPtg.RVAType + " - " + GetShortClassName(poiPtg) + " "
                              + poiPtg.RVAType);
                    sb.Append(Environment.NewLine);
                    continue;
                }
                if (poiPtg.IsBaseToken)
                {
                    continue;
                }
                sb.Append("  token[" + i + "] " + excelPtg.ToString() + " "
                          + excelPtg.RVAType);

                if (excelPtg.PtgClass != poiPtg.PtgClass)
                {
                    hasMismatch = true;
                    sb.Append(" - was " + poiPtg.RVAType);
                }
                sb.Append(Environment.NewLine);
            }
            //if (false)
            //{ // Set 'true' to see trace of RVA values
            //    Console.WriteLine(formula);
            //    Console.WriteLine(sb.ToString());
            //}
            if (hasMismatch)
            {
                throw new AssertionException(sb.ToString());
            }
        }
Exemplo n.º 23
0
 public StringEval(Ptg ptg) : this(((StringPtg)ptg).Value)
 {
 }
Exemplo n.º 24
0
        /**
         * returns an appropriate Eval impl instance for the Ptg. The Ptg must be
         * one of: Area3DPtg, AreaPtg, ReferencePtg, Ref3DPtg, IntPtg, NumberPtg,
         * StringPtg, BoolPtg <br/>special Note: OperationPtg subtypes cannot be
         * passed here!
         */
        private ValueEval GetEvalForPtg(Ptg ptg, OperationEvaluationContext ec)
        {
            //  consider converting all these (ptg is XxxPtg) expressions To (ptg.GetType() == XxxPtg.class)

            if (ptg is NamePtg)
            {
                // named ranges, macro functions
                NamePtg         namePtg    = (NamePtg)ptg;
                IEvaluationName nameRecord = _workbook.GetName(namePtg);
                if (nameRecord.IsFunctionName)
                {
                    return(new NameEval(nameRecord.NameText));
                }
                if (nameRecord.HasFormula)
                {
                    return(EvaluateNameFormula(nameRecord.NameDefinition, ec));
                }

                throw new Exception("Don't now how To evalate name '" + nameRecord.NameText + "'");
            }
            if (ptg is NameXPtg)
            {
                return(ec.GetNameXEval(((NameXPtg)ptg)));
            }

            if (ptg is IntPtg)
            {
                return(new NumberEval(((IntPtg)ptg).Value));
            }
            if (ptg is NumberPtg)
            {
                return(new NumberEval(((NumberPtg)ptg).Value));
            }
            if (ptg is StringPtg)
            {
                return(new StringEval(((StringPtg)ptg).Value));
            }
            if (ptg is BoolPtg)
            {
                return(BoolEval.ValueOf(((BoolPtg)ptg).Value));
            }
            if (ptg is ErrPtg)
            {
                return(ErrorEval.ValueOf(((ErrPtg)ptg).ErrorCode));
            }
            if (ptg is MissingArgPtg)
            {
                return(MissingArgEval.instance);
            }
            if (ptg is AreaErrPtg || ptg is RefErrorPtg ||
                ptg is DeletedArea3DPtg || ptg is DeletedRef3DPtg)
            {
                return(ErrorEval.REF_INVALID);
            }
            if (ptg is Ref3DPtg)
            {
                Ref3DPtg rptg = (Ref3DPtg)ptg;
                return(ec.GetRef3DEval(rptg.Row, rptg.Column, rptg.ExternSheetIndex));
            }
            if (ptg is Area3DPtg)
            {
                Area3DPtg aptg = (Area3DPtg)ptg;
                return(ec.GetArea3DEval(aptg.FirstRow, aptg.FirstColumn, aptg.LastRow, aptg.LastColumn, aptg.ExternSheetIndex));
            }
            if (ptg is RefPtg)
            {
                RefPtg rptg = (RefPtg)ptg;
                return(ec.GetRefEval(rptg.Row, rptg.Column));
            }
            if (ptg is AreaPtg)
            {
                AreaPtg aptg = (AreaPtg)ptg;
                return(ec.GetAreaEval(aptg.FirstRow, aptg.FirstColumn, aptg.LastRow, aptg.LastColumn));
            }

            if (ptg is UnknownPtg)
            {
                // POI uses UnknownPtg when the encoded Ptg array seems To be corrupted.
                // This seems To occur in very rare cases (e.g. unused name formulas in bug 44774, attachment 21790)
                // In any case, formulas are re-parsed before execution, so UnknownPtg should not Get here
                throw new RuntimeException("UnknownPtg not allowed");
            }
            if (ptg is ExpPtg)
            {
                // ExpPtg is used for array formulas and shared formulas.
                // it is currently unsupported, and may not even get implemented here
                throw new RuntimeException("ExpPtg currently not supported");
            }
            throw new RuntimeException("Unexpected ptg class (" + ptg.GetType().Name + ")");
        }
Exemplo n.º 25
0
        // visibility raised for testing
        /* package */
        public ValueEval EvaluateFormula(OperationEvaluationContext ec, Ptg[] ptgs)
        {
            Stack <ValueEval> stack = new Stack <ValueEval>();

            for (int i = 0, iSize = ptgs.Length; i < iSize; i++)
            {
                // since we don't know how To handle these yet :(
                Ptg ptg = ptgs[i];
                if (ptg is AttrPtg)
                {
                    AttrPtg attrPtg = (AttrPtg)ptg;
                    if (attrPtg.IsSum)
                    {
                        // Excel prefers To encode 'SUM()' as a tAttr Token, but this evaluator
                        // expects the equivalent function Token
                        //byte nArgs = 1;  // tAttrSum always Has 1 parameter
                        ptg = FuncVarPtg.SUM;//.Create("SUM", nArgs);
                    }
                    if (attrPtg.IsOptimizedChoose)
                    {
                        ValueEval arg0      = stack.Pop();
                        int[]     jumpTable = attrPtg.JumpTable;
                        int       dist;
                        int       nChoices = jumpTable.Length;
                        try
                        {
                            int switchIndex = Choose.EvaluateFirstArg(arg0, ec.RowIndex, ec.ColumnIndex);
                            if (switchIndex < 1 || switchIndex > nChoices)
                            {
                                stack.Push(ErrorEval.VALUE_INVALID);
                                dist = attrPtg.ChooseFuncOffset + 4; // +4 for tFuncFar(CHOOSE)
                            }
                            else
                            {
                                dist = jumpTable[switchIndex - 1];
                            }
                        }
                        catch (EvaluationException e)
                        {
                            stack.Push(e.GetErrorEval());
                            dist = attrPtg.ChooseFuncOffset + 4; // +4 for tFuncFar(CHOOSE)
                        }
                        // Encoded dist for tAttrChoose includes size of jump table, but
                        // countTokensToBeSkipped() does not (it counts whole tokens).
                        dist -= nChoices * 2 + 2; // subtract jump table size
                        i    += CountTokensToBeSkipped(ptgs, i, dist);
                        continue;
                    }
                    if (attrPtg.IsOptimizedIf)
                    {
                        ValueEval arg0 = stack.Pop();
                        bool      evaluatedPredicate;
                        try
                        {
                            evaluatedPredicate = If.EvaluateFirstArg(arg0, ec.RowIndex, ec.ColumnIndex);
                        }
                        catch (EvaluationException e)
                        {
                            stack.Push(e.GetErrorEval());
                            int dist = attrPtg.Data;
                            i      += CountTokensToBeSkipped(ptgs, i, dist);
                            attrPtg = (AttrPtg)ptgs[i];
                            dist    = attrPtg.Data + 1;
                            i      += CountTokensToBeSkipped(ptgs, i, dist);
                            continue;
                        }
                        if (evaluatedPredicate)
                        {
                            // nothing to skip - true param folows
                        }
                        else
                        {
                            int dist = attrPtg.Data;
                            i += CountTokensToBeSkipped(ptgs, i, dist);
                            Ptg nextPtg = ptgs[i + 1];
                            if (ptgs[i] is AttrPtg && nextPtg is FuncVarPtg)
                            {
                                // this is an if statement without a false param (as opposed to MissingArgPtg as the false param)
                                i++;
                                stack.Push(BoolEval.FALSE);
                            }
                        }
                        continue;
                    }
                    if (attrPtg.IsSkip)
                    {
                        int dist = attrPtg.Data + 1;
                        i += CountTokensToBeSkipped(ptgs, i, dist);
                        if (stack.Peek() == MissingArgEval.instance)
                        {
                            stack.Pop();
                            stack.Push(BlankEval.instance);
                        }
                        continue;
                    }
                }
                if (ptg is ControlPtg)
                {
                    // skip Parentheses, Attr, etc
                    continue;
                }
                if (ptg is MemFuncPtg)
                {
                    // can ignore, rest of Tokens for this expression are in OK RPN order
                    continue;
                }
                if (ptg is MemErrPtg)
                {
                    continue;
                }

                ValueEval opResult;
                if (ptg is OperationPtg)
                {
                    OperationPtg optg = (OperationPtg)ptg;

                    if (optg is UnionPtg)
                    {
                        continue;
                    }

                    int         numops = optg.NumberOfOperands;
                    ValueEval[] ops    = new ValueEval[numops];

                    // storing the ops in reverse order since they are popping
                    for (int j = numops - 1; j >= 0; j--)
                    {
                        ValueEval p = (ValueEval)stack.Pop();
                        ops[j] = p;
                    }
                    //				logDebug("Invoke " + operation + " (nAgs=" + numops + ")");
                    opResult = OperationEvaluatorFactory.Evaluate(optg, ops, ec);
                }
                else
                {
                    opResult = GetEvalForPtg(ptg, ec);
                }
                if (opResult == null)
                {
                    throw new Exception("Evaluation result must not be null");
                }
                //			logDebug("push " + opResult);
                stack.Push(opResult);
            }

            ValueEval value = ((ValueEval)stack.Pop());

            if (stack.Count != 0)
            {
                throw new InvalidOperationException("evaluation stack not empty");
            }
            return(DereferenceResult(value, ec.RowIndex, ec.ColumnIndex));
        }
Exemplo n.º 26
0
        /**
         * @param callerForceArrayFlag <c>true</c> if one of the current node's parents is a
         * function Ptg which Has been Changed from default 'V' To 'A' type (due To requirements on
         * the function return value).
         */
        private void TransformNode(ParseNode node, byte desiredOperandClass,
                                   bool callerForceArrayFlag)
        {
            Ptg token = node.GetToken();

            ParseNode[] children          = node.GetChildren();
            bool        IsSimpleValueFunc = IsSimpleValueFunction(token);

            if (IsSimpleValueFunc)
            {
                bool localForceArray = desiredOperandClass == Ptg.CLASS_ARRAY;
                for (int i = 0; i < children.Length; i++)
                {
                    TransformNode(children[i], desiredOperandClass, localForceArray);
                }
                SetSimpleValueFuncClass((AbstractFunctionPtg)token, desiredOperandClass, callerForceArrayFlag);
                return;
            }
            if (IsSingleArgSum(token))
            {
                // Need to process the argument of SUM with transformFunctionNode below
                // so make a dummy FuncVarPtg for that call.
                token = FuncVarPtg.SUM;
                // Note - the tAttrSum token (node.getToken()) is a base
                // token so does not need to have its operand class set
            }
            if (token is ValueOperatorPtg || token is ControlPtg ||
                token is MemFuncPtg ||
                token is MemAreaPtg ||
                token is UnionPtg)
            {
                // Value Operator Ptgs and Control are base Tokens, so Token will be unchanged
                // but any child nodes are processed according To desiredOperandClass and callerForceArrayFlag

                // As per OOO documentation Sec 3.2.4 "Token Class Transformation", "Step 1"
                // All direct operands of value operators that are initially 'R' type will
                // be converted To 'V' type.
                byte localDesiredOperandClass = desiredOperandClass == Ptg.CLASS_REF ? Ptg.CLASS_VALUE : desiredOperandClass;
                for (int i = 0; i < children.Length; i++)
                {
                    TransformNode(children[i], localDesiredOperandClass, callerForceArrayFlag);
                }
                return;
            }
            if (token is AbstractFunctionPtg)
            {
                TransformFunctionNode((AbstractFunctionPtg)token, children, desiredOperandClass, callerForceArrayFlag);
                return;
            }
            if (children.Length > 0)
            {
                //if (token == RangePtg.instance)
                if (token is OperationPtg)
                {
                    // TODO is any Token transformation required under the various ref operators?
                    return;
                }
                throw new InvalidOperationException("Node should not have any children");
            }

            if (token.IsBaseToken)
            {
                // nothing To do
                return;
            }
            token.PtgClass = (TransformClass(token.PtgClass, desiredOperandClass, callerForceArrayFlag));
        }
Exemplo n.º 27
0
        /**
         * Constructs an EmbeddedObjectRef record and Sets its fields appropriately.
         *
         * @param in the record input stream.
         */
        public EmbeddedObjectRefSubRecord(LittleEndianInput in1, int size)
        {
            // Much guess-work going on here due to lack of any documentation.
            // See similar source code in OOO:
            // http://lxr.go-oo.org/source/sc/sc/source/filter/excel/xiescher.cxx
            // 1223 void XclImpOleObj::ReadPictFmla( XclImpStream& rStrm, sal_uInt16 nRecSize )

            int streamIdOffset = in1.ReadShort(); // OOO calls this 'nFmlaLen'
            int remaining      = size - LittleEndianConstants.SHORT_SIZE;

            int dataLenAfterFormula = remaining - streamIdOffset;
            int formulaSize         = in1.ReadUShort();

            remaining          -= LittleEndianConstants.SHORT_SIZE;
            field_1_unknown_int = in1.ReadInt();
            remaining          -= LittleEndianConstants.INT_SIZE;
            byte[] formulaRawBytes = ReadRawData(in1, formulaSize);
            remaining     -= formulaSize;
            field_2_refPtg = ReadRefPtg(formulaRawBytes);
            if (field_2_refPtg == null)
            {
                // common case
                // field_2_n16 seems to be 5 here
                // The formula almost looks like tTbl but the row/column values seem like garbage.
                field_2_unknownFormulaData = formulaRawBytes;
            }
            else
            {
                field_2_unknownFormulaData = null;
            }


            int stringByteCount;

            if (remaining >= dataLenAfterFormula + 3)
            {
                int tag = in1.ReadByte();
                stringByteCount = LittleEndianConstants.BYTE_SIZE;
                if (tag != 0x03)
                {
                    throw new RecordFormatException("Expected byte 0x03 here");
                }
                int nChars = in1.ReadUShort();
                stringByteCount += LittleEndianConstants.SHORT_SIZE;
                if (nChars > 0)
                {
                    // OOO: the 4th way Xcl stores a unicode string: not even a Grbit byte present if Length 0
                    field_3_unicode_flag = (in1.ReadByte() & 0x01) != 0;
                    stringByteCount     += LittleEndianConstants.BYTE_SIZE;
                    if (field_3_unicode_flag)
                    {
                        field_4_ole_classname = StringUtil.ReadUnicodeLE(in1, nChars);
                        stringByteCount      += nChars * 2;
                    }
                    else
                    {
                        field_4_ole_classname = StringUtil.ReadCompressedUnicode(in1, nChars);
                        stringByteCount      += nChars;
                    }
                }
                else
                {
                    field_4_ole_classname = "";
                }
            }
            else
            {
                field_4_ole_classname = null;
                stringByteCount       = 0;
            }
            remaining -= stringByteCount;
            // Pad to next 2-byte boundary
            if (((stringByteCount + formulaSize) % 2) != 0)
            {
                int b = in1.ReadByte();
                remaining -= LittleEndianConstants.BYTE_SIZE;
                if (field_2_refPtg != null && field_4_ole_classname == null)
                {
                    field_4_unknownByte = (byte)b;
                }
            }
            int nUnexpectedPadding = remaining - dataLenAfterFormula;

            if (nUnexpectedPadding > 0)
            {
                Console.WriteLine("Discarding " + nUnexpectedPadding + " unexpected padding bytes ");
                ReadRawData(in1, nUnexpectedPadding);
                remaining -= nUnexpectedPadding;
            }

            // Fetch the stream ID
            if (dataLenAfterFormula >= 4)
            {
                field_5_stream_id = in1.ReadInt();
                remaining        -= LittleEndianConstants.INT_SIZE;
            }
            else
            {
                field_5_stream_id = null;
            }

            field_6_unknown = ReadRawData(in1, remaining);
        }
Exemplo n.º 28
0
 public ParseNode(Ptg token)
     : this(token, EMPTY_ARRAY)
 {
 }
Exemplo n.º 29
0
 public BoolEval(Ptg ptg)
 {
     this.value = ((BoolPtg)ptg).Value;
 }
Exemplo n.º 30
0
 public ParseNode(Ptg token, ParseNode child0, ParseNode child1)
     : this(token, new ParseNode[] { child0, child1, })
 {
 }
Exemplo n.º 31
0
        public TextObjectRecord(RecordInputStream in1)
        {
            field_1_options         = in1.ReadUShort();
            field_2_textOrientation = in1.ReadUShort();
            field_3_reserved4       = in1.ReadUShort();
            field_4_reserved5       = in1.ReadUShort();
            field_5_reserved6       = in1.ReadUShort();
            int field_6_textLength           = in1.ReadUShort();
            int field_7_formattingDataLength = in1.ReadUShort();

            field_8_reserved7 = in1.ReadInt();

            if (in1.Remaining > 0)
            {
                // Text Objects can have simple reference formulas
                // (This bit not mentioned in the MS document)
                if (in1.Remaining < 11)
                {
                    throw new RecordFormatException("Not enough remaining data for a link formula");
                }
                int formulaSize = in1.ReadUShort();
                _unknownPreFormulaInt = in1.ReadInt();
                Ptg[] ptgs = Ptg.ReadTokens(formulaSize, in1);
                if (ptgs.Length != 1)
                {
                    throw new RecordFormatException("Read " + ptgs.Length
                                                    + " tokens but expected exactly 1");
                }
                _linkRefPtg = (OperandPtg)ptgs[0];
                if (in1.Remaining > 0)
                {
                    _unknownPostFormulaByte = (byte)in1.ReadByte();
                }
                else
                {
                    _unknownPostFormulaByte = null;
                }
            }
            else
            {
                _linkRefPtg = null;
            }
            if (in1.Remaining > 0)
            {
                throw new RecordFormatException("Unused " + in1.Remaining + " bytes at end of record");
            }

            String text;

            if (field_6_textLength > 0)
            {
                text = ReadRawString(in1, field_6_textLength);
            }
            else
            {
                text = "";
            }
            _text = new HSSFRichTextString(text);

            if (field_7_formattingDataLength > 0)
            {
                ProcessFontRuns(in1, _text, field_7_formattingDataLength);
            }
        }