KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jxl > write > biff > ReadFormulaRecord


1 /*********************************************************************
2 *
3 * Copyright (C) 2002 Andrew Khan
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ***************************************************************************/

19
20 package jxl.write.biff;
21
22 import common.Assert;
23 import common.Logger;
24
25 import jxl.CellType;
26 import jxl.FormulaCell;
27 import jxl.Sheet;
28 import jxl.CellReferenceHelper;
29 import jxl.write.WritableCell;
30 import jxl.format.CellFormat;
31 import jxl.biff.Type;
32 import jxl.biff.FormattingRecords;
33 import jxl.biff.DoubleHelper;
34 import jxl.biff.IntegerHelper;
35 import jxl.biff.formula.FormulaException;
36 import jxl.biff.FormulaData;
37 import jxl.biff.formula.FormulaParser;
38 import jxl.biff.formula.FormulaException;
39
40 /**
41  * A formula record. This is invoked when copying a formula from a
42  * read only spreadsheet
43  * This method implements the FormulaData interface to allow the copying
44  * of writable sheets
45  */

46 class ReadFormulaRecord extends CellValue implements FormulaData
47 {
48   /**
49    * The logger
50    */

51   private static Logger logger = Logger.getLogger(ReadFormulaRecord.class);
52
53   /**
54    * The underlying formula from the read sheet
55    */

56   private FormulaData formula;
57
58   /**
59    * The formula parser
60    */

61   private FormulaParser parser;
62
63   /**
64    * Constructor
65    *
66    * @param f the formula to copy
67    */

68   protected ReadFormulaRecord(FormulaData f)
69   {
70     super(Type.FORMULA, f);
71     formula = f;
72   }
73
74   /**
75    * Gets the binary data for output to file
76    *
77    * @return the binary data
78    */

79   public byte[] getData()
80   {
81     // Take the superclass cell data to take into account cell
82
// rationalization
83
byte[] celldata = super.getData();
84     byte[] expressiondata = null;
85
86     try
87     {
88       if (parser == null)
89       {
90         expressiondata = formula.getFormulaData();
91       }
92       else
93       {
94         byte[] formulaBytes = parser.getBytes();
95         expressiondata = new byte[formulaBytes.length + 16];
96         IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14);
97         System.arraycopy(formulaBytes, 0, expressiondata, 16,
98                          formulaBytes.length);
99       }
100     }
101     catch (FormulaException e)
102     {
103       // Something has gone wrong trying to read the formula data eg. it
104
// might be unsupported biff7 data
105
logger.warn
106         (CellReferenceHelper.getCellReference(getColumn(), getRow()) +
107          " " + e.getMessage());
108
109       // Generate an appropriate dummy formula
110
WritableWorkbookImpl w = getSheet().getWorkbook();
111       if (formula.getType() == CellType.STRING_FORMULA)
112       {
113         parser = new FormulaParser("\"" + getContents() +"\"", w, w,
114                                    w.getSettings());
115       }
116       else
117       {
118         parser = new FormulaParser(getContents(), w, w,
119                                    w.getSettings());
120       }
121
122       // Get the bytes for the dummy formula
123
try
124       {
125         parser.parse();
126       }
127       catch(FormulaException e2)
128       {
129         logger.warn(e2.getMessage());
130         parser = new FormulaParser("\"ERROR\"", w, w, w.getSettings());
131         try {parser.parse();}
132         catch(FormulaException e3) {Assert.verify(false);}
133       }
134       byte[] formulaBytes = parser.getBytes();
135       expressiondata = new byte[formulaBytes.length + 16];
136       IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14);
137       System.arraycopy(formulaBytes, 0, expressiondata, 16,
138                        formulaBytes.length);
139     }
140
141     // Set the recalculate on load bit
142
expressiondata[8] |= 0x02;
143     
144     byte[] data = new byte[celldata.length +
145                            expressiondata.length];
146     System.arraycopy(celldata, 0, data, 0, celldata.length);
147     System.arraycopy(expressiondata, 0, data,
148                      celldata.length, expressiondata.length);
149     return data;
150   }
151
152   /**
153    * Returns the content type of this cell
154    *
155    * @return the content type for this cell
156    */

157   public CellType getType()
158   {
159     return formula.getType();
160   }
161
162   /**
163    * Quick and dirty function to return the contents of this cell as a string.
164    *
165    * @return the contents of this cell as a string
166    */

167   public String JavaDoc getContents()
168   {
169     return formula.getContents();
170   }
171
172   /**
173    * Gets the raw bytes for the formula. This will include the
174    * parsed tokens array. Used when copying spreadsheets
175    *
176    * @return the raw record data
177    */

178   public byte[] getFormulaData() throws FormulaException
179   {
180     byte[] d = formula.getFormulaData();
181     byte[] data = new byte[d.length];
182
183     System.arraycopy(d, 0, data, 0, d.length);
184       
185     // Set the recalculate on load bit
186
data[8] |= 0x02;
187     
188     return data;
189   }
190
191   /**
192    * Implementation of the deep copy function
193    *
194    * @param col the column which the new cell will occupy
195    * @param row the row which the new cell will occupy
196    * @return a copy of this cell, which can then be added to the sheet
197    */

198   public WritableCell copyTo(int col, int row)
199   {
200     return new FormulaRecord(col, row, this);
201   }
202
203   /**
204    * Overrides the method in the base class to add this to the Workbook's
205    * list of maintained formulas
206    *
207    * @param fr the formatting records
208    * @param ss the shared strings used within the workbook
209    * @param s the sheet this is being added to
210    */

