/**
  * This formula was copied from a formula already present in the writable
  * workbook.  Requires special handling to sort out the cell references
  *
  * @param ws the workbook settings
  * @param es the external sheet
  * @param nt the name table
  */
 private void initializeCopiedFormula(WorkbookSettings ws,
                                      ExternalSheet es, WorkbookMethods nt)
 {
     try
     {
         parser = new FormulaParser(formulaBytes, this, es, nt, ws);
         parser.parse();
         parser.adjustRelativeCellReferences
             (getColumn() - copiedFrom.getColumn(),
             getRow() - copiedFrom.getRow());
         formulaString = parser.getFormula();
         formulaBytes  = parser.getBytes();
     }
     catch (FormulaException e)
     {
         try
         {
             // try again, with an error formula
             formulaToParse = "ERROR(1)";
             parser         = new FormulaParser(formulaToParse, es, nt, ws);
             parser.parse();
             formulaString = parser.getFormula();
             formulaBytes  = parser.getBytes();
         }
         catch (FormulaException e2)
         {
             // fail silently
             //logger.error(string.Empty, e2);
         }
     }
 }
        /**
         * Gets the raw bytes for the formula.  This will include the
         * parsed tokens array.  Used when copying spreadsheets
         *
         * @return the raw record data
         * @exception FormulaException
         */
        public override byte[] getFormulaData()
        {
            if (!getSheet().getWorkbookBof().isBiff8())
            {
                throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
            }

            // Get the tokens, taking into account the mapping from shared
            // formula specific values into normal values
            FormulaParser fp = new FormulaParser
                                   (getTokens(), this,
                                   getExternalSheet(), getNameTable(),
                                   getSheet().getWorkbook().getSettings());

            fp.parse();
            byte[] rpnTokens = fp.getBytes();

            byte[] data = new byte[rpnTokens.Length + 22];

            // Set the standard info for this cell
            IntegerHelper.getTwoBytes(getRow(), data, 0);
            IntegerHelper.getTwoBytes(getColumn(), data, 2);
            IntegerHelper.getTwoBytes(getXFIndex(), data, 4);
            DoubleHelper.getIEEEBytes(value, data, 6);

            // Now copy in the parsed tokens
            System.Array.Copy(rpnTokens, 0, data, 22, rpnTokens.Length);
            IntegerHelper.getTwoBytes(rpnTokens.Length, data, 20);

            // Lop off the standard information
            byte[] d = new byte[data.Length - 6];
            System.Array.Copy(data, 6, d, 0, data.Length - 6);

            return(d);
        }
        /**
         * string formula specific exception handling.  Can't really create
         * a formula (as it will look for a cell of that name, so just
         * create a STRING record containing the contents
         *
         * @return the bodged data
         */
        public override byte[] handleFormulaException()
        {
            byte[] expressiondata = null;
            byte[] celldata       = base.getCellData();

            // Generate an appropriate dummy formula
            WritableWorkbookImpl w      = getSheet().getWorkbook();
            FormulaParser        parser = new FormulaParser("\"" + getContents() + "\"", w, w,
                                                            w.getSettings());

            // Get the bytes for the dummy formula
            try
            {
                parser.parse();
            }
            catch (FormulaException e2)
            {
                //logger.warn(e2.Message);
                parser = new FormulaParser("\"ERROR\"", w, w, w.getSettings());
                try
                {
                    parser.parse();
                }
                catch (FormulaException e3)
                {
                    Assert.verify(false);
                }
            }
            byte[] formulaBytes = parser.getBytes();
            expressiondata = new byte[formulaBytes.Length + 16];
            IntegerHelper.getTwoBytes(formulaBytes.Length, expressiondata, 14);
            System.Array.Copy(formulaBytes, 0, expressiondata, 16,
                              formulaBytes.Length);

            // Set the recalculate on load bit
            expressiondata[8] |= 0x02;

            byte[] data = new byte[celldata.Length +
                                   expressiondata.Length];
            System.Array.Copy(celldata, 0, data, 0, celldata.Length);
            System.Array.Copy(expressiondata, 0, data,
                              celldata.Length, expressiondata.Length);

            // Set the type bits to indicate a string formula
            data[6] = 0;
            unchecked
            {
                data[12] = (byte)-1;
                data[13] = (byte)-1;
            }

            return(data);
        }
        /**
         * Gets the binary data for output to file
         *
         * @return the binary data
         */
        public override byte[] getData()
        {
            // Take the superclass cell data to take into account cell
            // rationalization
            byte[] celldata       = base.getData();
            byte[] expressiondata = null;

            try
            {
                if (parser == null)
                {
                    expressiondata = formula.getFormulaData();
                }
                else
                {
                    byte[] formulaBytes = parser.getBytes();
                    expressiondata = new byte[formulaBytes.Length + 16];
                    IntegerHelper.getTwoBytes(formulaBytes.Length, expressiondata, 14);
                    System.Array.Copy(formulaBytes, 0, expressiondata, 16,
                                      formulaBytes.Length);
                }

                // Set the recalculate on load bit
                expressiondata[8] |= 0x02;

                byte[] data = new byte[celldata.Length +
                                       expressiondata.Length];
                System.Array.Copy(celldata, 0, data, 0, celldata.Length);
                System.Array.Copy(expressiondata, 0, data,
                                  celldata.Length, expressiondata.Length);
                return(data);
            }
            catch (FormulaException e)
            {
                // Something has gone wrong trying to read the formula data eg. it
                // might be unsupported biff7 data
                //logger.warn(CellReferenceHelper.getCellReference(getColumn(), getRow()) + " " + e.Message);
                return(handleFormulaException());
            }
        }
        /**
         * Initializes the string and the formula bytes.  In order to get
         * access to the workbook settings, the object is not initialized until
         * it is added to the sheet
         *
         * @param ws the workbook settings
         * @param es the external sheet
         * @param nt the name table
         */
        private void initialize(WorkbookSettings ws, ExternalSheet es,
                                WorkbookMethods nt)
        {
            if (copiedFrom != null)
            {
                initializeCopiedFormula(ws, es, nt);
                return;
            }

            parser = new FormulaParser(formulaToParse, es, nt, ws);

            try
            {
                parser.parse();
                formulaString = parser.getFormula();
                formulaBytes  = parser.getBytes();
            }
            catch (FormulaException e)
            {
                //logger.warn(e.Message + " when parsing formula " + formulaToParse + " in cell " +
                //   getSheet().getName() + "!" +
                //     CellReferenceHelper.getCellReference(getColumn(), getRow()));

                try
                {
                    // try again, with an error formula
                    formulaToParse = "ERROR(1)";
                    parser         = new FormulaParser(formulaToParse, es, nt, ws);
                    parser.parse();
                    formulaString = parser.getFormula();
                    formulaBytes  = parser.getBytes();
                }
                catch (FormulaException e2)
                {
                    // fail silently
                    //logger.error(string.Empty, e2);
                }
            }
        }
