Tweak how you get dataformat strings out of cell styles, to be more logical, and...
[poi.git] / src / java / org / apache / poi / hssf / usermodel / HSSFCell.java
blob670b33372d88db2d51e175e7b434663fb99121d0
1 /* ====================================================================
2 Licensed to the Apache Software Foundation (ASF) under one or more
3 contributor license agreements. See the NOTICE file distributed with
4 this work for additional information regarding copyright ownership.
5 The ASF licenses this file to You under the Apache License, Version 2.0
6 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
9 http://www.apache.org/licenses/LICENSE-2.0
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 ==================================================================== */
21 * Cell.java
23 * Created on September 30, 2001, 3:46 PM
25 package org.apache.poi.hssf.usermodel;
27 import java.text.DateFormat;
28 import java.text.SimpleDateFormat;
29 import java.util.Calendar;
30 import java.util.Date;
31 import java.util.HashMap;
32 import java.util.Iterator;
34 import org.apache.poi.hssf.model.FormulaParser;
35 import org.apache.poi.hssf.model.Sheet;
36 import org.apache.poi.hssf.model.Workbook;
37 import org.apache.poi.hssf.record.*;
38 import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
39 import org.apache.poi.hssf.record.formula.Ptg;
41 /**
42 * High level representation of a cell in a row of a spreadsheet.
43 * Cells can be numeric, formula-based or string-based (text). The cell type
44 * specifies this. String cells cannot conatin numbers and numeric cells cannot
45 * contain strings (at least according to our model). Client apps should do the
46 * conversions themselves. Formula cells have the formula string, as well as
47 * the formula result, which can be numeric or string.
48 * <p>
49 * Cells should have their number (0 based) before being added to a row. Only
50 * cells that have values should be added.
51 * <p>
53 * @author Andrew C. Oliver (acoliver at apache dot org)
54 * @author Dan Sherman (dsherman at isisph.com)
55 * @author Brian Sanders (kestrel at burdell dot org) Active Cell support
56 * @author Yegor Kozlov cell comments support
57 * @version 1.0-pre
60 public class HSSFCell
63 /**
64 * Numeric Cell type (0)
65 * @see #setCellType(int)
66 * @see #getCellType()
69 public final static int CELL_TYPE_NUMERIC = 0;
71 /**
72 * String Cell type (1)
73 * @see #setCellType(int)
74 * @see #getCellType()
77 public final static int CELL_TYPE_STRING = 1;
79 /**
80 * Formula Cell type (2)
81 * @see #setCellType(int)
82 * @see #getCellType()
85 public final static int CELL_TYPE_FORMULA = 2;
87 /**
88 * Blank Cell type (3)
89 * @see #setCellType(int)
90 * @see #getCellType()
93 public final static int CELL_TYPE_BLANK = 3;
95 /**
96 * Boolean Cell type (4)
97 * @see #setCellType(int)
98 * @see #getCellType()
101 public final static int CELL_TYPE_BOOLEAN = 4;
104 * Error Cell type (5)
105 * @see #setCellType(int)
106 * @see #getCellType()
109 public final static int CELL_TYPE_ERROR = 5;
110 public final static short ENCODING_UNCHANGED = -1;
111 public final static short ENCODING_COMPRESSED_UNICODE = 0;
112 public final static short ENCODING_UTF_16 = 1;
113 private int cellType;
114 private HSSFRichTextString stringValue;
115 private short encoding = ENCODING_UNCHANGED;
116 private Workbook book;
117 private Sheet sheet;
118 private CellValueRecordInterface record;
119 private HSSFComment comment;
122 * Creates new Cell - Should only be called by HSSFRow. This creates a cell
123 * from scratch.
124 * <p>
125 * When the cell is initially created it is set to CELL_TYPE_BLANK. Cell types
126 * can be changed/overwritten by calling setCellValue with the appropriate
127 * type as a parameter although conversions from one type to another may be
128 * prohibited.
130 * @param book - Workbook record of the workbook containing this cell
131 * @param sheet - Sheet record of the sheet containing this cell
132 * @param row - the row of this cell
133 * @param col - the column for this cell
135 * @see org.apache.poi.hssf.usermodel.HSSFRow#createCell(short)
138 //protected HSSFCell(Workbook book, Sheet sheet, short row, short col)
139 protected HSSFCell(Workbook book, Sheet sheet, int row, short col)
141 checkBounds(col);
142 stringValue = null;
143 this.book = book;
144 this.sheet = sheet;
146 // Relying on the fact that by default the cellType is set to 0 which
147 // is different to CELL_TYPE_BLANK hence the following method call correctly
148 // creates a new blank cell.
149 short xfindex = sheet.getXFIndexForColAt(col);
150 setCellType(CELL_TYPE_BLANK, false, row, col,xfindex);
154 * Creates new Cell - Should only be called by HSSFRow. This creates a cell
155 * from scratch.
157 * @param book - Workbook record of the workbook containing this cell
158 * @param sheet - Sheet record of the sheet containing this cell
159 * @param row - the row of this cell
160 * @param col - the column for this cell
161 * @param type - CELL_TYPE_NUMERIC, CELL_TYPE_STRING, CELL_TYPE_FORMULA, CELL_TYPE_BLANK,
162 * CELL_TYPE_BOOLEAN, CELL_TYPE_ERROR
163 * Type of cell
164 * @see org.apache.poi.hssf.usermodel.HSSFRow#createCell(short,int)
167 //protected HSSFCell(Workbook book, Sheet sheet, short row, short col,
168 protected HSSFCell(Workbook book, Sheet sheet, int row, short col,
169 int type)
171 checkBounds(col);
172 cellType = -1; // Force 'setCellType' to create a first Record
173 stringValue = null;
174 this.book = book;
175 this.sheet = sheet;
177 short xfindex = sheet.getXFIndexForColAt(col);
178 setCellType(type,false,row,col,xfindex);
182 * Creates an HSSFCell from a CellValueRecordInterface. HSSFSheet uses this when
183 * reading in cells from an existing sheet.
185 * @param book - Workbook record of the workbook containing this cell
186 * @param sheet - Sheet record of the sheet containing this cell
187 * @param cval - the Cell Value Record we wish to represent
190 //protected HSSFCell(Workbook book, Sheet sheet, short row,
191 protected HSSFCell(Workbook book, Sheet sheet, int row,
192 CellValueRecordInterface cval)
194 record = cval;
195 cellType = determineType(cval);
196 stringValue = null;
197 this.book = book;
198 this.sheet = sheet;
199 switch (cellType)
201 case CELL_TYPE_STRING :
202 stringValue = new HSSFRichTextString(book, (LabelSSTRecord ) cval);
203 break;
205 case CELL_TYPE_BLANK :
206 break;
208 case CELL_TYPE_FORMULA :
209 stringValue=new HSSFRichTextString(((FormulaRecordAggregate) cval).getStringValue());
210 break;
212 ExtendedFormatRecord xf = book.getExFormatAt(cval.getXFIndex());
214 setCellStyle(new HSSFCellStyle(( short ) cval.getXFIndex(), xf, book));
218 * private constructor to prevent blank construction
220 private HSSFCell()
225 * used internally -- given a cell value record, figure out its type
227 private int determineType(CellValueRecordInterface cval)
229 Record record = ( Record ) cval;
230 int sid = record.getSid();
231 int retval = 0;
233 switch (sid)
236 case NumberRecord.sid :
237 retval = HSSFCell.CELL_TYPE_NUMERIC;
238 break;
240 case BlankRecord.sid :
241 retval = HSSFCell.CELL_TYPE_BLANK;
242 break;
244 case LabelSSTRecord.sid :
245 retval = HSSFCell.CELL_TYPE_STRING;
246 break;
248 case FormulaRecordAggregate.sid :
249 retval = HSSFCell.CELL_TYPE_FORMULA;
250 break;
252 case BoolErrRecord.sid :
253 BoolErrRecord boolErrRecord = ( BoolErrRecord ) record;
255 retval = (boolErrRecord.isBoolean())
256 ? HSSFCell.CELL_TYPE_BOOLEAN
257 : HSSFCell.CELL_TYPE_ERROR;
258 break;
260 return retval;
264 * Returns the Workbook that this Cell is bound to
265 * @return
267 protected Workbook getBoundWorkbook() {
268 return book;
272 * Set the cell's number within the row (0 based).
273 * @param num short the cell number
274 * @deprecated Doesn't update the row's idea of what cell this is, use {@link HSSFRow#moveCell(HSSFCell, short)} instead
276 public void setCellNum(short num)
278 record.setColumn(num);
282 * Updates the cell record's idea of what
283 * column it belongs in (0 based)
284 * @param num the new cell number
286 protected void updateCellNum(short num)
288 record.setColumn(num);
292 * get the cell's number within the row
293 * @return short reperesenting the column number (logical!)
296 public short getCellNum()
298 return record.getColumn();
302 * set the cells type (numeric, formula or string)
303 * @see #CELL_TYPE_NUMERIC
304 * @see #CELL_TYPE_STRING
305 * @see #CELL_TYPE_FORMULA
306 * @see #CELL_TYPE_BLANK
307 * @see #CELL_TYPE_BOOLEAN
308 * @see #CELL_TYPE_ERROR
311 public void setCellType(int cellType)
313 int row=record.getRow();
314 short col=record.getColumn();
315 short styleIndex=record.getXFIndex();
316 setCellType(cellType, true, row, col, styleIndex);
320 * sets the cell type. The setValue flag indicates whether to bother about
321 * trying to preserve the current value in the new record if one is created.
322 * <p>
323 * The @see #setCellValue method will call this method with false in setValue
324 * since it will overwrite the cell value later
328 private void setCellType(int cellType, boolean setValue, int row,short col, short styleIndex)
331 // if (cellType == CELL_TYPE_FORMULA)
332 // {
333 // throw new RuntimeException(
334 // "Formulas have not been implemented in this release");
335 // }
336 if (cellType > CELL_TYPE_ERROR)
338 throw new RuntimeException("I have no idea what type that is!");
340 switch (cellType)
343 case CELL_TYPE_FORMULA :
344 FormulaRecordAggregate frec = null;
346 if (cellType != this.cellType)
348 frec = new FormulaRecordAggregate(new FormulaRecord(),null);
350 else
352 frec = ( FormulaRecordAggregate ) record;
354 frec.setColumn(col);
355 if (setValue)
357 frec.getFormulaRecord().setValue(getNumericCellValue());
359 frec.setXFIndex(styleIndex);
360 frec.setRow(row);
361 record = frec;
362 break;
364 case CELL_TYPE_NUMERIC :
365 NumberRecord nrec = null;
367 if (cellType != this.cellType)
369 nrec = new NumberRecord();
371 else
373 nrec = ( NumberRecord ) record;
375 nrec.setColumn(col);
376 if (setValue)
378 nrec.setValue(getNumericCellValue());
380 nrec.setXFIndex(styleIndex);
381 nrec.setRow(row);
382 record = nrec;
383 break;
385 case CELL_TYPE_STRING :
386 LabelSSTRecord lrec = null;
388 if (cellType != this.cellType)
390 lrec = new LabelSSTRecord();
392 else
394 lrec = ( LabelSSTRecord ) record;
396 lrec.setColumn(col);
397 lrec.setRow(row);
398 lrec.setXFIndex(styleIndex);
399 if (setValue)
401 if ((getStringCellValue() != null)
402 && (!getStringCellValue().equals("")))
404 int sst = 0;
406 UnicodeString str = getRichStringCellValue().getUnicodeString();
407 //jmh if (encoding == ENCODING_COMPRESSED_UNICODE)
408 //jmh {
409 // jmh str.setCompressedUnicode();
410 // jmh } else if (encoding == ENCODING_UTF_16)
411 // jmh {
412 // jmh str.setUncompressedUnicode();
413 // jmh }
414 sst = book.addSSTString(str);
415 lrec.setSSTIndex(sst);
416 getRichStringCellValue().setUnicodeString(book.getSSTString(sst));
419 record = lrec;
420 break;
422 case CELL_TYPE_BLANK :
423 BlankRecord brec = null;
425 if (cellType != this.cellType)
427 brec = new BlankRecord();
429 else
431 brec = ( BlankRecord ) record;
433 brec.setColumn(col);
435 // During construction the cellStyle may be null for a Blank cell.
436 brec.setXFIndex(styleIndex);
437 brec.setRow(row);
438 record = brec;
439 break;
441 case CELL_TYPE_BOOLEAN :
442 BoolErrRecord boolRec = null;
444 if (cellType != this.cellType)
446 boolRec = new BoolErrRecord();
448 else
450 boolRec = ( BoolErrRecord ) record;
452 boolRec.setColumn(col);
453 if (setValue)
455 boolRec.setValue(convertCellValueToBoolean());
457 boolRec.setXFIndex(styleIndex);
458 boolRec.setRow(row);
459 record = boolRec;
460 break;
462 case CELL_TYPE_ERROR :
463 BoolErrRecord errRec = null;
465 if (cellType != this.cellType)
467 errRec = new BoolErrRecord();
469 else
471 errRec = ( BoolErrRecord ) record;
473 errRec.setColumn(col);
474 if (setValue)
476 errRec.setValue(getErrorCellValue());
478 errRec.setXFIndex(styleIndex);
479 errRec.setRow(row);
480 record = errRec;
481 break;
483 if (cellType != this.cellType &&
484 this.cellType!=-1 ) // Special Value to indicate an uninitialized Cell
486 int loc = sheet.getLoc();
488 sheet.replaceValueRecord(record);
489 sheet.setLoc(loc);
491 this.cellType = cellType;
495 * get the cells type (numeric, formula or string)
496 * @see #CELL_TYPE_STRING
497 * @see #CELL_TYPE_NUMERIC
498 * @see #CELL_TYPE_FORMULA
499 * @see #CELL_TYPE_BOOLEAN
500 * @see #CELL_TYPE_ERROR
503 public int getCellType()
505 return cellType;
509 * set a numeric value for the cell
511 * @param value the numeric value to set this cell to. For formulas we'll set the
512 * precalculated value, for numerics we'll set its value. For other types we
513 * will change the cell to a numeric cell and set its value.
515 public void setCellValue(double value)
517 int row=record.getRow();
518 short col=record.getColumn();
519 short styleIndex=record.getXFIndex();
520 if ((cellType != CELL_TYPE_NUMERIC) && (cellType != CELL_TYPE_FORMULA))
522 setCellType(CELL_TYPE_NUMERIC, false, row, col, styleIndex);
525 // Save into the apropriate record
526 if(record instanceof FormulaRecordAggregate) {
527 (( FormulaRecordAggregate ) record).getFormulaRecord().setValue(value);
528 } else {
529 (( NumberRecord ) record).setValue(value);
534 * set a date value for the cell. Excel treats dates as numeric so you will need to format the cell as
535 * a date.
537 * @param value the date value to set this cell to. For formulas we'll set the
538 * precalculated value, for numerics we'll set its value. For other types we
539 * will change the cell to a numeric cell and set its value.
541 public void setCellValue(Date value)
543 setCellValue(HSSFDateUtil.getExcelDate(value, this.book.isUsing1904DateWindowing()));
547 * set a date value for the cell. Excel treats dates as numeric so you will need to format the cell as
548 * a date.
550 * This will set the cell value based on the Calendar's timezone. As Excel
551 * does not support timezones this means that both 20:00+03:00 and
552 * 20:00-03:00 will be reported as the same value (20:00) even that there
553 * are 6 hours difference between the two times. This difference can be
554 * preserved by using <code>setCellValue(value.getTime())</code> which will
555 * automatically shift the times to the default timezone.
557 * @param value the date value to set this cell to. For formulas we'll set the
558 * precalculated value, for numerics we'll set its value. For othertypes we
559 * will change the cell to a numeric cell and set its value.
561 public void setCellValue(Calendar value)
563 setCellValue( HSSFDateUtil.getExcelDate(value, this.book.isUsing1904DateWindowing()) );
567 * set a string value for the cell. Please note that if you are using
568 * full 16 bit unicode you should call <code>setEncoding()</code> first.
570 * @param value value to set the cell to. For formulas we'll set the formula
571 * string, for String cells we'll set its value. For other types we will
572 * change the cell to a string cell and set its value.
573 * If value is null then we will change the cell to a Blank cell.
574 * @deprecated Use setCellValue(HSSFRichTextString) instead.
577 public void setCellValue(String value)
579 HSSFRichTextString str = new HSSFRichTextString(value);
580 setCellValue(str);
584 * set a string value for the cell. Please note that if you are using
585 * full 16 bit unicode you should call <code>setEncoding()</code> first.
587 * @param value value to set the cell to. For formulas we'll set the formula
588 * string, for String cells we'll set its value. For other types we will
589 * change the cell to a string cell and set its value.
590 * If value is null then we will change the cell to a Blank cell.
592 public void setCellValue(HSSFRichTextString value) {
593 int row=record.getRow();
594 short col=record.getColumn();
595 short styleIndex=record.getXFIndex();
596 if (value == null) {
597 setCellType(CELL_TYPE_BLANK, false, row, col, styleIndex);
598 return;
600 if (cellType == CELL_TYPE_FORMULA) {
601 // Set the 'pre-evaluated result' for the formula
602 // note - formulas do not preserve text formatting.
603 FormulaRecordAggregate fr = (FormulaRecordAggregate) record;
604 // must make new sr because fr.getStringRecord() may be null
605 StringRecord sr = new StringRecord();
606 sr.setString(value.getString()); // looses format
607 fr.setStringRecord(sr);
608 return;
611 if (cellType != CELL_TYPE_STRING) {
612 setCellType(CELL_TYPE_STRING, false, row, col, styleIndex);
614 int index = 0;
616 UnicodeString str = value.getUnicodeString();
617 index = book.addSSTString(str);
618 (( LabelSSTRecord ) record).setSSTIndex(index);
619 stringValue = value;
620 stringValue.setWorkbookReferences(book, (( LabelSSTRecord ) record));
621 stringValue.setUnicodeString(book.getSSTString(index));
624 public void setCellFormula(String formula) {
625 int row=record.getRow();
626 short col=record.getColumn();
627 short styleIndex=record.getXFIndex();
628 //Workbook.currentBook=book;
629 if (formula==null) {
630 setCellType(CELL_TYPE_BLANK,false,row,col,styleIndex);
631 } else {
632 setCellType(CELL_TYPE_FORMULA,false,row,col,styleIndex);
633 FormulaRecordAggregate rec = (FormulaRecordAggregate) record;
634 FormulaRecord frec = rec.getFormulaRecord();
635 frec.setOptions(( short ) 2);
636 frec.setValue(0);
638 //only set to default if there is no extended format index already set
639 if (rec.getXFIndex() == (short)0) rec.setXFIndex(( short ) 0x0f);
640 FormulaParser fp = new FormulaParser(formula, book);
641 fp.parse();
642 Ptg[] ptg = fp.getRPNPtg();
643 int size = 0;
645 // clear the Ptg Stack
646 for (int i=0, iSize=frec.getNumberOfExpressionTokens(); i<iSize; i++) {
647 frec.popExpressionToken();
650 // fill the Ptg Stack with Ptgs of new formula
651 for (int k = 0; k < ptg.length; k++) {
652 size += ptg[ k ].getSize();
653 frec.pushExpressionToken(ptg[ k ]);
655 rec.getFormulaRecord().setExpressionLength(( short ) size);
656 //Workbook.currentBook = null;
660 public String getCellFormula() {
661 //Workbook.currentBook=book;
662 String retval = FormulaParser.toFormulaString(book, ((FormulaRecordAggregate)record).getFormulaRecord().getParsedExpression());
663 //Workbook.currentBook=null;
664 return retval;
669 * get the value of the cell as a number. For strings we throw an exception.
670 * For blank cells we return a 0.
673 public double getNumericCellValue()
675 if (cellType == CELL_TYPE_BLANK)
677 return 0;
679 if (cellType == CELL_TYPE_STRING)
681 throw new NumberFormatException(
682 "You cannot get a numeric value from a String based cell");
684 if (cellType == CELL_TYPE_BOOLEAN)
686 throw new NumberFormatException(
687 "You cannot get a numeric value from a boolean cell");
689 if (cellType == CELL_TYPE_ERROR)
691 throw new NumberFormatException(
692 "You cannot get a numeric value from an error cell");
694 if(cellType == CELL_TYPE_NUMERIC)
696 return ((NumberRecord)record).getValue();
698 if(cellType == CELL_TYPE_FORMULA)
700 return ((FormulaRecordAggregate)record).getFormulaRecord().getValue();
702 throw new NumberFormatException("Unknown Record Type in Cell:"+cellType);
706 * get the value of the cell as a date. For strings we throw an exception.
707 * For blank cells we return a null.
709 public Date getDateCellValue()
711 if (cellType == CELL_TYPE_BLANK)
713 return null;
715 if (cellType == CELL_TYPE_STRING)
717 throw new NumberFormatException(
718 "You cannot get a date value from a String based cell");
720 if (cellType == CELL_TYPE_BOOLEAN)
722 throw new NumberFormatException(
723 "You cannot get a date value from a boolean cell");
725 if (cellType == CELL_TYPE_ERROR)
727 throw new NumberFormatException(
728 "You cannot get a date value from an error cell");
730 double value=this.getNumericCellValue();
731 if (book.isUsing1904DateWindowing()) {
732 return HSSFDateUtil.getJavaDate(value,true);
734 else {
735 return HSSFDateUtil.getJavaDate(value,false);
740 * get the value of the cell as a string - for numeric cells we throw an exception.
741 * For blank cells we return an empty string.
742 * For formulaCells that are not string Formulas, we return empty String
743 * @deprecated Use the HSSFRichTextString return
746 public String getStringCellValue()
748 HSSFRichTextString str = getRichStringCellValue();
749 return str.getString();
753 * get the value of the cell as a string - for numeric cells we throw an exception.
754 * For blank cells we return an empty string.
755 * For formulaCells that are not string Formulas, we return empty String
758 public HSSFRichTextString getRichStringCellValue()
760 if (cellType == CELL_TYPE_BLANK)
762 return new HSSFRichTextString("");
764 if (cellType == CELL_TYPE_NUMERIC)
766 throw new NumberFormatException(
767 "You cannot get a string value from a numeric cell");
769 if (cellType == CELL_TYPE_BOOLEAN)
771 throw new NumberFormatException(
772 "You cannot get a string value from a boolean cell");
774 if (cellType == CELL_TYPE_ERROR)
776 throw new NumberFormatException(
777 "You cannot get a string value from an error cell");
779 if (cellType == CELL_TYPE_FORMULA)
781 if (stringValue==null) return new HSSFRichTextString("");
783 return stringValue;
787 * set a boolean value for the cell
789 * @param value the boolean value to set this cell to. For formulas we'll set the
790 * precalculated value, for booleans we'll set its value. For other types we
791 * will change the cell to a boolean cell and set its value.
794 public void setCellValue(boolean value)
796 int row=record.getRow();
797 short col=record.getColumn();
798 short styleIndex=record.getXFIndex();
799 if ((cellType != CELL_TYPE_BOOLEAN ) && ( cellType != CELL_TYPE_FORMULA))
801 setCellType(CELL_TYPE_BOOLEAN, false, row, col, styleIndex);
803 (( BoolErrRecord ) record).setValue(value);
807 * set a error value for the cell
809 * @param value the error value to set this cell to. For formulas we'll set the
810 * precalculated value ??? IS THIS RIGHT??? , for errors we'll set
811 * its value. For other types we will change the cell to an error
812 * cell and set its value.
815 public void setCellErrorValue(byte value)
817 int row=record.getRow();
818 short col=record.getColumn();
819 short styleIndex=record.getXFIndex();
820 if ((cellType != CELL_TYPE_ERROR) && (cellType != CELL_TYPE_FORMULA))
822 setCellType(CELL_TYPE_ERROR, false, row, col, styleIndex);
824 (( BoolErrRecord ) record).setValue(value);
827 * Chooses a new boolean value for the cell when its type is changing.<p/>
829 * Usually the caller is calling setCellType() with the intention of calling
830 * setCellValue(boolean) straight afterwards. This method only exists to give
831 * the cell a somewhat reasonable value until the setCellValue() call (if at all).
832 * TODO - perhaps a method like setCellTypeAndValue(int, Object) should be introduced to avoid this
834 private boolean convertCellValueToBoolean() {
836 switch (cellType) {
837 case CELL_TYPE_BOOLEAN:
838 return (( BoolErrRecord ) record).getBooleanValue();
839 case CELL_TYPE_STRING:
840 return Boolean.valueOf(((StringRecord)record).getString()).booleanValue();
841 case CELL_TYPE_NUMERIC:
842 return ((NumberRecord)record).getValue() != 0;
844 // All other cases convert to false
845 // These choices are not well justified.
846 case CELL_TYPE_FORMULA:
847 // should really evaluate, but HSSFCell can't call HSSFFormulaEvaluator
848 case CELL_TYPE_ERROR:
849 case CELL_TYPE_BLANK:
850 return false;
852 throw new RuntimeException("Unexpected cell type (" + cellType + ")");
856 * get the value of the cell as a boolean. For strings, numbers, and errors, we throw an exception.
857 * For blank cells we return a false.
860 public boolean getBooleanCellValue()
862 if (cellType == CELL_TYPE_BOOLEAN)
864 return (( BoolErrRecord ) record).getBooleanValue();
866 if (cellType == CELL_TYPE_BLANK)
868 return false;
870 throw new NumberFormatException(
871 "You cannot get a boolean value from a non-boolean cell");
875 * get the value of the cell as an error code. For strings, numbers, and booleans, we throw an exception.
876 * For blank cells we return a 0.
879 public byte getErrorCellValue()
881 if (cellType == CELL_TYPE_ERROR)
883 return (( BoolErrRecord ) record).getErrorValue();
885 if (cellType == CELL_TYPE_BLANK)
887 return ( byte ) 0;
889 throw new NumberFormatException(
890 "You cannot get an error value from a non-error cell");
894 * set the style for the cell. The style should be an HSSFCellStyle created/retreived from
895 * the HSSFWorkbook.
897 * @param style reference contained in the workbook
898 * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createCellStyle()
899 * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(short)
902 public void setCellStyle(HSSFCellStyle style)
904 record.setXFIndex(style.getIndex());
908 * get the style for the cell. This is a reference to a cell style contained in the workbook
909 * object.
910 * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(short)
913 public HSSFCellStyle getCellStyle()
915 short styleIndex=record.getXFIndex();
916 ExtendedFormatRecord xf = book.getExFormatAt(styleIndex);
917 return new HSSFCellStyle(styleIndex, xf, book);
921 * used for internationalization, currently -1 for unchanged, 0 for compressed unicode or 1 for 16-bit
923 * @see #ENCODING_UNCHANGED
924 * @see #ENCODING_COMPRESSED_UNICODE
925 * @see #ENCODING_UTF_16
927 * @return -1, 1 or 0 for unchanged, compressed or uncompressed (used only with String type)
929 * @deprecated As of 3-Jan-06 POI now automatically handles Unicode without forcing the encoding.
931 public short getEncoding()
933 return encoding;
937 * set the encoding to either 8 or 16 bit. (US/UK use 8-bit, rest of the western world use 16bit)
939 * @see #ENCODING_UNCHANGED
940 * @see #ENCODING_COMPRESSED_UNICODE
941 * @see #ENCODING_UTF_16
943 * @param encoding either ENCODING_COMPRESSED_UNICODE (0) or ENCODING_UTF_16 (1)
944 * @deprecated As of 3-Jan-06 POI now automatically handles Unicode without forcing the encoding.
947 public void setEncoding(short encoding)
949 this.encoding = encoding;
953 * Should only be used by HSSFSheet and friends. Returns the low level CellValueRecordInterface record
955 * @return CellValueRecordInterface representing the cell via the low level api.
958 protected CellValueRecordInterface getCellValueRecord()
960 return record;
964 * @throws RuntimeException if the bounds are exceeded.
966 private void checkBounds(int cellNum) {
967 if (cellNum > 255) {
968 throw new RuntimeException("You cannot have more than 255 columns "+
969 "in a given row (IV). Because Excel can't handle it");
971 else if (cellNum < 0) {
972 throw new RuntimeException("You cannot reference columns with an index of less then 0.");
977 * Sets this cell as the active cell for the worksheet
979 public void setAsActiveCell()
981 int row=record.getRow();
982 short col=record.getColumn();
983 this.sheet.setActiveCellRow(row);
984 this.sheet.setActiveCellCol(col);
988 * Returns a string representation of the cell
990 * This method returns a simple representation,
991 * anthing more complex should be in user code, with
992 * knowledge of the semantics of the sheet being processed.
994 * Formula cells return the formula string,
995 * rather than the formula result.
996 * Dates are displayed in dd-MMM-yyyy format
997 * Errors are displayed as #ERR&lt;errIdx&gt;
999 public String toString() {
1000 switch (getCellType()) {
1001 case CELL_TYPE_BLANK:
1002 return "";
1003 case CELL_TYPE_BOOLEAN:
1004 return getBooleanCellValue()?"TRUE":"FALSE";
1005 case CELL_TYPE_ERROR:
1006 return "#ERR"+getErrorCellValue();
1007 case CELL_TYPE_FORMULA:
1008 return getCellFormula();
1009 case CELL_TYPE_NUMERIC:
1010 //TODO apply the dataformat for this cell
1011 if (HSSFDateUtil.isCellDateFormatted(this)) {
1012 DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
1013 return sdf.format(getDateCellValue());
1014 }else {
1015 return getNumericCellValue() + "";
1017 case CELL_TYPE_STRING:
1018 return getStringCellValue();
1019 default:
1020 return "Unknown Cell Type: " + getCellType();
1025 * Assign a comment to this cell
1027 * @param comment comment associated with this cell
1029 public void setCellComment(HSSFComment comment){
1030 comment.setRow((short)record.getRow());
1031 comment.setColumn(record.getColumn());
1032 this.comment = comment;
1036 * Returns comment associated with this cell
1038 * @return comment associated with this cell
1040 public HSSFComment getCellComment(){
1041 if (comment == null) {
1042 comment = findCellComment(sheet, record.getRow(), record.getColumn());
1044 return comment;
1048 * Cell comment finder.
1049 * Returns cell comment for the specified sheet, row and column.
1051 * @return cell comment or <code>null</code> if not found
1053 protected static HSSFComment findCellComment(Sheet sheet, int row, int column){
1054 HSSFComment comment = null;
1055 HashMap txshapes = new HashMap(); //map shapeId and TextObjectRecord
1056 for (Iterator it = sheet.getRecords().iterator(); it.hasNext(); ) {
1057 Record rec = ( Record ) it.next();
1058 if (rec instanceof NoteRecord){
1059 NoteRecord note = (NoteRecord)rec;
1060 if (note.getRow() == row && note.getColumn() == column){
1061 TextObjectRecord txo = (TextObjectRecord)txshapes.get(new Integer(note.getShapeId()));
1062 comment = new HSSFComment(note, txo);
1063 comment.setRow(note.getRow());
1064 comment.setColumn(note.getColumn());
1065 comment.setAuthor(note.getAuthor());
1066 comment.setVisible(note.getFlags() == NoteRecord.NOTE_VISIBLE);
1067 comment.setString(txo.getStr());
1068 break;
1070 } else if (rec instanceof ObjRecord){
1071 ObjRecord obj = (ObjRecord)rec;
1072 SubRecord sub = (SubRecord)obj.getSubRecords().get(0);
1073 if (sub instanceof CommonObjectDataSubRecord){
1074 CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord)sub;
1075 if (cmo.getObjectType() == CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT){
1076 //find the nearest TextObjectRecord which holds comment's text and map it to its shapeId
1077 while(it.hasNext()) {
1078 rec = ( Record ) it.next();
1079 if (rec instanceof TextObjectRecord) {
1080 txshapes.put(new Integer(cmo.getObjectId()), rec);
1081 break;
1089 return comment;
1093 * Returns hyperlink associated with this cell
1095 * @return hyperlink associated with this cell or null if not found
1097 public HSSFHyperlink getHyperlink(){
1098 for (Iterator it = sheet.getRecords().iterator(); it.hasNext(); ) {
1099 Record rec = ( Record ) it.next();
1100 if (rec instanceof HyperlinkRecord){
1101 HyperlinkRecord link = (HyperlinkRecord)rec;
1102 if(link.getFirstColumn() == record.getColumn() && link.getFirstRow() == record.getRow()){
1103 return new HSSFHyperlink(link);
1107 return null;
1111 * Assign a hypelrink to this cell
1113 * @param link hypelrink associated with this cell
1115 public void setHyperlink(HSSFHyperlink link){
1116 link.setFirstRow(record.getRow());
1117 link.setLastRow(record.getRow());
1118 link.setFirstColumn(record.getColumn());
1119 link.setLastColumn(record.getColumn());
1121 switch(link.getType()){
1122 case HSSFHyperlink.LINK_EMAIL:
1123 case HSSFHyperlink.LINK_URL:
1124 link.setLabel("url");
1125 break;
1126 case HSSFHyperlink.LINK_FILE:
1127 link.setLabel("file");
1128 break;
1129 case HSSFHyperlink.LINK_DOCUMENT:
1130 link.setLabel("place");
1131 break;
1134 int eofLoc = sheet.findFirstRecordLocBySid( EOFRecord.sid );
1135 sheet.getRecords().add( eofLoc, link.record );