1    
2    /* ====================================================================
3     * The Apache Software License, Version 1.1
4     *
5     * Copyright (c) 2002 The Apache Software Foundation.  All rights
6     * reserved.
7     *
8     * Redistribution and use in source and binary forms, with or without
9     * modification, are permitted provided that the following conditions
10    * are met:
11    *
12    * 1. Redistributions of source code must retain the above copyright
13    *    notice, this list of conditions and the following disclaimer.
14    *
15    * 2. Redistributions in binary form must reproduce the above copyright
16    *    notice, this list of conditions and the following disclaimer in
17    *    the documentation and/or other materials provided with the
18    *    distribution.
19    *
20    * 3. The end-user documentation included with the redistribution,
21    *    if any, must include the following acknowledgment:
22    *       "This product includes software developed by the
23    *        Apache Software Foundation (http://www.apache.org/)."
24    *    Alternately, this acknowledgment may appear in the software itself,
25    *    if and wherever such third-party acknowledgments normally appear.
26    *
27    * 4. The names "Apache" and "Apache Software Foundation" and
28    *    "Apache POI" must not be used to endorse or promote products
29    *    derived from this software without prior written permission. For
30    *    written permission, please contact apache@apache.org.
31    *
32    * 5. Products derived from this software may not be called "Apache",
33    *    "Apache POI", nor may "Apache" appear in their name, without
34    *    prior written permission of the Apache Software Foundation.
35    *
36    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47    * SUCH DAMAGE.
48    * ====================================================================
49    *
50    * This software consists of voluntary contributions made by many
51    * individuals on behalf of the Apache Software Foundation.  For more
52    * information on the Apache Software Foundation, please see
53    * <http://www.apache.org/>.
54    */
55   
56   /*
57    * Cell.java
58    *
59    * Created on September 30, 2001, 3:46 PM
60    */
61   package org.apache.poi.hssf.usermodel;
62   
63   import org.apache.poi.hssf.model.Workbook;
64   import org.apache.poi.hssf.model.Sheet;
65   import org.apache.poi.hssf.model.FormulaParser;
66   import org.apache.poi.hssf.record.CellValueRecordInterface;
67   import org.apache.poi.hssf.record.Record;
68   import org.apache.poi.hssf.record.FormulaRecord;
69   import org.apache.poi.hssf.record.LabelSSTRecord;
70   import org.apache.poi.hssf.record.NumberRecord;
71   import org.apache.poi.hssf.record.BlankRecord;
72   import org.apache.poi.hssf.record.BoolErrRecord;
73   import org.apache.poi.hssf.record.ExtendedFormatRecord;
74   import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
75   import org.apache.poi.hssf.record.formula.Ptg;
76   import org.apache.poi.hssf.util.SheetReferences;
77   
78   //import org.apache.poi.hssf.record.formula.FormulaParser;
79   
80   import java.util.Date;
81   import java.util.Calendar;
82   
83   /**
84    * High level representation of a cell in a row of a spreadsheet.
85    * Cells can be numeric, formula-based or string-based (text).  The cell type
86    * specifies this.  String cells cannot conatin numbers and numeric cells cannot
87    * contain strings (at least according to our model).  Client apps should do the
88    * conversions themselves.  Formula cells are treated like string cells, simply
89    * containing a formula string.  They'll be rendered differently.
90    * <p>
91    * Cells should have their number (0 based) before being added to a row.  Only
92    * cells that have values should be added.
93    * <p>
94    * NOTE: the alpha won't be implementing formulas
95    *
96    * @author  Andrew C. Oliver (acoliver at apache dot org)
97    * @author  Dan Sherman (dsherman at isisph.com)
98    * @author  Brian Sanders (kestrel at burdell dot org) Active Cell support
99    * @version 1.0-pre
100   */
101  
102  public class HSSFCell
103  {
104  
105      /**
106       * Numeric Cell type (0)
107       * @see #setCellType(int)
108       * @see #getCellType()
109       */
110  
111      public final static int          CELL_TYPE_NUMERIC           = 0;
112  
113      /**
114       * String Cell type (1)
115       * @see #setCellType(int)
116       * @see #getCellType()
117       */
118  
119      public final static int          CELL_TYPE_STRING            = 1;
120  
121      /**
122       * Formula Cell type (2)
123       * @see #setCellType(int)
124       * @see #getCellType()
125       */
126  
127      public final static int          CELL_TYPE_FORMULA           = 2;
128  
129      /**
130       * Blank Cell type (3)
131       * @see #setCellType(int)
132       * @see #getCellType()
133       */
134  
135      public final static int          CELL_TYPE_BLANK             = 3;
136  
137      /**
138       * Boolean Cell type (4)
139       * @see #setCellType(int)
140       * @see #getCellType()
141       */
142  
143      public final static int          CELL_TYPE_BOOLEAN           = 4;
144  
145      /**
146       * Error Cell type (5)
147       * @see #setCellType(int)
148       * @see #getCellType()
149       */
150  
151      public final static int          CELL_TYPE_ERROR             = 5;
152      public final static short        ENCODING_COMPRESSED_UNICODE = 0;
153      public final static short        ENCODING_UTF_16             = 1;
154      private short                    cellNum;
155      private int                      cellType;
156      private HSSFCellStyle            cellStyle;
157      private double                   cellValue;
158      private String                   stringValue;
159      private boolean                  booleanValue;
160      private byte                     errorValue;
161      private short                    encoding = ENCODING_COMPRESSED_UNICODE;
162      private Workbook                 book;
163      private Sheet                    sheet;
164      //private short                    row;
165      private int                    row;
166      private CellValueRecordInterface record;
167  
168      /**
169       * Creates new Cell - Should only be called by HSSFRow.  This creates a cell
170       * from scratch.
171       * <p>
172       * When the cell is initially created it is set to CELL_TYPE_BLANK. Cell types
173       * can be changed/overwritten by calling setCellValue with the appropriate
174       * type as a parameter although conversions from one type to another may be
175       * prohibited.
176       *
177       * @param book - Workbook record of the workbook containing this cell
178       * @param sheet - Sheet record of the sheet containing this cell
179       * @param row   - the row of this cell
180       * @param col   - the column for this cell
181       *
182       * @see org.apache.poi.hssf.usermodel.HSSFRow#createCell(short)
183       */
184  
185      //protected HSSFCell(Workbook book, Sheet sheet, short row, short col)
186      protected HSSFCell(Workbook book, Sheet sheet, int row, short col)
187      {
188          checkBounds(col);
189          cellNum      = col;
190          this.row     = row;
191          cellStyle    = null;
192          cellValue    = 0;
193          stringValue  = null;
194          booleanValue = false;
195          errorValue   = ( byte ) 0;
196          this.book    = book;
197          this.sheet   = sheet;
198  
199          // Relying on the fact that by default the cellType is set to 0 which
200          // is different to CELL_TYPE_BLANK hence the following method call correctly
201          // creates a new blank cell.
202          setCellType(CELL_TYPE_BLANK, false);
203          ExtendedFormatRecord xf = book.getExFormatAt(0xf);
204  
205          setCellStyle(new HSSFCellStyle(( short ) 0xf, xf));
206      }
207  
208      /**
209       * Creates new Cell - Should only be called by HSSFRow.  This creates a cell
210       * from scratch.
211       *
212       * @param book - Workbook record of the workbook containing this cell
213       * @param sheet - Sheet record of the sheet containing this cell
214       * @param row   - the row of this cell
215       * @param col   - the column for this cell
216       * @param type  - CELL_TYPE_NUMERIC, CELL_TYPE_STRING, CELL_TYPE_FORMULA, CELL_TYPE_BLANK,
217       *                CELL_TYPE_BOOLEAN, CELL_TYPE_ERROR
218       *                Type of cell
219       * @see org.apache.poi.hssf.usermodel.HSSFRow#createCell(short,int)
220       * @deprecated As of 22-Jan-2002 use @see org.apache.poi.hssf.usermodel.HSSFRow#createCell(short)
221       * and use setCellValue to specify the type lazily.
222       */
223  
224      //protected HSSFCell(Workbook book, Sheet sheet, short row, short col,
225      protected HSSFCell(Workbook book, Sheet sheet, int row, short col,
226                         int type)
227      {
228          checkBounds(col);
229          cellNum      = col;
230          this.row     = row;
231          cellType     = type;
232          cellStyle    = null;
233          cellValue    = 0;
234          stringValue  = null;
235          booleanValue = false;
236          errorValue   = ( byte ) 0;
237          this.book    = book;
238          this.sheet   = sheet;
239          switch (type)
240          {
241  
242              case CELL_TYPE_NUMERIC :
243                  record = new NumberRecord();
244                  (( NumberRecord ) record).setColumn(col);
245                  (( NumberRecord ) record).setRow(row);
246                  (( NumberRecord ) record).setValue(( short ) 0);
247                  (( NumberRecord ) record).setXFIndex(( short ) 0);
248                  break;
249  
250              case CELL_TYPE_STRING :
251                  record = new LabelSSTRecord();
252                  (( LabelSSTRecord ) record).setColumn(col);
253                  (( LabelSSTRecord ) record).setRow(row);
254                  (( LabelSSTRecord ) record).setXFIndex(( short ) 0);
255                  break;
256  
257              case CELL_TYPE_BLANK :
258                  record = new BlankRecord();
259                  (( BlankRecord ) record).setColumn(col);
260                  (( BlankRecord ) record).setRow(row);
261                  (( BlankRecord ) record).setXFIndex(( short ) 0);
262                  break;
263  
264              case CELL_TYPE_FORMULA :
265                  FormulaRecord formulaRecord = new FormulaRecord();
266                  record = new FormulaRecordAggregate(formulaRecord,null);
267                  formulaRecord.setColumn(col);
268                  formulaRecord.setRow(row);
269                  formulaRecord.setXFIndex(( short ) 0);
270              case CELL_TYPE_BOOLEAN :
271                  record = new BoolErrRecord();
272                  (( BoolErrRecord ) record).setColumn(col);
273                  (( BoolErrRecord ) record).setRow(row);
274                  (( BoolErrRecord ) record).setXFIndex(( short ) 0);
275                  (( BoolErrRecord ) record).setValue(false);
276                  break;
277  
278              case CELL_TYPE_ERROR :
279                  record = new BoolErrRecord();
280                  (( BoolErrRecord ) record).setColumn(col);
281                  (( BoolErrRecord ) record).setRow(row);
282                  (( BoolErrRecord ) record).setXFIndex(( short ) 0);
283                  (( BoolErrRecord ) record).setValue(( byte ) 0);
284                  break;
285          }
286          ExtendedFormatRecord xf = book.getExFormatAt(0xf);
287  
288          setCellStyle(new HSSFCellStyle(( short ) 0xf, xf));
289      }
290  
291      /**
292       * Creates an HSSFCell from a CellValueRecordInterface.  HSSFSheet uses this when
293       * reading in cells from an existing sheet.
294       *
295       * @param book - Workbook record of the workbook containing this cell
296       * @param sheet - Sheet record of the sheet containing this cell
297       * @param cval - the Cell Value Record we wish to represent
298       */
299  
300      //protected HSSFCell(Workbook book, Sheet sheet, short row,
301      protected HSSFCell(Workbook book, Sheet sheet, int row,
302                         CellValueRecordInterface cval)
303      {
304          cellNum     = cval.getColumn();
305          record      = cval;
306          this.row    = row;
307          cellType    = determineType(cval);
308          cellStyle   = null;
309          stringValue = null;
310          this.book   = book;
311          this.sheet  = sheet;
312          switch (cellType)
313          {
314  
315              case CELL_TYPE_NUMERIC :
316                  cellValue = (( NumberRecord ) cval).getValue();
317                  break;
318  
319              case CELL_TYPE_STRING :
320                  stringValue =
321                      book.getSSTString( ( (LabelSSTRecord ) cval).getSSTIndex());
322                  break;
323  
324              case CELL_TYPE_BLANK :
325                  break;
326  
327              case CELL_TYPE_FORMULA :
328                  cellValue = (( FormulaRecordAggregate ) cval).getFormulaRecord().getValue();
329                  break;
330  
331              case CELL_TYPE_BOOLEAN :
332                  booleanValue = (( BoolErrRecord ) cval).getBooleanValue();
333                  break;
334  
335              case CELL_TYPE_ERROR :
336                  errorValue = (( BoolErrRecord ) cval).getErrorValue();
337                  break;
338          }
339          ExtendedFormatRecord xf = book.getExFormatAt(cval.getXFIndex());
340  
341          setCellStyle(new HSSFCellStyle(( short ) cval.getXFIndex(), xf));
342      }
343  
344      /**
345       * private constructor to prevent blank construction
346       */
347      private HSSFCell()
348      {
349      }
350  
351      /**
352       * used internally -- given a cell value record, figure out its type
353       */
354      private int determineType(CellValueRecordInterface cval)
355      {
356          Record record = ( Record ) cval;
357          int    sid    = record.getSid();
358          int    retval = 0;
359  
360          switch (sid)
361          {
362  
363              case NumberRecord.sid :
364                  retval = HSSFCell.CELL_TYPE_NUMERIC;
365                  break;
366  
367              case BlankRecord.sid :
368                  retval = HSSFCell.CELL_TYPE_BLANK;
369                  break;
370  
371              case LabelSSTRecord.sid :
372                  retval = HSSFCell.CELL_TYPE_STRING;
373                  break;
374  
375              case FormulaRecordAggregate.sid :
376                  retval = HSSFCell.CELL_TYPE_FORMULA;
377                  break;
378  
379              case BoolErrRecord.sid :
380                  BoolErrRecord boolErrRecord = ( BoolErrRecord ) record;
381  
382                  retval = (boolErrRecord.isBoolean())
383                           ? HSSFCell.CELL_TYPE_BOOLEAN
384                           : HSSFCell.CELL_TYPE_ERROR;
385                  break;
386          }
387          return retval;
388      }
389  
390      /**
391       * set the cell's number within the row (0 based)
392       * @param num  short the cell number
393       */
394  
395      public void setCellNum(short num)
396      {
397          cellNum = num;
398          record.setColumn(num);
399      }
400  
401      /**
402       *  get the cell's number within the row
403       * @return short reperesenting the column number (logical!)
404       */
405  
406      public short getCellNum()
407      {
408          return cellNum;
409      }
410  
411      /**
412       * set the cells type (numeric, formula or string) -- DONT USE FORMULAS IN THIS RELEASE
413       * WE'LL THROW YOU A RUNTIME EXCEPTION IF YOU DO
414       * @see #CELL_TYPE_NUMERIC
415       * @see #CELL_TYPE_STRING
416       * @see #CELL_TYPE_FORMULA
417       * @see #CELL_TYPE_BLANK
418       * @see #CELL_TYPE_BOOLEAN
419       * @see #CELL_TYPE_ERROR
420       */
421  
422      public void setCellType(int cellType)
423      {
424          setCellType(cellType, true);
425      }
426  
427      /**
428       * sets the cell type. The setValue flag indicates whether to bother about
429       *  trying to preserve the current value in the new record if one is created.
430       *  <p>
431       *  The @see #setCellValue method will call this method with false in setValue
432       *  since it will overwrite the cell value later
433       *
434       */
435  
436      private void setCellType(int cellType, boolean setValue)
437      {
438  
439          // if (cellType == CELL_TYPE_FORMULA)
440          // {
441          // throw new RuntimeException(
442          // "Formulas have not been implemented in this release");
443          // }
444          if (cellType > CELL_TYPE_ERROR)
445          {
446              throw new RuntimeException("I have no idea what type that is!");
447          }
448          switch (cellType)
449          {
450  
451              case CELL_TYPE_FORMULA :
452                  FormulaRecordAggregate frec = null;
453  
454                  if (cellType != this.cellType)
455                  {
456                      frec = new FormulaRecordAggregate(new FormulaRecord(),null);
457                  }
458                  else
459                  {
460                      frec = ( FormulaRecordAggregate ) record;
461                  }
462                  frec.setColumn(getCellNum());
463                  if (setValue)
464                  {
465                      frec.getFormulaRecord().setValue(getNumericCellValue());
466                  }
467                  frec.setXFIndex(( short ) cellStyle.getIndex());
468                  frec.setRow(row);
469                  record = frec;
470                  break;
471  
472              case CELL_TYPE_NUMERIC :
473                  NumberRecord nrec = null;
474  
475                  if (cellType != this.cellType)
476                  {
477                      nrec = new NumberRecord();
478                  }
479                  else
480                  {
481                      nrec = ( NumberRecord ) record;
482                  }
483                  nrec.setColumn(getCellNum());
484                  if (setValue)
485                  {
486                      nrec.setValue(getNumericCellValue());
487                  }
488                  nrec.setXFIndex(( short ) cellStyle.getIndex());
489                  nrec.setRow(row);
490                  record = nrec;
491                  break;
492  
493              case CELL_TYPE_STRING :
494                  LabelSSTRecord lrec = null;
495  
496                  if (cellType != this.cellType)
497                  {
498                      lrec = new LabelSSTRecord();
499                  }
500                  else
501                  {
502                      lrec = ( LabelSSTRecord ) record;
503                  }
504                  lrec.setColumn(getCellNum());
505                  lrec.setRow(row);
506                  lrec.setXFIndex(( short ) cellStyle.getIndex());
507                  if (setValue)
508                  {
509                      if ((getStringCellValue() != null)
510                              && (!getStringCellValue().equals("")))
511                      {
512                          int sst = 0;
513  
514                          if (encoding == ENCODING_COMPRESSED_UNICODE)
515                          {
516                              sst = book.addSSTString(getStringCellValue());
517                          }
518                          if (encoding == ENCODING_UTF_16)
519                          {
520                              sst = book.addSSTString(getStringCellValue(),
521                                                      true);
522                          }
523                          lrec.setSSTIndex(sst);
524                      }
525                  }
526                  record = lrec;
527                  break;
528  
529              case CELL_TYPE_BLANK :
530                  BlankRecord brec = null;
531  
532                  if (cellType != this.cellType)
533                  {
534                      brec = new BlankRecord();
535                  }
536                  else
537                  {
538                      brec = ( BlankRecord ) record;
539                  }
540                  brec.setColumn(getCellNum());
541  
542                  // During construction the cellStyle may be null for a Blank cell.
543                  if (cellStyle != null)
544                  {
545                      brec.setXFIndex(( short ) cellStyle.getIndex());
546                  }
547                  else
548                  {
549                      brec.setXFIndex(( short ) 0);
550                  }
551                  brec.setRow(row);
552                  record = brec;
553                  break;
554  
555              case CELL_TYPE_BOOLEAN :
556                  BoolErrRecord boolRec = null;
557  
558                  if (cellType != this.cellType)
559                  {
560                      boolRec = new BoolErrRecord();
561                  }
562                  else
563                  {
564                      boolRec = ( BoolErrRecord ) record;
565                  }
566                  boolRec.setColumn(getCellNum());
567                  if (setValue)
568                  {
569                      boolRec.setValue(getBooleanCellValue());
570                  }
571                  boolRec.setXFIndex(( short ) cellStyle.getIndex());
572                  boolRec.setRow(row);
573                  record = boolRec;
574                  break;
575  
576              case CELL_TYPE_ERROR :
577                  BoolErrRecord errRec = null;
578  
579                  if (cellType != this.cellType)
580                  {
581                      errRec = new BoolErrRecord();
582                  }
583                  else
584                  {
585                      errRec = ( BoolErrRecord ) record;
586                  }
587                  errRec.setColumn(getCellNum());
588                  if (setValue)
589                  {
590                      errRec.setValue(getErrorCellValue());
591                  }
592                  errRec.setXFIndex(( short ) cellStyle.getIndex());
593                  errRec.setRow(row);
594                  record = errRec;
595                  break;
596          }
597          if (cellType != this.cellType)
598          {
599              int loc = sheet.getLoc();
600  
601              sheet.replaceValueRecord(record);
602              sheet.setLoc(loc);
603          }
604          this.cellType = cellType;
605      }
606  
607      /**
608       * get the cells type (numeric, formula or string)
609       * @see #CELL_TYPE_STRING
610       * @see #CELL_TYPE_NUMERIC
611       * @see #CELL_TYPE_FORMULA
612       * @see #CELL_TYPE_BOOLEAN
613       * @see #CELL_TYPE_ERROR
614       */
615  
616      public int getCellType()
617      {
618          return cellType;
619      }
620  
621      /**
622       * set a numeric value for the cell
623       *
624       * @param value  the numeric value to set this cell to.  For formulas we'll set the
625       *        precalculated value, for numerics we'll set its value. For other types we
626       *        will change the cell to a numeric cell and set its value.
627       */
628      public void setCellValue(double value)
629      {
630          if ((cellType != CELL_TYPE_NUMERIC) && (cellType != CELL_TYPE_FORMULA))
631          {
632              setCellType(CELL_TYPE_NUMERIC, false);
633          }
634          (( NumberRecord ) record).setValue(value);
635          cellValue = value;
636      }
637  
638      /**
639       * set a date value for the cell. Excel treats dates as numeric so you will need to format the cell as
640       * a date.
641       *
642       * @param value  the date value to set this cell to.  For formulas we'll set the
643       *        precalculated value, for numerics we'll set its value. For other types we
644       *        will change the cell to a numeric cell and set its value.
645       */
646      public void setCellValue(Date value)
647      {
648          setCellValue(HSSFDateUtil.getExcelDate(value));
649      }
650  
651      /**
652       * set a date value for the cell. Excel treats dates as numeric so you will need to format the cell as
653       * a date.
654       *
655       * @param value  the date value to set this cell to.  For formulas we'll set the
656       *        precalculated value, for numerics we'll set its value. For othertypes we
657       *        will change the cell to a numeric cell and set its value.
658       */
659      public void setCellValue(Calendar value)
660      {
661          setCellValue(value.getTime());
662      }
663  
664      /**
665       * set a string value for the cell. Please note that if you are using
666       * full 16 bit unicode you should call <code>setEncoding()</code> first.
667       *
668       * @param value  value to set the cell to.  For formulas we'll set the formula
669       * string, for String cells we'll set its value.  For other types we will
670       * change the cell to a string cell and set its value.
671       * If value is null then we will change the cell to a Blank cell.
672       */
673  
674      public void setCellValue(String value)
675      {
676          if (value == null)
677          {
678              setCellType(CELL_TYPE_BLANK, false);
679          }
680          else
681          {
682              if ((cellType != CELL_TYPE_STRING ) && ( cellType != CELL_TYPE_FORMULA))
683              {
684                  setCellType(CELL_TYPE_STRING, false);
685              }
686              int index = 0;
687  
688              if (encoding == ENCODING_COMPRESSED_UNICODE)
689              {
690                  index = book.addSSTString(value);
691              }
692              if (encoding == ENCODING_UTF_16)
693              {
694                  index = book.addSSTString(value, true);
695              }
696              (( LabelSSTRecord ) record).setSSTIndex(index);
697              stringValue = value;
698          }
699      }
700  
701      public void setCellFormula(String formula) {
702          //Workbook.currentBook=book;
703          if (formula==null) {
704              setCellType(CELL_TYPE_BLANK,false);
705          } else {
706              setCellType(CELL_TYPE_FORMULA,false);
707              FormulaRecordAggregate rec = (FormulaRecordAggregate) record;
708              rec.getFormulaRecord().setOptions(( short ) 2);
709              rec.getFormulaRecord().setValue(0);
710              
711              //only set to default if there is no extended format index already set
712              if (rec.getXFIndex() == (short)0) rec.setXFIndex(( short ) 0x0f);
713              FormulaParser fp = new FormulaParser(formula+";",book);
714              fp.parse();
715              Ptg[] ptg  = fp.getRPNPtg();
716              int   size = 0;
717              //System.out.println("got Ptgs " + ptg.length);
718              for (int k = 0; k < ptg.length; k++) {
719                  size += ptg[ k ].getSize();
720                  rec.getFormulaRecord().pushExpressionToken(ptg[ k ]);
721              }
722              rec.getFormulaRecord().setExpressionLength(( short ) size);
723              //Workbook.currentBook = null;
724          }
725      }
726  
727      public String getCellFormula() {
728          //Workbook.currentBook=book;
729          SheetReferences refs = book.getSheetReferences();
730          String retval = FormulaParser.toFormulaString(refs, ((FormulaRecordAggregate)record).getFormulaRecord().getParsedExpression());
731          //Workbook.currentBook=null;
732          return retval;
733      }
734  
735  
736      /**
737       * get the value of the cell as a number.  For strings we throw an exception.
738       * For blank cells we return a 0.
739       */
740  
741      public double getNumericCellValue()
742      {
743          if (cellType == CELL_TYPE_BLANK)
744          {
745              return 0;
746          }
747          if (cellType == CELL_TYPE_STRING)
748          {
749              throw new NumberFormatException(
750                  "You cannot get a numeric value from a String based cell");
751          }
752          if (cellType == CELL_TYPE_BOOLEAN)
753          {
754              throw new NumberFormatException(
755                  "You cannot get a numeric value from a boolean cell");
756          }
757          if (cellType == CELL_TYPE_ERROR)
758          {
759              throw new NumberFormatException(
760                  "You cannot get a numeric value from an error cell");
761          }
762          return cellValue;
763      }
764  
765      /**
766       * get the value of the cell as a date.  For strings we throw an exception.
767       * For blank cells we return a null.
768       */
769      public Date getDateCellValue()
770      {
771          if (cellType == CELL_TYPE_BLANK)
772          {
773              return null;
774          }
775          if (cellType == CELL_TYPE_STRING)
776          {
777              throw new NumberFormatException(
778                  "You cannot get a date value from a String based cell");
779          }
780          if (cellType == CELL_TYPE_BOOLEAN)
781          {
782              throw new NumberFormatException(
783                  "You cannot get a date value from a boolean cell");
784          }
785          if (cellType == CELL_TYPE_ERROR)
786          {
787              throw new NumberFormatException(
788                  "You cannot get a date value from an error cell");
789          }
790          if (book.isUsing1904DateWindowing()) {
791              return HSSFDateUtil.getJavaDate(cellValue,true);
792          }
793          else {
794              return HSSFDateUtil.getJavaDate(cellValue,false);
795          }
796      }
797  
798      /**
799       * get the value of the cell as a string - for numeric cells we throw an exception.
800       * For blank cells we return an empty string.
801       */
802  
803      public String getStringCellValue()
804      {
805          if (cellType == CELL_TYPE_BLANK)
806          {
807              return "";
808          }
809          if (cellType == CELL_TYPE_NUMERIC)
810          {
811              throw new NumberFormatException(
812                  "You cannot get a string value from a numeric cell");
813          }
814          if (cellType == CELL_TYPE_BOOLEAN)
815          {
816              throw new NumberFormatException(
817                  "You cannot get a string value from a boolean cell");
818          }
819          if (cellType == CELL_TYPE_ERROR)
820          {
821              throw new NumberFormatException(
822                  "You cannot get a string value from an error cell");
823          }
824          return stringValue;
825      }
826  
827      /**
828       * set a boolean value for the cell
829       *
830       * @param value the boolean value to set this cell to.  For formulas we'll set the
831       *        precalculated value, for booleans we'll set its value. For other types we
832       *        will change the cell to a boolean cell and set its value.
833       */
834  
835      public void setCellValue(boolean value)
836      {
837          if ((cellType != CELL_TYPE_BOOLEAN ) && ( cellType != CELL_TYPE_FORMULA))
838          {
839              setCellType(CELL_TYPE_BOOLEAN, false);
840          }
841          (( BoolErrRecord ) record).setValue(value);
842          booleanValue = value;
843      }
844  
845      /**
846       * set a error value for the cell
847       *
848       * @param value the error value to set this cell to.  For formulas we'll set the
849       *        precalculated value ??? IS THIS RIGHT??? , for errors we'll set
850       *        its value. For other types we will change the cell to an error
851       *        cell and set its value.
852       */
853  
854      public void setCellErrorValue(byte value)
855      {
856          if ((cellType != CELL_TYPE_ERROR) && (cellType != CELL_TYPE_FORMULA))
857          {
858              setCellType(CELL_TYPE_ERROR, false);
859          }
860          (( BoolErrRecord ) record).setValue(value);
861          errorValue = value;
862      }
863  
864      /**
865       * get the value of the cell as a boolean.  For strings, numbers, and errors, we throw an exception.
866       * For blank cells we return a false.
867       */
868  
869      public boolean getBooleanCellValue()
870      {
871          if (cellType == CELL_TYPE_BOOLEAN)
872          {
873              return booleanValue;
874          }
875          if (cellType == CELL_TYPE_BLANK)
876          {
877              return false;
878          }
879          throw new NumberFormatException(
880              "You cannot get a boolean value from a non-boolean cell");
881      }
882  
883      /**
884       * get the value of the cell as an error code.  For strings, numbers, and booleans, we throw an exception.
885       * For blank cells we return a 0.
886       */
887  
888      public byte getErrorCellValue()
889      {
890          if (cellType == CELL_TYPE_ERROR)
891          {
892              return errorValue;
893          }
894          if (cellType == CELL_TYPE_BLANK)
895          {
896              return ( byte ) 0;
897          }
898          throw new NumberFormatException(
899              "You cannot get an error value from a non-error cell");
900      }
901  
902      /**
903       * set the style for the cell.  The style should be an HSSFCellStyle created/retreived from
904       * the HSSFWorkbook.
905       *
906       * @param style  reference contained in the workbook
907       * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createCellStyle()
908       * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(short)
909       */
910  
911      public void setCellStyle(HSSFCellStyle style)
912      {
913          cellStyle = style;
914          record.setXFIndex(style.getIndex());
915      }
916  
917      /**
918       * get the style for the cell.  This is a reference to a cell style contained in the workbook
919       * object.
920       * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(short)
921       */
922  
923      public HSSFCellStyle getCellStyle()
924      {
925          return cellStyle;
926      }
927  
928      /**
929       * used for internationalization, currently 0 for compressed unicode or 1 for 16-bit
930       *
931       * @see #ENCODING_COMPRESSED_UNICODE
932       * @see #ENCODING_UTF_16
933       *
934       * @return 1 or 0 for compressed or uncompressed (used only with String type)
935       */
936  
937      public short getEncoding()
938      {
939          return encoding;
940      }
941  
942      /**
943       * set the encoding to either 8 or 16 bit. (US/UK use 8-bit, rest of the western world use 16bit)
944       *
945       * @see #ENCODING_COMPRESSED_UNICODE
946       * @see #ENCODING_UTF_16
947       *
948       * @param encoding either ENCODING_COMPRESSED_UNICODE (0) or ENCODING_UTF_16 (1)
949       */
950  
951      public void setEncoding(short encoding)
952      {
953          this.encoding = encoding;
954      }
955  
956      /**
957       * Should only be used by HSSFSheet and friends.  Returns the low level CellValueRecordInterface record
958       *
959       * @return CellValueRecordInterface representing the cell via the low level api.
960       */
961  
962      protected CellValueRecordInterface getCellValueRecord()
963      {
964          return record;
965      }
966  
967      /**
968       * @throws RuntimeException if the bounds are exceeded.
969       */
970      private void checkBounds(int cellNum) {
971        if (cellNum > 255) {
972            throw new RuntimeException("You cannot have more than 255 columns "+
973                      "in a given row (IV).  Because Excel can't handle it");
974        }
975        else if (cellNum < 0) {
976            throw new RuntimeException("You cannot reference columns with an index of less then 0.");
977        }
978      }
979      
980      /**
981       * Sets this cell as the active cell for the worksheet
982       */
983      public void setAsActiveCell()
984      {
985          this.sheet.setActiveCellRow(this.row);
986          this.sheet.setActiveCellCol(this.cellNum);
987      }
988  }
989