Exemple #6
0
        /**
         * Error formula specific exception handling.  Can't really create
         * a formula (as it will look for a cell of that name, so just
         * create a STRING record containing the contents
         *
         * @return the bodged data
         */
        public override byte[] handleFormulaException()
        {
            byte[] expressiondata = null;
            byte[] celldata       = base.getCellData();

            // Generate an appropriate dummy formula
            WritableWorkbookImpl w      = getSheet().getWorkbook();
            FormulaParser        parser = new FormulaParser(getValue().ToString(), w, w, w.getSettings());

            // Get the bytes for the dummy formula
            try
            {
                parser.parse();
            }
            catch (FormulaException e2)
            {
                //logger.warn(e2.Message);
            }
            byte[] formulaBytes = parser.getBytes();
            expressiondata = new byte[formulaBytes.Length + 16];
            IntegerHelper.getTwoBytes(formulaBytes.Length, expressiondata, 14);
            System.Array.Copy(formulaBytes, 0, expressiondata, 16,
                              formulaBytes.Length);

            // Set the recalculate on load bit
            expressiondata[8] |= 0x02;

            byte[] data = new byte[celldata.Length +
                                   expressiondata.Length];
            System.Array.Copy(celldata, 0, data, 0, celldata.Length);
            System.Array.Copy(expressiondata, 0, data,
                              celldata.Length, expressiondata.Length);

            // Store the value in the formula
            DoubleHelper.getIEEEBytes(getValue(), data, 6);

            return(data);
        }