211   void setCellDetails(FormattingRecords fr, SharedStrings ss,
212                       WritableSheetImpl s)
213   {
214     super.setCellDetails(fr, ss, s);
215     s.getWorkbook().addRCIRCell(this);
216   }
217
218   /**
219    * Called when a column is inserted on the specified sheet. Notifies all
220    * RCIR cells of this change. The default implementation here does nothing
221    *
222    * @param s the sheet on which the column was inserted
223    * @param sheetIndex the sheet index on which the column was inserted
224    * @param col the column number which was inserted
225    */

226   void columnInserted(Sheet s, int sheetIndex, int col)
227   {
228     try
229     {
230       if (parser == null)
231       {
232         byte[] formulaData = formula.getFormulaData();
233         byte[] formulaBytes = new byte[formulaData.length - 16];
234         System.arraycopy(formulaData, 16,
235                          formulaBytes, 0, formulaBytes.length);
236         parser = new FormulaParser(formulaBytes,
237                                    this,
238                                    getSheet().getWorkbook(),
239                                    getSheet().getWorkbook(),
240                                    getSheet().getWorkbookSettings());
241         parser.parse();
242       }
243
244       parser.columnInserted(sheetIndex, col, s == getSheet());
245     }
246     catch (FormulaException e)
247     {
248       logger.warn("cannot insert column within formula: " + e.getMessage());
249     }
250   }
251
252   /**
253    * Called when a column is removed on the specified sheet. Notifies all
254    * RCIR cells of this change. The default implementation here does nothing
255    *
256    * @param s the sheet on which the column was inserted
257    * @param sheetIndex the sheet index on which the column was inserted
258    * @param col the column number which was inserted
259    */

260   void columnRemoved(Sheet s, int sheetIndex, int col)
261   {
262     try
263     {
264       if (parser == null)
265       {
266         byte[] formulaData = formula.getFormulaData();
267         byte[] formulaBytes = new byte[formulaData.length - 16];
268         System.arraycopy(formulaData, 16,
269                          formulaBytes, 0, formulaBytes.length);
270         parser = new FormulaParser(formulaBytes,
271                                    this,
272                                    getSheet().getWorkbook(),
273                                    getSheet().getWorkbook(),
274                                    getSheet().getWorkbookSettings());
275         parser.parse();
276       }
277
278       parser.columnRemoved(sheetIndex, col, s == getSheet());
279     }
280     catch (FormulaException e)
281     {
282       logger.warn("cannot remove column within formula: " + e.getMessage());
283     }
284   }
285
286   /**
287    * Called when a row is inserted on the specified sheet. Notifies all
288    * RCIR cells of this change. The default implementation here does nothing
289    *
290    * @param s the sheet on which the column was inserted
291    * @param sheetIndex the sheet index on which the column was inserted
292    * @param row the column number which was inserted
293    */

294   void rowInserted(Sheet s, int sheetIndex, int row)
295   {
296     try
297     {
298       if (parser == null)
299       {
300         byte[] formulaData = formula.getFormulaData();
301         byte[] formulaBytes = new byte[formulaData.length - 16];
302         System.arraycopy(formulaData, 16,
303                          formulaBytes, 0, formulaBytes.length);
304         parser = new FormulaParser(formulaBytes,
305                                    this,
306                                    getSheet().getWorkbook(),
307                                    getSheet().getWorkbook(),
308                                    getSheet().getWorkbookSettings());
309         parser.parse();
310       }
311
312       parser.rowInserted(sheetIndex, row, s == getSheet());
313     }
314     catch (FormulaException e)
315     {
316       logger.warn("cannot insert row within formula: " + e.getMessage());
317     }
318   }
319
320   /**
321    * Called when a row is inserted on the specified sheet. Notifies all
322    * RCIR cells of this change. The default implementation here does nothing
323    *
324    * @param s the sheet on which the row was removed
325    * @param sheetIndex the sheet index on which the column was removed
326    * @param row the column number which was removed
327    */

328   void rowRemoved(Sheet s, int sheetIndex, int row)
329   {
330     try
331     {
332       if (parser == null)
333       {
334         byte[] formulaData = formula.getFormulaData();
335         byte[] formulaBytes = new byte[formulaData.length - 16];
336         System.arraycopy(formulaData, 16,
337                          formulaBytes, 0, formulaBytes.length);
338         parser = new FormulaParser(formulaBytes,
339                                    this,
340                                    getSheet().getWorkbook(),
341                                    getSheet().getWorkbook(),
342                                    getSheet().getWorkbookSettings());
343         parser.parse();
344       }
345
346       parser.rowRemoved(sheetIndex, row, s == getSheet());
347     }
348     catch (FormulaException e)
349     {
350       logger.warn("cannot remove row within formula: " + e.getMessage());
351     }
352   }
353
354   /**
355    * Accessor for the read formula
356    *
357    * @return the read formula
358    */

359   protected FormulaData getReadFormula()
360   {
361     return formula;
362   }
363
364   /**
365    * Accessor for the read formula
366    *
367    * @return the read formula
368    */

369   public String JavaDoc getFormula() throws FormulaException
370   {
371     return ( (FormulaCell) formula).getFormula();
372   }
373 }
374
Popular Tags