/** * 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); } } }
/** * 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); }
/** * 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); }
/** * 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(); }