Exemple #7
0
        /**
         * Gets the data
         */
        public virtual byte[] getData()
        {
            // Compute the length of the data
            byte[] f1Bytes = formula1 != null?formula1.getBytes() : new byte[0];

            byte[] f2Bytes = formula2 != null?formula2.getBytes() : new byte[0];

            int dataLength = 4 +                          // the options
                             promptTitle.Length * 2 + 3 + // the prompt title
                             errorTitle.Length * 2 + 3 +  // the error title
                             promptText.Length * 2 + 3 +  // the prompt text
                             errorText.Length * 2 + 3 +   // the error text
                             f1Bytes.Length + 2 +         // first formula
                             f2Bytes.Length + 2 +         // second formula
                             +4 +                         // unused bytes
                             10;                          // cell range

            byte[] data = new byte[dataLength];

            // The position
            int pos = 0;

            // The options
            int options = 0;

            options |= type.getValue();
            options |= errorStyle.getValue() << 4;
            options |= condition.getValue() << 20;

            if (stringListGiven)
            {
                options |= STRING_LIST_GIVEN_MASK;
            }

            if (emptyCellsAllowed)
            {
                options |= EMPTY_CELLS_ALLOWED_MASK;
            }

            if (suppressArrow)
            {
                options |= SUPPRESS_ARROW_MASK;
            }

            if (showPrompt)
            {
                options |= SHOW_PROMPT_MASK;
            }

            if (showError)
            {
                options |= SHOW_ERROR_MASK;
            }

            // The text
            IntegerHelper.getFourBytes(options, data, pos);
            pos += 4;

            IntegerHelper.getTwoBytes(promptTitle.Length, data, pos);
            pos += 2;

            data[pos] = (byte)0x1;             // unicode indicator
            pos++;

            StringHelper.getUnicodeBytes(promptTitle, data, pos);
            pos += promptTitle.Length * 2;

            IntegerHelper.getTwoBytes(errorTitle.Length, data, pos);
            pos += 2;

            data[pos] = (byte)0x1;             // unicode indicator
            pos++;

            StringHelper.getUnicodeBytes(errorTitle, data, pos);
            pos += errorTitle.Length * 2;

            IntegerHelper.getTwoBytes(promptText.Length, data, pos);
            pos += 2;

            data[pos] = (byte)0x1;             // unicode indicator
            pos++;

            StringHelper.getUnicodeBytes(promptText, data, pos);
            pos += promptText.Length * 2;

            IntegerHelper.getTwoBytes(errorText.Length, data, pos);
            pos += 2;

            data[pos] = (byte)0x1;             // unicode indicator
            pos++;

            StringHelper.getUnicodeBytes(errorText, data, pos);
            pos += errorText.Length * 2;

            // Formula 1
            IntegerHelper.getTwoBytes(f1Bytes.Length, data, pos);
            pos += 4;

            System.Array.Copy(f1Bytes, 0, data, pos, f1Bytes.Length);
            pos += f1Bytes.Length;

            // Formula 2
            IntegerHelper.getTwoBytes(f2Bytes.Length, data, pos);
            pos += 4;

            System.Array.Copy(f2Bytes, 0, data, pos, f2Bytes.Length);
            pos += f2Bytes.Length;

            // The cell ranges
            IntegerHelper.getTwoBytes(1, data, pos);
            pos += 2;

            IntegerHelper.getTwoBytes(row1, data, pos);
            pos += 2;

            IntegerHelper.getTwoBytes(row2, data, pos);
            pos += 2;

            IntegerHelper.getTwoBytes(column1, data, pos);
            pos += 2;

            IntegerHelper.getTwoBytes(column2, data, pos);
            pos += 2;

            return(data);
        }
Exemple #8
0
        /**
         * Error formula specific exception handling.  Can't really create
         * a formula (as it will look for a cell of that name, so just
         * create a STRING record containing the contents
         *
         * @return the bodged data
         */
        public override byte[] handleFormulaException()
        {
            byte[] expressiondata = null;
            byte[] celldata       = base.getCellData();

            int    errorCode     = getErrorCode();
            string formulaString = null;

            if (errorCode == FormulaErrorCode.DIV0.getCode())
            {
                formulaString = "1/0";
            }
            else if (errorCode == FormulaErrorCode.VALUE.getCode())
            {
                formulaString = "\"\"/0";
            }
            else if (errorCode == FormulaErrorCode.REF.getCode())
            {
                formulaString = "\"#REF!\"";
            }
            else
            {
                formulaString = "\"ERROR\"";
            }

            // Generate an appropriate dummy formula
            WritableWorkbookImpl w      = getSheet().getWorkbook();
            FormulaParser        parser = new FormulaParser(formulaString, w, w,
                                                            w.getSettings());

            // Get the bytes for the dummy formula
            try
            {
                parser.parse();
            }
            catch (FormulaException e2)
            {
                //logger.warn(e2.Message);
            }

            byte[] formulaBytes = parser.getBytes();
            expressiondata = new byte[formulaBytes.Length + 16];
            IntegerHelper.getTwoBytes(formulaBytes.Length, expressiondata, 14);
            System.Array.Copy(formulaBytes, 0, expressiondata, 16, formulaBytes.Length);

            // Set the recalculate on load bit
            expressiondata[8] |= 0x02;

            byte[] data = new byte[celldata.Length + expressiondata.Length];
            System.Array.Copy(celldata, 0, data, 0, celldata.Length);
            System.Array.Copy(expressiondata, 0, data, celldata.Length, expressiondata.Length);

            // Set the type bits to indicate an error
            data[6]  = 2;
            data[12] = (byte)0xff;
            data[13] = (byte)0xff;

            // Set the error code
            data[8] = (byte)errorCode;

            return(data);
        }
 /**
  * Called when a column is inserted on the specified sheet.  Notifies all
  * RCIR cells of this change. The default implementation here does nothing
  *
  * @param s the sheet on which the column was inserted
  * @param sheetIndex the sheet index on which the column was inserted
  * @param col the column number which was inserted
  */
 public override void columnInserted(Sheet s, int sheetIndex, int col)
 {
     parser.columnInserted(sheetIndex, col, s == getSheet());
     formulaBytes = parser.getBytes();
 }