You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SXSSFCell.java 40KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308
  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
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.xssf.streaming;
  16. import java.text.DateFormat;
  17. import java.text.SimpleDateFormat;
  18. import java.util.Calendar;
  19. import java.util.Date;
  20. import java.util.Map;
  21. import org.apache.poi.ss.SpreadsheetVersion;
  22. import org.apache.poi.ss.formula.FormulaParseException;
  23. import org.apache.poi.ss.formula.eval.ErrorEval;
  24. import org.apache.poi.ss.usermodel.Cell;
  25. import org.apache.poi.ss.usermodel.CellStyle;
  26. import org.apache.poi.ss.usermodel.CellType;
  27. import org.apache.poi.ss.usermodel.Comment;
  28. import org.apache.poi.ss.usermodel.DateUtil;
  29. import org.apache.poi.ss.usermodel.FormulaError;
  30. import org.apache.poi.ss.usermodel.Hyperlink;
  31. import org.apache.poi.ss.usermodel.RichTextString;
  32. import org.apache.poi.ss.usermodel.Row;
  33. import org.apache.poi.ss.util.CellAddress;
  34. import org.apache.poi.ss.util.CellRangeAddress;
  35. import org.apache.poi.ss.util.CellReference;
  36. import org.apache.poi.util.Internal;
  37. import org.apache.poi.util.LocaleUtil;
  38. import org.apache.poi.util.NotImplemented;
  39. import org.apache.poi.util.POILogFactory;
  40. import org.apache.poi.util.POILogger;
  41. import org.apache.poi.util.Removal;
  42. import org.apache.poi.xssf.usermodel.XSSFHyperlink;
  43. import org.apache.poi.xssf.usermodel.XSSFRichTextString;
  44. /**
  45. * Streaming version of XSSFRow implementing the "BigGridDemo" strategy.
  46. */
  47. public class SXSSFCell implements Cell {
  48. private static final POILogger logger = POILogFactory.getLogger(SXSSFCell.class);
  49. private final SXSSFRow _row;
  50. private Value _value;
  51. private CellStyle _style;
  52. private Property _firstProperty;
  53. /**
  54. * @deprecated POI 3.15 beta 3.
  55. * Will be deleted when we make the CellType enum transition. See bug 59791.
  56. */
  57. @Removal(version="3.17")
  58. @Deprecated
  59. public SXSSFCell(SXSSFRow row, int cellType)
  60. {
  61. this(row, CellType.forInt((cellType)));
  62. }
  63. public SXSSFCell(SXSSFRow row,CellType cellType)
  64. {
  65. _row=row;
  66. setType(cellType);
  67. }
  68. //start of interface implementation
  69. /**
  70. * Returns column index of this cell
  71. *
  72. * @return zero-based column index of a column in a sheet.
  73. */
  74. @Override
  75. public int getColumnIndex()
  76. {
  77. return _row.getCellIndex(this);
  78. }
  79. /**
  80. * Returns row index of a row in the sheet that contains this cell
  81. *
  82. * @return zero-based row index of a row in the sheet that contains this cell
  83. */
  84. @Override
  85. public int getRowIndex()
  86. {
  87. return _row.getRowNum();
  88. }
  89. /**
  90. * {@inheritDoc}
  91. */
  92. @Override
  93. public CellAddress getAddress() {
  94. return new CellAddress(this);
  95. }
  96. /**
  97. * Returns the sheet this cell belongs to
  98. *
  99. * @return the sheet this cell belongs to
  100. */
  101. @Override
  102. public SXSSFSheet getSheet()
  103. {
  104. return _row.getSheet();
  105. }
  106. /**
  107. * Returns the Row this cell belongs to
  108. *
  109. * @return the Row that owns this cell
  110. */
  111. @Override
  112. public Row getRow()
  113. {
  114. return _row;
  115. }
  116. /**
  117. * Set the cells type (numeric, formula or string)
  118. *
  119. * @throws IllegalArgumentException if the specified cell type is invalid
  120. * @see CellType#NUMERIC
  121. * @see CellType#STRING
  122. * @see CellType#FORMULA
  123. * @see CellType#BLANK
  124. * @see CellType#BOOLEAN
  125. * @see CellType#ERROR
  126. * @deprecated POI 3.15 beta 3. Use {@link #setCellType(CellType)} instead.
  127. * Will be deleted when we make the CellType enum transition. See bug 59791.
  128. */
  129. @Override
  130. public void setCellType(int cellType)
  131. {
  132. ensureType(CellType.forInt(cellType));
  133. }
  134. /**
  135. * Set the cells type (numeric, formula or string)
  136. *
  137. * @throws IllegalArgumentException if the specified cell type is invalid
  138. */
  139. @Override
  140. public void setCellType(CellType cellType)
  141. {
  142. ensureType(cellType);
  143. }
  144. /**
  145. * Return the cell type.
  146. *
  147. * @return the cell type
  148. */
  149. @Override
  150. public int getCellType()
  151. {
  152. return getCellTypeEnum().getCode();
  153. }
  154. /**
  155. * Return the cell type.
  156. *
  157. * @return the cell type
  158. * @since POI 3.15 beta 3
  159. * @deprecated POI 3.15 beta 3
  160. * Will be deleted when we make the CellType enum transition. See bug 59791.
  161. */
  162. @Internal(since="POI 3.15 beta 3")
  163. @Override
  164. public CellType getCellTypeEnum()
  165. {
  166. return _value.getType();
  167. }
  168. /**
  169. * Only valid for formula cells
  170. * @return one of ({@link CellType#NUMERIC}, {@link CellType#STRING},
  171. * {@link CellType#BOOLEAN}, {@link CellType#ERROR}) depending
  172. * on the cached value of the formula
  173. */
  174. @Override
  175. public int getCachedFormulaResultType()
  176. {
  177. return getCachedFormulaResultTypeEnum().getCode();
  178. }
  179. /**
  180. * Only valid for formula cells
  181. * @return one of ({@link CellType#NUMERIC}, {@link CellType#STRING},
  182. * {@link CellType#BOOLEAN}, {@link CellType#ERROR}) depending
  183. * on the cached value of the formula
  184. * @since POI 3.15 beta 3
  185. * @deprecated POI 3.15 beta 3.
  186. * Will be deleted when we make the CellType enum transition. See bug 59791.
  187. */
  188. @Internal(since="POI 3.15 beta 3")
  189. @Override
  190. public CellType getCachedFormulaResultTypeEnum()
  191. {
  192. if (_value.getType() != CellType.FORMULA) {
  193. throw new IllegalStateException("Only formula cells have cached results");
  194. }
  195. return ((FormulaValue)_value).getFormulaType();
  196. }
  197. /**
  198. * Set a numeric value for the cell
  199. *
  200. * @param value the numeric value to set this cell to. For formulas we'll set the
  201. * precalculated value, for numerics we'll set its value. For other types we
  202. * will change the cell to a numeric cell and set its value.
  203. */
  204. @Override
  205. public void setCellValue(double value)
  206. {
  207. if(Double.isInfinite(value)) {
  208. // Excel does not support positive/negative infinities,
  209. // rather, it gives a #DIV/0! error in these cases.
  210. setCellErrorValue(FormulaError.DIV0.getCode());
  211. } else if (Double.isNaN(value)){
  212. setCellErrorValue(FormulaError.NUM.getCode());
  213. } else {
  214. ensureTypeOrFormulaType(CellType.NUMERIC);
  215. if(_value.getType()==CellType.FORMULA)
  216. ((NumericFormulaValue)_value).setPreEvaluatedValue(value);
  217. else
  218. ((NumericValue)_value).setValue(value);
  219. }
  220. }
  221. /**
  222. * Converts the supplied date to its equivalent Excel numeric value and sets
  223. * that into the cell.
  224. * <p/>
  225. * <b>Note</b> - There is actually no 'DATE' cell type in Excel. In many
  226. * cases (when entering date values), Excel automatically adjusts the
  227. * <i>cell style</i> to some date format, creating the illusion that the cell
  228. * data type is now something besides {@link CellType#NUMERIC}. POI
  229. * does not attempt to replicate this behaviour. To make a numeric cell
  230. * display as a date, use {@link #setCellStyle(CellStyle)} etc.
  231. *
  232. * @param value the numeric value to set this cell to. For formulas we'll set the
  233. * precalculated value, for numerics we'll set its value. For other types we
  234. * will change the cell to a numerics cell and set its value.
  235. */
  236. @Override
  237. public void setCellValue(Date value) {
  238. if(value == null) {
  239. setCellType(CellType.BLANK);
  240. return;
  241. }
  242. boolean date1904 = getSheet().getWorkbook().isDate1904();
  243. setCellValue(DateUtil.getExcelDate(value, date1904));
  244. }
  245. /**
  246. * Set a date value for the cell. Excel treats dates as numeric so you will need to format the cell as
  247. * a date.
  248. * <p>
  249. * This will set the cell value based on the Calendar's timezone. As Excel
  250. * does not support timezones this means that both 20:00+03:00 and
  251. * 20:00-03:00 will be reported as the same value (20:00) even that there
  252. * are 6 hours difference between the two times. This difference can be
  253. * preserved by using <code>setCellValue(value.getTime())</code> which will
  254. * automatically shift the times to the default timezone.
  255. * </p>
  256. *
  257. * @param value the date value to set this cell to. For formulas we'll set the
  258. * precalculated value, for numerics we'll set its value. For othertypes we
  259. * will change the cell to a numeric cell and set its value.
  260. */
  261. @Override
  262. public void setCellValue(Calendar value) {
  263. if(value == null) {
  264. setCellType(CellType.BLANK);
  265. return;
  266. }
  267. boolean date1904 = getSheet().getWorkbook().isDate1904();
  268. setCellValue( DateUtil.getExcelDate(value, date1904 ));
  269. }
  270. /**
  271. * Set a rich string value for the cell.
  272. *
  273. * @param value value to set the cell to. For formulas we'll set the formula
  274. * string, for String cells we'll set its value. For other types we will
  275. * change the cell to a string cell and set its value.
  276. * If value is null then we will change the cell to a Blank cell.
  277. */
  278. @Override
  279. public void setCellValue(RichTextString value)
  280. {
  281. XSSFRichTextString xvalue = (XSSFRichTextString)value;
  282. if (xvalue != null && xvalue.getString() != null) {
  283. ensureRichTextStringType();
  284. if (xvalue.length() > SpreadsheetVersion.EXCEL2007.getMaxTextLength()) {
  285. throw new IllegalArgumentException("The maximum length of cell contents (text) is 32,767 characters");
  286. }
  287. if (xvalue.hasFormatting())
  288. logger.log(POILogger.WARN, "SXSSF doesn't support Shared Strings, rich text formatting information has be lost");
  289. ((RichTextValue)_value).setValue(xvalue);
  290. } else {
  291. setCellType(CellType.BLANK);
  292. }
  293. }
  294. /**
  295. * Set a string value for the cell.
  296. *
  297. * @param value value to set the cell to. For formulas we'll set the formula
  298. * string, for String cells we'll set its value. For other types we will
  299. * change the cell to a string cell and set its value.
  300. * If value is null then we will change the cell to a Blank cell.
  301. */
  302. @Override
  303. public void setCellValue(String value)
  304. {
  305. if (value != null) {
  306. ensureTypeOrFormulaType(CellType.STRING);
  307. if (value.length() > SpreadsheetVersion.EXCEL2007.getMaxTextLength()) {
  308. throw new IllegalArgumentException("The maximum length of cell contents (text) is 32,767 characters");
  309. }
  310. if(_value.getType()==CellType.FORMULA)
  311. if(_value instanceof NumericFormulaValue) {
  312. ((NumericFormulaValue) _value).setPreEvaluatedValue(Double.parseDouble(value));
  313. } else {
  314. ((StringFormulaValue) _value).setPreEvaluatedValue(value);
  315. }
  316. else
  317. ((PlainStringValue)_value).setValue(value);
  318. } else {
  319. setCellType(CellType.BLANK);
  320. }
  321. }
  322. /**
  323. * Sets formula for this cell.
  324. * <p>
  325. * Note, this method only sets the formula string and does not calculate the formula value.
  326. * To set the precalculated value use {@link #setCellValue(double)} or {@link #setCellValue(String)}
  327. * </p>
  328. *
  329. * @param formula the formula to set, e.g. <code>"SUM(C4:E4)"</code>.
  330. * If the argument is <code>null</code> then the current formula is removed.
  331. * @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid
  332. */
  333. @Override
  334. public void setCellFormula(String formula) throws FormulaParseException
  335. {
  336. if(formula == null) {
  337. setType(CellType.BLANK);
  338. return;
  339. }
  340. ensureFormulaType(computeTypeFromFormula(formula));
  341. ((FormulaValue)_value).setValue(formula);
  342. }
  343. /**
  344. * Return a formula for the cell, for example, <code>SUM(C4:E4)</code>
  345. *
  346. * @return a formula for the cell
  347. * @throws IllegalStateException if the cell type returned by {@link #getCellTypeEnum()} is not CellType.FORMULA
  348. */
  349. @Override
  350. public String getCellFormula()
  351. {
  352. if(_value.getType()!=CellType.FORMULA)
  353. throw typeMismatch(CellType.FORMULA,_value.getType(),false);
  354. return ((FormulaValue)_value).getValue();
  355. }
  356. /**
  357. * Get the value of the cell as a number.
  358. * <p>
  359. * For strings we throw an exception. For blank cells we return a 0.
  360. * For formulas or error cells we return the precalculated value;
  361. * </p>
  362. * @return the value of the cell as a number
  363. * @throws IllegalStateException if the cell type returned by {@link #getCellTypeEnum()} is CellType.STRING
  364. * @exception NumberFormatException if the cell value isn't a parsable <code>double</code>.
  365. * @see org.apache.poi.ss.usermodel.DataFormatter for turning this number into a string similar to that which Excel would render this number as.
  366. */
  367. @Override
  368. public double getNumericCellValue()
  369. {
  370. CellType cellType = getCellTypeEnum();
  371. switch(cellType)
  372. {
  373. case BLANK:
  374. return 0.0;
  375. case FORMULA:
  376. {
  377. FormulaValue fv=(FormulaValue)_value;
  378. if(fv.getFormulaType()!=CellType.NUMERIC)
  379. throw typeMismatch(CellType.NUMERIC, CellType.FORMULA, false);
  380. return ((NumericFormulaValue)_value).getPreEvaluatedValue();
  381. }
  382. case NUMERIC:
  383. return ((NumericValue)_value).getValue();
  384. default:
  385. throw typeMismatch(CellType.NUMERIC, cellType, false);
  386. }
  387. }
  388. /**
  389. * Get the value of the cell as a date.
  390. * <p>
  391. * For strings we throw an exception. For blank cells we return a null.
  392. * </p>
  393. * @return the value of the cell as a date
  394. * @throws IllegalStateException if the cell type returned by {@link #getCellTypeEnum()} is CellType.STRING
  395. * @exception NumberFormatException if the cell value isn't a parsable <code>double</code>.
  396. * @see org.apache.poi.ss.usermodel.DataFormatter for formatting this date into a string similar to how excel does.
  397. */
  398. @Override
  399. public Date getDateCellValue()
  400. {
  401. CellType cellType = getCellTypeEnum();
  402. if (cellType == CellType.BLANK)
  403. {
  404. return null;
  405. }
  406. double value = getNumericCellValue();
  407. boolean date1904 = getSheet().getWorkbook().isDate1904();
  408. return DateUtil.getJavaDate(value, date1904);
  409. }
  410. /**
  411. * Get the value of the cell as a XSSFRichTextString
  412. * <p>
  413. * For numeric cells we throw an exception. For blank cells we return an empty string.
  414. * For formula cells we return the pre-calculated value if a string, otherwise an exception.
  415. * </p>
  416. * @return the value of the cell as a XSSFRichTextString
  417. */
  418. @Override
  419. public RichTextString getRichStringCellValue()
  420. {
  421. CellType cellType = getCellTypeEnum();
  422. if(getCellTypeEnum() != CellType.STRING)
  423. throw typeMismatch(CellType.STRING, cellType, false);
  424. StringValue sval = (StringValue)_value;
  425. if(sval.isRichText())
  426. return ((RichTextValue)_value).getValue();
  427. else {
  428. String plainText = getStringCellValue();
  429. return getSheet().getWorkbook().getCreationHelper().createRichTextString(plainText);
  430. }
  431. }
  432. /**
  433. * Get the value of the cell as a string
  434. * <p>
  435. * For numeric cells we throw an exception. For blank cells we return an empty string.
  436. * For formulaCells that are not string Formulas, we throw an exception.
  437. * </p>
  438. * @return the value of the cell as a string
  439. */
  440. @Override
  441. public String getStringCellValue()
  442. {
  443. CellType cellType = getCellTypeEnum();
  444. switch(cellType)
  445. {
  446. case BLANK:
  447. return "";
  448. case FORMULA:
  449. {
  450. FormulaValue fv=(FormulaValue)_value;
  451. if(fv.getFormulaType()!=CellType.STRING)
  452. throw typeMismatch(CellType.STRING, CellType.FORMULA, false);
  453. return ((StringFormulaValue)_value).getPreEvaluatedValue();
  454. }
  455. case STRING:
  456. {
  457. if(((StringValue)_value).isRichText())
  458. return ((RichTextValue)_value).getValue().getString();
  459. else
  460. return ((PlainStringValue)_value).getValue();
  461. }
  462. default:
  463. throw typeMismatch(CellType.STRING, cellType, false);
  464. }
  465. }
  466. /**
  467. * Set a boolean value for the cell
  468. *
  469. * @param value the boolean value to set this cell to. For formulas we'll set the
  470. * precalculated value, for booleans we'll set its value. For other types we
  471. * will change the cell to a boolean cell and set its value.
  472. */
  473. @Override
  474. public void setCellValue(boolean value)
  475. {
  476. ensureTypeOrFormulaType(CellType.BOOLEAN);
  477. if(_value.getType()==CellType.FORMULA)
  478. ((BooleanFormulaValue)_value).setPreEvaluatedValue(value);
  479. else
  480. ((BooleanValue)_value).setValue(value);
  481. }
  482. /**
  483. * Set a error value for the cell
  484. *
  485. * @param value the error value to set this cell to. For formulas we'll set the
  486. * precalculated value , for errors we'll set
  487. * its value. For other types we will change the cell to an error
  488. * cell and set its value.
  489. * @see org.apache.poi.ss.usermodel.FormulaError
  490. */
  491. @Override
  492. public void setCellErrorValue(byte value)
  493. {
  494. ensureType(CellType.ERROR);
  495. if(_value.getType()==CellType.FORMULA)
  496. ((ErrorFormulaValue)_value).setPreEvaluatedValue(value);
  497. else
  498. ((ErrorValue)_value).setValue(value);
  499. }
  500. /**
  501. * Get the value of the cell as a boolean.
  502. * <p>
  503. * For strings, numbers, and errors, we throw an exception. For blank cells we return a false.
  504. * </p>
  505. * @return the value of the cell as a boolean
  506. * @throws IllegalStateException if the cell type returned by {@link #getCellTypeEnum()}
  507. * is not CellType.BOOLEAN, CellType.BLANK or CellType.FORMULA
  508. */
  509. @Override
  510. public boolean getBooleanCellValue()
  511. {
  512. CellType cellType = getCellTypeEnum();
  513. switch(cellType)
  514. {
  515. case BLANK:
  516. return false;
  517. case FORMULA:
  518. {
  519. FormulaValue fv=(FormulaValue)_value;
  520. if(fv.getFormulaType()!=CellType.BOOLEAN)
  521. throw typeMismatch(CellType.BOOLEAN, CellType.FORMULA, false);
  522. return ((BooleanFormulaValue)_value).getPreEvaluatedValue();
  523. }
  524. case BOOLEAN:
  525. {
  526. return ((BooleanValue)_value).getValue();
  527. }
  528. default:
  529. throw typeMismatch(CellType.BOOLEAN, cellType, false);
  530. }
  531. }
  532. /**
  533. * Get the value of the cell as an error code.
  534. * <p>
  535. * For strings, numbers, and booleans, we throw an exception.
  536. * For blank cells we return a 0.
  537. * </p>
  538. *
  539. * @return the value of the cell as an error code
  540. * @throws IllegalStateException if the cell type returned by {@link #getCellTypeEnum()} isn't CellType.ERROR
  541. * @see org.apache.poi.ss.usermodel.FormulaError for error codes
  542. */
  543. @Override
  544. public byte getErrorCellValue()
  545. {
  546. CellType cellType = getCellTypeEnum();
  547. switch(cellType)
  548. {
  549. case BLANK:
  550. return 0;
  551. case FORMULA:
  552. {
  553. FormulaValue fv=(FormulaValue)_value;
  554. if(fv.getFormulaType()!=CellType.ERROR)
  555. throw typeMismatch(CellType.ERROR, CellType.FORMULA, false);
  556. return ((ErrorFormulaValue)_value).getPreEvaluatedValue();
  557. }
  558. case ERROR:
  559. {
  560. return ((ErrorValue)_value).getValue();
  561. }
  562. default:
  563. throw typeMismatch(CellType.ERROR, cellType, false);
  564. }
  565. }
  566. /**
  567. * <p>Set the style for the cell. The style should be an CellStyle created/retreived from
  568. * the Workbook.</p>
  569. *
  570. * <p>To change the style of a cell without affecting other cells that use the same style,
  571. * use {@link org.apache.poi.ss.util.CellUtil#setCellStyleProperties(Cell, Map)}</p>
  572. *
  573. * @param style reference contained in the workbook.
  574. * If the value is null then the style information is removed causing the cell to used the default workbook style.
  575. * @see org.apache.poi.ss.usermodel.Workbook#createCellStyle
  576. */
  577. @Override
  578. public void setCellStyle(CellStyle style)
  579. {
  580. _style=style;
  581. }
  582. /**
  583. * Return the cell's style.
  584. *
  585. * @return the cell's style. Always not-null. Default cell style has zero index and can be obtained as
  586. * <code>workbook.getCellStyleAt(0)</code>
  587. * @see org.apache.poi.ss.usermodel.Workbook#getCellStyleAt(int)
  588. */
  589. @Override
  590. public CellStyle getCellStyle()
  591. {
  592. if(_style == null){
  593. SXSSFWorkbook wb = (SXSSFWorkbook)getRow().getSheet().getWorkbook();
  594. return wb.getCellStyleAt((short)0);
  595. } else {
  596. return _style;
  597. }
  598. }
  599. /**
  600. * {@inheritDoc}
  601. */
  602. @Override
  603. public void setAsActiveCell()
  604. {
  605. getSheet().setActiveCell(getAddress());
  606. }
  607. /**
  608. * Assign a comment to this cell
  609. *
  610. * @param comment comment associated with this cell
  611. */
  612. @Override
  613. public void setCellComment(Comment comment)
  614. {
  615. setProperty(Property.COMMENT,comment);
  616. }
  617. /**
  618. * Returns comment associated with this cell
  619. *
  620. * @return comment associated with this cell or <code>null</code> if not found
  621. */
  622. @Override
  623. public Comment getCellComment()
  624. {
  625. return (Comment)getPropertyValue(Property.COMMENT);
  626. }
  627. /**
  628. * Removes the comment for this cell, if there is one.
  629. */
  630. @Override
  631. public void removeCellComment()
  632. {
  633. removeProperty(Property.COMMENT);
  634. }
  635. /**
  636. * @return hyperlink associated with this cell or <code>null</code> if not found
  637. */
  638. @Override
  639. public Hyperlink getHyperlink()
  640. {
  641. return (Hyperlink)getPropertyValue(Property.HYPERLINK);
  642. }
  643. /**
  644. * Assign a hyperlink to this cell. If the supplied hyperlink is null, the
  645. * hyperlink for this cell will be removed.
  646. *
  647. * @param link hyperlink associated with this cell
  648. */
  649. @Override
  650. public void setHyperlink(Hyperlink link)
  651. {
  652. if (link == null) {
  653. removeHyperlink();
  654. return;
  655. }
  656. setProperty(Property.HYPERLINK,link);
  657. XSSFHyperlink xssfobj = (XSSFHyperlink)link;
  658. // Assign to us
  659. CellReference ref = new CellReference(getRowIndex(), getColumnIndex());
  660. xssfobj.getCTHyperlink().setRef( ref.formatAsString() );
  661. // Add to the lists
  662. getSheet()._sh.addHyperlink(xssfobj);
  663. }
  664. /**
  665. * Removes the hyperlink for this cell, if there is one.
  666. */
  667. @Override
  668. public void removeHyperlink()
  669. {
  670. removeProperty(Property.HYPERLINK);
  671. getSheet()._sh.removeHyperlink(getRowIndex(), getColumnIndex());
  672. }
  673. /**
  674. * Only valid for array formula cells
  675. *
  676. * @return range of the array formula group that the cell belongs to.
  677. */
  678. // TODO: What is this?
  679. @NotImplemented
  680. public CellRangeAddress getArrayFormulaRange()
  681. {
  682. return null;
  683. }
  684. /**
  685. * @return <code>true</code> if this cell is part of group of cells having a common array formula.
  686. */
  687. //TODO: What is this?
  688. @NotImplemented
  689. public boolean isPartOfArrayFormulaGroup()
  690. {
  691. return false;
  692. }
  693. //end of interface implementation
  694. /**
  695. * Returns a string representation of the cell
  696. * <p>
  697. * Formula cells return the formula string, rather than the formula result.
  698. * Dates are displayed in dd-MMM-yyyy format
  699. * Errors are displayed as #ERR&lt;errIdx&gt;
  700. * </p>
  701. */
  702. @Override
  703. public String toString() {
  704. switch (getCellTypeEnum()) {
  705. case BLANK:
  706. return "";
  707. case BOOLEAN:
  708. return getBooleanCellValue() ? "TRUE" : "FALSE";
  709. case ERROR:
  710. return ErrorEval.getText(getErrorCellValue());
  711. case FORMULA:
  712. return getCellFormula();
  713. case NUMERIC:
  714. if (DateUtil.isCellDateFormatted(this)) {
  715. DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", LocaleUtil.getUserLocale());
  716. sdf.setTimeZone(LocaleUtil.getUserTimeZone());
  717. return sdf.format(getDateCellValue());
  718. }
  719. return getNumericCellValue() + "";
  720. case STRING:
  721. return getRichStringCellValue().toString();
  722. default:
  723. return "Unknown Cell Type: " + getCellTypeEnum();
  724. }
  725. }
  726. /*package*/ void removeProperty(int type)
  727. {
  728. Property current=_firstProperty;
  729. Property previous=null;
  730. while(current!=null&&current.getType()!=type)
  731. {
  732. previous=current;
  733. current=current._next;
  734. }
  735. if(current!=null)
  736. {
  737. if(previous!=null)
  738. {
  739. previous._next=current._next;
  740. }
  741. else
  742. {
  743. _firstProperty=current._next;
  744. }
  745. }
  746. }
  747. /*package*/ void setProperty(int type,Object value)
  748. {
  749. Property current=_firstProperty;
  750. Property previous=null;
  751. while(current!=null&&current.getType()!=type)
  752. {
  753. previous=current;
  754. current=current._next;
  755. }
  756. if(current!=null)
  757. {
  758. current.setValue(value);
  759. }
  760. else
  761. {
  762. switch(type)
  763. {
  764. case Property.COMMENT:
  765. {
  766. current=new CommentProperty(value);
  767. break;
  768. }
  769. case Property.HYPERLINK:
  770. {
  771. current=new HyperlinkProperty(value);
  772. break;
  773. }
  774. default:
  775. {
  776. throw new IllegalArgumentException("Invalid type: " + type);
  777. }
  778. }
  779. if(previous!=null)
  780. {
  781. previous._next=current;
  782. }
  783. else
  784. {
  785. _firstProperty=current;
  786. }
  787. }
  788. }
  789. /*package*/ Object getPropertyValue(int type)
  790. {
  791. return getPropertyValue(type,null);
  792. }
  793. /*package*/ Object getPropertyValue(int type,String defaultValue)
  794. {
  795. Property current=_firstProperty;
  796. while(current!=null&&current.getType()!=type) current=current._next;
  797. return current==null?defaultValue:current.getValue();
  798. }
  799. /*package*/ void ensurePlainStringType()
  800. {
  801. if(_value.getType()!=CellType.STRING
  802. ||((StringValue)_value).isRichText())
  803. _value=new PlainStringValue();
  804. }
  805. /*package*/ void ensureRichTextStringType()
  806. {
  807. if(_value.getType()!=CellType.STRING
  808. ||!((StringValue)_value).isRichText())
  809. _value=new RichTextValue();
  810. }
  811. /*package*/ void ensureType(CellType type)
  812. {
  813. if(_value.getType()!=type)
  814. setType(type);
  815. }
  816. /*package*/ void ensureFormulaType(CellType type)
  817. {
  818. if(_value.getType()!=CellType.FORMULA
  819. ||((FormulaValue)_value).getFormulaType()!=type)
  820. setFormulaType(type);
  821. }
  822. /*
  823. * Sets the cell type to type if it is different
  824. */
  825. /*package*/ void ensureTypeOrFormulaType(CellType type)
  826. {
  827. if(_value.getType()==type)
  828. {
  829. if(type==CellType.STRING&&((StringValue)_value).isRichText())
  830. setType(CellType.STRING);
  831. return;
  832. }
  833. if(_value.getType()==CellType.FORMULA)
  834. {
  835. if(((FormulaValue)_value).getFormulaType()==type)
  836. return;
  837. setFormulaType(type); // once a formula, always a formula
  838. return;
  839. }
  840. setType(type);
  841. }
  842. /**
  843. * changes the cell type to the specified type, and resets the value to the default value for that type
  844. * If cell type is the same as specified type, this will reset the value to the default value for that type
  845. *
  846. * @param type the cell type to set
  847. * @throws IllegalArgumentException if type is not a recognized type
  848. */
  849. /*package*/ void setType(CellType type)
  850. {
  851. switch(type)
  852. {
  853. case NUMERIC:
  854. {
  855. _value=new NumericValue();
  856. break;
  857. }
  858. case STRING:
  859. {
  860. PlainStringValue sval = new PlainStringValue();
  861. if(_value != null){
  862. // if a cell is not blank then convert the old value to string
  863. String str = convertCellValueToString();
  864. sval.setValue(str);
  865. }
  866. _value = sval;
  867. break;
  868. }
  869. case FORMULA:
  870. {
  871. _value=new NumericFormulaValue();
  872. break;
  873. }
  874. case BLANK:
  875. {
  876. _value=new BlankValue();
  877. break;
  878. }
  879. case BOOLEAN:
  880. {
  881. BooleanValue bval = new BooleanValue();
  882. if(_value != null){
  883. // if a cell is not blank then convert the old value to string
  884. boolean val = convertCellValueToBoolean();
  885. bval.setValue(val);
  886. }
  887. _value = bval;
  888. break;
  889. }
  890. case ERROR:
  891. {
  892. _value=new ErrorValue();
  893. break;
  894. }
  895. default:
  896. {
  897. throw new IllegalArgumentException("Illegal type " + type);
  898. }
  899. }
  900. }
  901. /*package*/ void setFormulaType(CellType type)
  902. {
  903. Value prevValue = _value;
  904. switch(type)
  905. {
  906. case NUMERIC:
  907. {
  908. _value=new NumericFormulaValue();
  909. break;
  910. }
  911. case STRING:
  912. {
  913. _value=new StringFormulaValue();
  914. break;
  915. }
  916. case BOOLEAN:
  917. {
  918. _value=new BooleanFormulaValue();
  919. break;
  920. }
  921. case ERROR:
  922. {
  923. _value=new ErrorFormulaValue();
  924. break;
  925. }
  926. default:
  927. {
  928. throw new IllegalArgumentException("Illegal type " + type);
  929. }
  930. }
  931. // if we had a Formula before, we should copy over the _value of the formula
  932. if(prevValue instanceof FormulaValue) {
  933. ((FormulaValue)_value)._value = ((FormulaValue)prevValue)._value;
  934. }
  935. }
  936. //TODO: implement this correctly
  937. @NotImplemented
  938. /*package*/ CellType computeTypeFromFormula(String formula)
  939. {
  940. return CellType.NUMERIC;
  941. }
  942. //COPIED FROM https://svn.apache.org/repos/asf/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java since the functions are declared private there
  943. /**
  944. * Used to help format error messages
  945. */
  946. private static RuntimeException typeMismatch(CellType expectedTypeCode, CellType actualTypeCode, boolean isFormulaCell) {
  947. String msg = "Cannot get a " + expectedTypeCode + " value from a " + actualTypeCode
  948. + " " + (isFormulaCell ? "formula " : "") + "cell";
  949. return new IllegalStateException(msg);
  950. }
  951. private boolean convertCellValueToBoolean() {
  952. CellType cellType = getCellTypeEnum();
  953. if (cellType == CellType.FORMULA) {
  954. cellType = getCachedFormulaResultTypeEnum();
  955. }
  956. switch (cellType) {
  957. case BOOLEAN:
  958. return getBooleanCellValue();
  959. case STRING:
  960. String text = getStringCellValue();
  961. return Boolean.parseBoolean(text);
  962. case NUMERIC:
  963. return getNumericCellValue() != 0;
  964. case ERROR:
  965. case BLANK:
  966. return false;
  967. default: throw new RuntimeException("Unexpected cell type (" + cellType + ")");
  968. }
  969. }
  970. private String convertCellValueToString() {
  971. CellType cellType = getCellTypeEnum();
  972. return convertCellValueToString(cellType);
  973. }
  974. private String convertCellValueToString(CellType cellType) {
  975. switch (cellType) {
  976. case BLANK:
  977. return "";
  978. case BOOLEAN:
  979. return getBooleanCellValue() ? "TRUE" : "FALSE";
  980. case STRING:
  981. return getStringCellValue();
  982. case NUMERIC:
  983. return Double.toString( getNumericCellValue() );
  984. case ERROR:
  985. byte errVal = getErrorCellValue();
  986. return FormulaError.forInt(errVal).getString();
  987. case FORMULA:
  988. if (_value != null) {
  989. FormulaValue fv = (FormulaValue)_value;
  990. if (fv.getFormulaType() != CellType.FORMULA) {
  991. return convertCellValueToString(fv.getFormulaType());
  992. }
  993. }
  994. return "";
  995. default:
  996. throw new IllegalStateException("Unexpected cell type (" + cellType + ")");
  997. }
  998. }
  999. //END OF COPIED CODE
  1000. static abstract class Property
  1001. {
  1002. final static int COMMENT=1;
  1003. final static int HYPERLINK=2;
  1004. Object _value;
  1005. Property _next;
  1006. public Property(Object value)
  1007. {
  1008. _value=value;
  1009. }
  1010. abstract int getType();
  1011. void setValue(Object value)
  1012. {
  1013. _value=value;
  1014. }
  1015. Object getValue()
  1016. {
  1017. return _value;
  1018. }
  1019. }
  1020. static class CommentProperty extends Property
  1021. {
  1022. public CommentProperty(Object value)
  1023. {
  1024. super(value);
  1025. }
  1026. @Override
  1027. public int getType()
  1028. {
  1029. return COMMENT;
  1030. }
  1031. }
  1032. static class HyperlinkProperty extends Property
  1033. {
  1034. public HyperlinkProperty(Object value)
  1035. {
  1036. super(value);
  1037. }
  1038. @Override
  1039. public int getType()
  1040. {
  1041. return HYPERLINK;
  1042. }
  1043. }
  1044. interface Value
  1045. {
  1046. CellType getType();
  1047. }
  1048. static class NumericValue implements Value
  1049. {
  1050. double _value;
  1051. public CellType getType()
  1052. {
  1053. return CellType.NUMERIC;
  1054. }
  1055. void setValue(double value)
  1056. {
  1057. _value=value;
  1058. }
  1059. double getValue()
  1060. {
  1061. return _value;
  1062. }
  1063. }
  1064. static abstract class StringValue implements Value
  1065. {
  1066. public CellType getType()
  1067. {
  1068. return CellType.STRING;
  1069. }
  1070. //We cannot introduce a new type CellType.RICH_TEXT because the types are public so we have to make rich text as a type of string
  1071. abstract boolean isRichText(); // using the POI style which seems to avoid "instanceof".
  1072. }
  1073. static class PlainStringValue extends StringValue
  1074. {
  1075. String _value;
  1076. void setValue(String value)
  1077. {
  1078. _value=value;
  1079. }
  1080. String getValue()
  1081. {
  1082. return _value;
  1083. }
  1084. @Override
  1085. boolean isRichText()
  1086. {
  1087. return false;
  1088. }
  1089. }
  1090. static class RichTextValue extends StringValue
  1091. {
  1092. RichTextString _value;
  1093. @Override
  1094. public CellType getType()
  1095. {
  1096. return CellType.STRING;
  1097. }
  1098. void setValue(RichTextString value)
  1099. {
  1100. _value=value;
  1101. }
  1102. RichTextString getValue()
  1103. {
  1104. return _value;
  1105. }
  1106. @Override
  1107. boolean isRichText()
  1108. {
  1109. return true;
  1110. }
  1111. }
  1112. static abstract class FormulaValue implements Value
  1113. {
  1114. String _value;
  1115. public CellType getType()
  1116. {
  1117. return CellType.FORMULA;
  1118. }
  1119. void setValue(String value)
  1120. {
  1121. _value=value;
  1122. }
  1123. String getValue()
  1124. {
  1125. return _value;
  1126. }
  1127. abstract CellType getFormulaType();
  1128. }
  1129. static class NumericFormulaValue extends FormulaValue
  1130. {
  1131. double _preEvaluatedValue;
  1132. @Override
  1133. CellType getFormulaType()
  1134. {
  1135. return CellType.NUMERIC;
  1136. }
  1137. void setPreEvaluatedValue(double value)
  1138. {
  1139. _preEvaluatedValue=value;
  1140. }
  1141. double getPreEvaluatedValue()
  1142. {
  1143. return _preEvaluatedValue;
  1144. }
  1145. }
  1146. static class StringFormulaValue extends FormulaValue
  1147. {
  1148. String _preEvaluatedValue;
  1149. @Override
  1150. CellType getFormulaType()
  1151. {
  1152. return CellType.STRING;
  1153. }
  1154. void setPreEvaluatedValue(String value)
  1155. {
  1156. _preEvaluatedValue=value;
  1157. }
  1158. String getPreEvaluatedValue()
  1159. {
  1160. return _preEvaluatedValue;
  1161. }
  1162. }
  1163. static class BooleanFormulaValue extends FormulaValue
  1164. {
  1165. boolean _preEvaluatedValue;
  1166. @Override
  1167. CellType getFormulaType()
  1168. {
  1169. return CellType.BOOLEAN;
  1170. }
  1171. void setPreEvaluatedValue(boolean value)
  1172. {
  1173. _preEvaluatedValue=value;
  1174. }
  1175. boolean getPreEvaluatedValue()
  1176. {
  1177. return _preEvaluatedValue;
  1178. }
  1179. }
  1180. static class ErrorFormulaValue extends FormulaValue
  1181. {
  1182. byte _preEvaluatedValue;
  1183. @Override
  1184. CellType getFormulaType()
  1185. {
  1186. return CellType.ERROR;
  1187. }
  1188. void setPreEvaluatedValue(byte value)
  1189. {
  1190. _preEvaluatedValue=value;
  1191. }
  1192. byte getPreEvaluatedValue()
  1193. {
  1194. return _preEvaluatedValue;
  1195. }
  1196. }
  1197. static class BlankValue implements Value
  1198. {
  1199. public CellType getType()
  1200. {
  1201. return CellType.BLANK;
  1202. }
  1203. }
  1204. static class BooleanValue implements Value
  1205. {
  1206. boolean _value;
  1207. public CellType getType()
  1208. {
  1209. return CellType.BOOLEAN;
  1210. }
  1211. void setValue(boolean value)
  1212. {
  1213. _value=value;
  1214. }
  1215. boolean getValue()
  1216. {
  1217. return _value;
  1218. }
  1219. }
  1220. static class ErrorValue implements Value
  1221. {
  1222. byte _value;
  1223. public CellType getType()
  1224. {
  1225. return CellType.ERROR;
  1226. }
  1227. void setValue(byte value)
  1228. {
  1229. _value=value;
  1230. }
  1231. byte getValue()
  1232. {
  1233. return _value;
  1234. }
  1235. }
  1236. }