/** * Called by the cell value when the cell features are added to the sheet */ public void setCell(int col, int row, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws) { // If this is part of an extended cells validation, then do nothing // as this will already have been called and parsed when the top left // cell was added if (hasExtendedCellsValidation) { return; } row1 = row; row2 = row; column1 = col; column2 = col; formula1 = new FormulaParser(formula1String, es, nt, ws, ParseContext.DATA_VALIDATION); formula1.parse(); if (formula2String != null) { formula2 = new FormulaParser(formula2String, es, nt, ws, ParseContext.DATA_VALIDATION); formula2.parse(); } }
/// <summary> Gets the raw bytes for the formula. This will include the /// parsed tokens array. Used when copying spreadsheets /// /// </summary> /// <returns> the raw record data /// </returns> /// <exception cref=""> FormulaException /// </exception> public override sbyte[] getFormulaData() { // Get the tokens, taking into account the mapping from shared // formula specific values into normal values FormulaParser fp = new FormulaParser(getTokens(), this, ExternalSheet, NameTable, Sheet.Workbook.Settings); fp.parse(); sbyte[] rpnTokens = fp.Bytes; sbyte[] data = new sbyte[rpnTokens.Length + 22]; // Set the standard info for this cell IntegerHelper.getTwoBytes(Row, data, 0); IntegerHelper.getTwoBytes(Column, data, 2); IntegerHelper.getTwoBytes(XFIndex, data, 4); DoubleHelper.getIEEEBytes(Value, data, 6); // Now copy in the parsed tokens Array.Copy(rpnTokens, 0, data, 22, rpnTokens.Length); IntegerHelper.getTwoBytes(rpnTokens.Length, data, 20); // Lop off the standard information sbyte[] d = new sbyte[data.Length - 6]; Array.Copy(data, 6, d, 0, data.Length - 6); return(d); }
/** * 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); }
/** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * * @return TRUE if this formula was able to be imported, FALSE otherwise */ public bool handleImportedCellReferences(ExternalSheet es, WorkbookMethods mt, WorkbookSettings ws) { try { if (parser == null) { byte[] formulaData = formula.getFormulaData(); byte[] formulaBytes = new byte[formulaData.Length - 16]; System.Array.Copy(formulaData, 16, formulaBytes, 0, formulaBytes.Length); parser = new FormulaParser(formulaBytes, this, es, mt, ws); parser.parse(); } return(parser.handleImportedCellReferences()); } catch (FormulaException e) { //logger.warn("cannot import formula: " + e.Message); return(false); } }
/** * Called when a row 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 row was removed * @param sheetIndex the sheet index on which the column was removed * @param row the column number which was removed */ public override void rowRemoved(Sheet s, int sheetIndex, int row) { try { if (parser == null) { byte[] formulaData = formula.getFormulaData(); byte[] formulaBytes = new byte[formulaData.Length - 16]; System.Array.Copy(formulaData, 16, formulaBytes, 0, formulaBytes.Length); parser = new FormulaParser(formulaBytes, this, getSheet().getWorkbook(), getSheet().getWorkbook(), getSheet().getWorkbookSettings()); parser.parse(); } parser.rowRemoved(sheetIndex, row, s == getSheet()); } catch (FormulaException e) { //logger.warn("cannot remove row within formula: " + e.Message); } }
/** * 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 formula as an excel string * * @return the formula as an excel string * @exception FormulaException */ public string getFormula() { if (formulaString == null) { FormulaParser fp = new FormulaParser (tokens, this, externalSheet, nameTable, getSheet().getWorkbook().getSettings()); fp.parse(); formulaString = fp.getFormula(); } return(formulaString); }
/** * Gets the formula as an excel string * * @return the formula as an excel string * @exception FormulaException */ public string getFormula() { if (formulaString == null) { byte[] tokens = new byte[data.Length - 22]; System.Array.Copy(data, 22, tokens, 0, tokens.Length); FormulaParser fp = new FormulaParser (tokens, this, externalSheet, nameTable, getSheet().getWorkbook().getSettings()); fp.parse(); formulaString = fp.getFormula(); } return(formulaString); }
/** * Gets the formula as an excel string * * @return the formula as an excel string * @exception FormulaException */ public string getFormula() { // Note that the standard information was lopped off by the NumberFormula // record when creating this formula if (formulaString == null) { byte[] tokens = new byte[data.Length - 16]; System.Array.Copy(data, 16, tokens, 0, tokens.Length); FormulaParser fp = new FormulaParser (tokens, this, externalSheet, nameTable, getSheet().getWorkbook().getSettings()); fp.parse(); formulaString = fp.getFormula(); } return(formulaString); }
/** * 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); } } }
/** * 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); }
/** * Constructor */ public DVParser(byte[] data, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws) { Assert.verify(nt != null); wasCopied = false; int options = IntegerHelper.getInt(data[0], data[1], data[2], data[3]); int typeVal = options & 0xf; type = DVType.getType(typeVal); int errorStyleVal = (options & 0x70) >> 4; errorStyle = ErrorStyle.getErrorStyle(errorStyleVal); int conditionVal = (options & 0xf00000) >> 20; condition = Condition.getCondition(conditionVal); stringListGiven = (options & STRING_LIST_GIVEN_MASK) != 0; emptyCellsAllowed = (options & EMPTY_CELLS_ALLOWED_MASK) != 0; suppressArrow = (options & SUPPRESS_ARROW_MASK) != 0; showPrompt = (options & SHOW_PROMPT_MASK) != 0; showError = (options & SHOW_ERROR_MASK) != 0; int pos = 4; int length = IntegerHelper.getInt(data[pos], data[pos + 1]); if (length > 0 && data[pos + 2] == 0) { promptTitle = StringHelper.getString(data, length, pos + 3, ws); pos += length + 3; } else if (length > 0) { promptTitle = StringHelper.getUnicodeString(data, length, pos + 3); pos += length * 2 + 3; } else { pos += 3; } length = IntegerHelper.getInt(data[pos], data[pos + 1]); if (length > 0 && data[pos + 2] == 0) { errorTitle = StringHelper.getString(data, length, pos + 3, ws); pos += length + 3; } else if (length > 0) { errorTitle = StringHelper.getUnicodeString(data, length, pos + 3); pos += length * 2 + 3; } else { pos += 3; } length = IntegerHelper.getInt(data[pos], data[pos + 1]); if (length > 0 && data[pos + 2] == 0) { promptText = StringHelper.getString(data, length, pos + 3, ws); pos += length + 3; } else if (length > 0) { promptText = StringHelper.getUnicodeString(data, length, pos + 3); pos += length * 2 + 3; } else { pos += 3; } length = IntegerHelper.getInt(data[pos], data[pos + 1]); if (length > 0 && data[pos + 2] == 0) { errorText = StringHelper.getString(data, length, pos + 3, ws); pos += length + 3; } else if (length > 0) { errorText = StringHelper.getUnicodeString(data, length, pos + 3); pos += length * 2 + 3; } else { pos += 3; } int formula1Length = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 4; int formula1Pos = pos; pos += formula1Length; int formula2Length = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 4; int formula2Pos = pos; pos += formula2Length; pos += 2; row1 = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; row2 = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; column1 = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; column2 = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; hasExtendedCellsValidation = (row1 == row2 && column1 == column2) ? false : true; // Do the formulas try { // First, create a temporary blank cell for any formula relative // references EmptyCell tmprt = new EmptyCell(column1, row1); if (formula1Length != 0) { byte[] tokens = new byte[formula1Length]; System.Array.Copy(data, formula1Pos, tokens, 0, formula1Length); formula1 = new FormulaParser(tokens, tmprt, es, nt, ws, ParseContext.DATA_VALIDATION); formula1.parse(); } if (formula2Length != 0) { byte[] tokens = new byte[formula2Length]; System.Array.Copy(data, formula2Pos, tokens, 0, formula2Length); formula2 = new FormulaParser(tokens, tmprt, es, nt, ws, ParseContext.DATA_VALIDATION); formula2.parse(); } } catch (FormulaException e) { //logger.warn(e.Message + " for cells " + // CellReferenceHelper.getCellReference(column1,row1) + "-" + // CellReferenceHelper.getCellReference(column2,row2)); } }
/** * 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); }