PageRenderTime 47ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

/components/forks/poi/src/loci/poi/hssf/model/Sheet.java

http://github.com/openmicroscopy/bioformats
Java | 3299 lines | 1613 code | 334 blank | 1352 comment | 345 complexity | 1e8d548d196dc1063c30d9430b35b9f5 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0, BSD-2-Clause, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * #%L
  3. * Fork of Apache Jakarta POI.
  4. * %%
  5. * Copyright (C) 2008 - 2013 Open Microscopy Environment:
  6. * - Board of Regents of the University of Wisconsin-Madison
  7. * - Glencoe Software, Inc.
  8. * - University of Dundee
  9. * %%
  10. * Licensed under the Apache License, Version 2.0 (the "License");
  11. * you may not use this file except in compliance with the License.
  12. * You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS,
  18. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. * See the License for the specific language governing permissions and
  20. * limitations under the License.
  21. * #L%
  22. */
  23. /* ====================================================================
  24. Licensed to the Apache Software Foundation (ASF) under one or more
  25. contributor license agreements. See the NOTICE file distributed with
  26. this work for additional information regarding copyright ownership.
  27. The ASF licenses this file to You under the Apache License, Version 2.0
  28. (the "License"); you may not use this file except in compliance with
  29. the License. You may obtain a copy of the License at
  30. http://www.apache.org/licenses/LICENSE-2.0
  31. Unless required by applicable law or agreed to in writing, software
  32. distributed under the License is distributed on an "AS IS" BASIS,
  33. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  34. See the License for the specific language governing permissions and
  35. limitations under the License.
  36. ==================================================================== */
  37. package loci.poi.hssf.model;
  38. import loci.poi.hssf.record.*;
  39. import loci.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
  40. import loci.poi.hssf.record.aggregates.FormulaRecordAggregate;
  41. import loci.poi.hssf.record.aggregates.RowRecordsAggregate;
  42. import loci.poi.hssf.record.aggregates.ValueRecordsAggregate;
  43. import loci.poi.hssf.record.formula.Ptg;
  44. import loci.poi.hssf.util.PaneInformation;
  45. import loci.poi.util.POILogFactory;
  46. import loci.poi.util.POILogger;
  47. import java.util.ArrayList;
  48. import java.util.Iterator;
  49. import java.util.List; // normally I don't do this, buy we literally mean ALL
  50. /**
  51. * Low level model implementation of a Sheet (one workbook contains many sheets)
  52. * This file contains the low level binary records starting at the sheets BOF and
  53. * ending with the sheets EOF. Use HSSFSheet for a high level representation.
  54. * <P>
  55. * The structures of the highlevel API use references to this to perform most of their
  56. * operations. Its probably unwise to use these low level structures directly unless you
  57. * really know what you're doing. I recommend you read the Microsoft Excel 97 Developer's
  58. * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf
  59. * before even attempting to use this.
  60. * <P>
  61. * @author Andrew C. Oliver (acoliver at apache dot org)
  62. * @author Glen Stampoultzis (glens at apache.org)
  63. * @author Shawn Laubach (slaubach at apache dot org) Gridlines, Headers, Footers, PrintSetup, and Setting Default Column Styles
  64. * @author Jason Height (jheight at chariot dot net dot au) Clone support. DBCell & Index Record writing support
  65. * @author Brian Sanders (kestrel at burdell dot org) Active Cell support
  66. * @author Jean-Pierre Paris (jean-pierre.paris at m4x dot org) (Just a little)
  67. *
  68. * @see loci.poi.hssf.model.Workbook
  69. * @see loci.poi.hssf.usermodel.HSSFSheet
  70. * @version 1.0-pre
  71. */
  72. public class Sheet implements Model
  73. {
  74. public static final short LeftMargin = 0;
  75. public static final short RightMargin = 1;
  76. public static final short TopMargin = 2;
  77. public static final short BottomMargin = 3;
  78. private static POILogger log = POILogFactory.getLogger(Sheet.class);
  79. protected ArrayList records = null;
  80. int preoffset = 0; // offset of the sheet in a new file
  81. int loc = 0;
  82. protected int dimsloc = 0;
  83. protected DimensionsRecord dims;
  84. protected DefaultColWidthRecord defaultcolwidth = null;
  85. protected DefaultRowHeightRecord defaultrowheight = null;
  86. protected GridsetRecord gridset = null;
  87. protected PrintSetupRecord printSetup = null;
  88. protected HeaderRecord header = null;
  89. protected FooterRecord footer = null;
  90. protected PrintGridlinesRecord printGridlines = null;
  91. protected WindowTwoRecord windowTwo = null;
  92. protected MergeCellsRecord merged = null;
  93. protected Margin[] margins = null;
  94. protected List mergedRecords = new ArrayList();
  95. protected int numMergedRegions = 0;
  96. protected SelectionRecord selection = null;
  97. protected ColumnInfoRecordsAggregate columns = null;
  98. protected ValueRecordsAggregate cells = null;
  99. protected RowRecordsAggregate rows = null;
  100. private Iterator valueRecIterator = null;
  101. private Iterator rowRecIterator = null;
  102. protected int eofLoc = 0;
  103. protected ProtectRecord protect = null;
  104. protected PageBreakRecord rowBreaks = null;
  105. protected PageBreakRecord colBreaks = null;
  106. protected ObjectProtectRecord objprotect = null;
  107. protected ScenarioProtectRecord scenprotect = null;
  108. protected PasswordRecord password = null;
  109. public static final byte PANE_LOWER_RIGHT = (byte)0;
  110. public static final byte PANE_UPPER_RIGHT = (byte)1;
  111. public static final byte PANE_LOWER_LEFT = (byte)2;
  112. public static final byte PANE_UPPER_LEFT = (byte)3;
  113. /**
  114. * Creates new Sheet with no intialization --useless at this point
  115. * @see #createSheet(List,int,int)
  116. */
  117. public Sheet()
  118. {
  119. }
  120. /**
  121. * read support (offset used as starting point for search) for low level
  122. * API. Pass in an array of Record objects, the sheet number (0 based) and
  123. * a record offset (should be the location of the sheets BOF record). A Sheet
  124. * object is constructed and passed back with all of its initialization set
  125. * to the passed in records and references to those records held. This function
  126. * is normally called via Workbook.
  127. *
  128. * @param recs array containing those records in the sheet in sequence (normally obtained from RecordFactory)
  129. * @param sheetnum integer specifying the sheet's number (0,1 or 2 in this release)
  130. * @param offset of the sheet's BOF record
  131. *
  132. * @return Sheet object with all values set to those read from the file
  133. *
  134. * @see loci.poi.hssf.model.Workbook
  135. * @see loci.poi.hssf.record.Record
  136. */
  137. public static Sheet createSheet(List recs, int sheetnum, int offset)
  138. {
  139. if (log.check( POILogger.DEBUG ))
  140. log.logFormatted(POILogger.DEBUG,
  141. "Sheet createSheet (existing file) with %",
  142. new Integer(recs.size()));
  143. Sheet retval = new Sheet();
  144. ArrayList records = new ArrayList(recs.size() / 5);
  145. boolean isfirstcell = true;
  146. boolean isfirstrow = true;
  147. int bofEofNestingLevel = 0;
  148. for (int k = offset; k < recs.size(); k++)
  149. {
  150. Record rec = ( Record ) recs.get(k);
  151. if (rec.getSid() == BOFRecord.sid)
  152. {
  153. bofEofNestingLevel++;
  154. if (log.check( POILogger.DEBUG ))
  155. log.log(POILogger.DEBUG, "Hit BOF record. Nesting increased to " + bofEofNestingLevel);
  156. }
  157. else if (rec.getSid() == EOFRecord.sid)
  158. {
  159. --bofEofNestingLevel;
  160. if (log.check( POILogger.DEBUG ))
  161. log.log(POILogger.DEBUG, "Hit EOF record. Nesting decreased to " + bofEofNestingLevel);
  162. if (bofEofNestingLevel == 0) {
  163. records.add(rec);
  164. retval.eofLoc = k;
  165. break;
  166. }
  167. }
  168. else if (rec.getSid() == DimensionsRecord.sid)
  169. {
  170. // Make a columns aggregate if one hasn't ready been created.
  171. if (retval.columns == null)
  172. {
  173. retval.columns = new ColumnInfoRecordsAggregate();
  174. records.add(retval.columns);
  175. }
  176. retval.dims = ( DimensionsRecord ) rec;
  177. retval.dimsloc = records.size();
  178. }
  179. else if (rec.getSid() == MergeCellsRecord.sid)
  180. {
  181. retval.mergedRecords.add(rec);
  182. retval.merged = ( MergeCellsRecord ) rec;
  183. retval.numMergedRegions += retval.merged.getNumAreas();
  184. }
  185. else if (rec.getSid() == ColumnInfoRecord.sid)
  186. {
  187. ColumnInfoRecord col = (ColumnInfoRecord)rec;
  188. if (retval.columns != null)
  189. {
  190. rec = null; //only add the aggregate once
  191. }
  192. else
  193. {
  194. rec = retval.columns = new ColumnInfoRecordsAggregate();
  195. }
  196. retval.columns.insertColumn(col);
  197. }
  198. else if (rec.getSid() == DefaultColWidthRecord.sid)
  199. {
  200. retval.defaultcolwidth = ( DefaultColWidthRecord ) rec;
  201. }
  202. else if (rec.getSid() == DefaultRowHeightRecord.sid)
  203. {
  204. retval.defaultrowheight = ( DefaultRowHeightRecord ) rec;
  205. }
  206. else if ( rec.isValue() && bofEofNestingLevel == 1 )
  207. {
  208. if ( isfirstcell )
  209. {
  210. retval.cells = new ValueRecordsAggregate();
  211. rec = retval.cells;
  212. retval.cells.construct( k, recs );
  213. isfirstcell = false;
  214. }
  215. else
  216. {
  217. rec = null;
  218. }
  219. }
  220. else if ( rec.getSid() == StringRecord.sid )
  221. {
  222. rec = null;
  223. }
  224. else if ( rec.getSid() == RowRecord.sid )
  225. {
  226. RowRecord row = (RowRecord)rec;
  227. if (!isfirstrow) rec = null; //only add the aggregate once
  228. if ( isfirstrow )
  229. {
  230. retval.rows = new RowRecordsAggregate();
  231. rec = retval.rows;
  232. isfirstrow = false;
  233. }
  234. retval.rows.insertRow(row);
  235. }
  236. else if ( rec.getSid() == PrintGridlinesRecord.sid )
  237. {
  238. retval.printGridlines = (PrintGridlinesRecord) rec;
  239. }
  240. else if ( rec.getSid() == GridsetRecord.sid )
  241. {
  242. retval.gridset = (GridsetRecord) rec;
  243. }
  244. else if ( rec.getSid() == HeaderRecord.sid && bofEofNestingLevel == 1)
  245. {
  246. retval.header = (HeaderRecord) rec;
  247. }
  248. else if ( rec.getSid() == FooterRecord.sid && bofEofNestingLevel == 1)
  249. {
  250. retval.footer = (FooterRecord) rec;
  251. }
  252. else if ( rec.getSid() == PrintSetupRecord.sid && bofEofNestingLevel == 1)
  253. {
  254. retval.printSetup = (PrintSetupRecord) rec;
  255. }
  256. else if ( rec.getSid() == LeftMarginRecord.sid)
  257. {
  258. retval.getMargins()[LeftMargin] = (LeftMarginRecord) rec;
  259. }
  260. else if ( rec.getSid() == RightMarginRecord.sid)
  261. {
  262. retval.getMargins()[RightMargin] = (RightMarginRecord) rec;
  263. }
  264. else if ( rec.getSid() == TopMarginRecord.sid)
  265. {
  266. retval.getMargins()[TopMargin] = (TopMarginRecord) rec;
  267. }
  268. else if ( rec.getSid() == BottomMarginRecord.sid)
  269. {
  270. retval.getMargins()[BottomMargin] = (BottomMarginRecord) rec;
  271. }
  272. else if ( rec.getSid() == SelectionRecord.sid )
  273. {
  274. retval.selection = (SelectionRecord) rec;
  275. }
  276. else if ( rec.getSid() == WindowTwoRecord.sid )
  277. {
  278. retval.windowTwo = (WindowTwoRecord) rec;
  279. }
  280. else if ( rec.getSid() == DBCellRecord.sid )
  281. {
  282. rec = null;
  283. }
  284. else if ( rec.getSid() == IndexRecord.sid )
  285. {
  286. rec = null;
  287. }
  288. else if ( rec.getSid() == ProtectRecord.sid )
  289. {
  290. retval.protect = (ProtectRecord) rec;
  291. }
  292. else if ( rec.getSid() == ObjectProtectRecord.sid )
  293. {
  294. retval.objprotect = (ObjectProtectRecord) rec;
  295. }
  296. else if ( rec.getSid() == ScenarioProtectRecord.sid )
  297. {
  298. retval.scenprotect = (ScenarioProtectRecord) rec;
  299. }
  300. else if ( rec.getSid() == PasswordRecord.sid )
  301. {
  302. retval.password = (PasswordRecord) rec;
  303. }
  304. else if (rec.getSid() == PageBreakRecord.HORIZONTAL_SID)
  305. {
  306. retval.rowBreaks = (PageBreakRecord)rec;
  307. }
  308. else if (rec.getSid() == PageBreakRecord.VERTICAL_SID)
  309. {
  310. retval.colBreaks = (PageBreakRecord)rec;
  311. }
  312. if (rec != null)
  313. {
  314. records.add(rec);
  315. }
  316. }
  317. retval.records = records;
  318. // if (retval.rows == null)
  319. // {
  320. // retval.rows = new RowRecordsAggregate();
  321. // }
  322. retval.checkCells();
  323. retval.checkRows();
  324. // if (retval.cells == null)
  325. // {
  326. // retval.cells = new ValueRecordsAggregate();
  327. // }
  328. if (log.check( POILogger.DEBUG ))
  329. log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited");
  330. return retval;
  331. }
  332. /**
  333. * Clones the low level records of this sheet and returns the new sheet instance.
  334. * This method is implemented by adding methods for deep cloning to all records that
  335. * can be added to a sheet. The <b>Record</b> object does not implement cloneable.
  336. * When adding a new record, implement a public clone method if and only if the record
  337. * belongs to a sheet.
  338. */
  339. public Sheet cloneSheet()
  340. {
  341. ArrayList clonedRecords = new ArrayList(this.records.size());
  342. for (int i=0; i<this.records.size();i++) {
  343. Record rec = (Record)((Record)this.records.get(i)).clone();
  344. //Need to pull out the Row record and the Value records from their
  345. //Aggregates.
  346. //This is probably the best way to do it since we probably dont want the createSheet
  347. //To cater for these artificial Record types
  348. if (rec instanceof RowRecordsAggregate) {
  349. RowRecordsAggregate rrAgg = (RowRecordsAggregate)rec;
  350. for (Iterator rowIter = rrAgg.getIterator();rowIter.hasNext();) {
  351. Record rowRec = (Record)rowIter.next();
  352. clonedRecords.add(rowRec);
  353. }
  354. } else if (rec instanceof ValueRecordsAggregate) {
  355. ValueRecordsAggregate vrAgg = (ValueRecordsAggregate)rec;
  356. for (Iterator cellIter = vrAgg.getIterator();cellIter.hasNext();) {
  357. Record valRec = (Record)cellIter.next();
  358. if (valRec instanceof FormulaRecordAggregate) {
  359. FormulaRecordAggregate fmAgg = (FormulaRecordAggregate)valRec;
  360. Record fmAggRec = fmAgg.getFormulaRecord();
  361. if (fmAggRec != null)
  362. clonedRecords.add(fmAggRec);
  363. fmAggRec = fmAgg.getStringRecord();
  364. if (fmAggRec != null)
  365. clonedRecords.add(fmAggRec);
  366. } else {
  367. clonedRecords.add(valRec);
  368. }
  369. }
  370. } else if (rec instanceof FormulaRecordAggregate) { //Is this required now??
  371. FormulaRecordAggregate fmAgg = (FormulaRecordAggregate)rec;
  372. Record fmAggRec = fmAgg.getFormulaRecord();
  373. if (fmAggRec != null)
  374. clonedRecords.add(fmAggRec);
  375. fmAggRec = fmAgg.getStringRecord();
  376. if (fmAggRec != null)
  377. clonedRecords.add(fmAggRec);
  378. } else {
  379. clonedRecords.add(rec);
  380. }
  381. }
  382. return createSheet(clonedRecords, 0, 0);
  383. }
  384. /**
  385. * read support (offset = 0) Same as createSheet(Record[] recs, int, int)
  386. * only the record offset is assumed to be 0.
  387. *
  388. * @param records array containing those records in the sheet in sequence (normally obtained from RecordFactory)
  389. * @param sheetnum integer specifying the sheet's number (0,1 or 2 in this release)
  390. * @return Sheet object
  391. */
  392. public static Sheet createSheet(List records, int sheetnum)
  393. {
  394. if (log.check( POILogger.DEBUG ))
  395. log.log(POILogger.DEBUG,
  396. "Sheet createSheet (exisiting file) assumed offset 0");
  397. return createSheet(records, sheetnum, 0);
  398. }
  399. /**
  400. * Creates a sheet with all the usual records minus values and the "index"
  401. * record (not required). Sets the location pointer to where the first value
  402. * records should go. Use this to create a sheet from "scratch".
  403. *
  404. * @return Sheet object with all values set to defaults
  405. */
  406. public static Sheet createSheet()
  407. {
  408. if (log.check( POILogger.DEBUG ))
  409. log.log(POILogger.DEBUG, "Sheet createsheet from scratch called");
  410. Sheet retval = new Sheet();
  411. ArrayList records = new ArrayList(30);
  412. records.add(retval.createBOF());
  413. // records.add(retval.createIndex());
  414. records.add(retval.createCalcMode());
  415. records.add(retval.createCalcCount() );
  416. records.add( retval.createRefMode() );
  417. records.add( retval.createIteration() );
  418. records.add( retval.createDelta() );
  419. records.add( retval.createSaveRecalc() );
  420. records.add( retval.createPrintHeaders() );
  421. retval.printGridlines = (PrintGridlinesRecord) retval.createPrintGridlines();
  422. records.add( retval.printGridlines );
  423. retval.gridset = (GridsetRecord) retval.createGridset();
  424. records.add( retval.gridset );
  425. records.add( retval.createGuts() );
  426. retval.defaultrowheight =
  427. (DefaultRowHeightRecord) retval.createDefaultRowHeight();
  428. records.add( retval.defaultrowheight );
  429. records.add( retval.createWSBool() );
  430. retval.rowBreaks = new PageBreakRecord(PageBreakRecord.HORIZONTAL_SID);
  431. records.add(retval.rowBreaks);
  432. retval.colBreaks = new PageBreakRecord(PageBreakRecord.VERTICAL_SID);
  433. records.add(retval.colBreaks);
  434. retval.header = (HeaderRecord) retval.createHeader();
  435. records.add( retval.header );
  436. retval.footer = (FooterRecord) retval.createFooter();
  437. records.add( retval.footer );
  438. records.add( retval.createHCenter() );
  439. records.add( retval.createVCenter() );
  440. retval.printSetup = (PrintSetupRecord) retval.createPrintSetup();
  441. records.add( retval.printSetup );
  442. retval.defaultcolwidth =
  443. (DefaultColWidthRecord) retval.createDefaultColWidth();
  444. records.add( retval.defaultcolwidth);
  445. ColumnInfoRecordsAggregate columns = new ColumnInfoRecordsAggregate();
  446. records.add( columns );
  447. retval.columns = columns;
  448. retval.dims = ( DimensionsRecord ) retval.createDimensions();
  449. records.add(retval.dims);
  450. retval.dimsloc = records.size()-1;
  451. records.add(retval.windowTwo = retval.createWindowTwo());
  452. retval.setLoc(records.size() - 1);
  453. retval.selection =
  454. (SelectionRecord) retval.createSelection();
  455. records.add(retval.selection);
  456. retval.protect = (ProtectRecord) retval.createProtect();
  457. records.add(retval.protect);
  458. records.add(retval.createEOF());
  459. retval.records = records;
  460. if (log.check( POILogger.DEBUG ))
  461. log.log(POILogger.DEBUG, "Sheet createsheet from scratch exit");
  462. return retval;
  463. }
  464. private void checkCells()
  465. {
  466. if (cells == null)
  467. {
  468. cells = new ValueRecordsAggregate();
  469. records.add(getDimsLoc() + 1, cells);
  470. }
  471. }
  472. private void checkRows()
  473. {
  474. if (rows == null)
  475. {
  476. rows = new RowRecordsAggregate();
  477. records.add(getDimsLoc() + 1, rows);
  478. }
  479. }
  480. //public int addMergedRegion(short rowFrom, short colFrom, short rowTo,
  481. public int addMergedRegion(int rowFrom, short colFrom, int rowTo,
  482. short colTo)
  483. {
  484. if (merged == null || merged.getNumAreas() == 1027)
  485. {
  486. merged = ( MergeCellsRecord ) createMergedCells();
  487. mergedRecords.add(merged);
  488. records.add(records.size() - 1, merged);
  489. }
  490. merged.addArea(rowFrom, colFrom, rowTo, colTo);
  491. return numMergedRegions++;
  492. }
  493. public void removeMergedRegion(int index)
  494. {
  495. //safety checks
  496. if (index >= numMergedRegions || mergedRecords.size() == 0)
  497. return;
  498. int pos = 0;
  499. int startNumRegions = 0;
  500. //optimisation for current record
  501. if (numMergedRegions - index < merged.getNumAreas())
  502. {
  503. pos = mergedRecords.size() - 1;
  504. startNumRegions = numMergedRegions - merged.getNumAreas();
  505. }
  506. else
  507. {
  508. for (int n = 0; n < mergedRecords.size(); n++)
  509. {
  510. MergeCellsRecord record = (MergeCellsRecord) mergedRecords.get(n);
  511. if (startNumRegions + record.getNumAreas() > index)
  512. {
  513. pos = n;
  514. break;
  515. }
  516. startNumRegions += record.getNumAreas();
  517. }
  518. }
  519. MergeCellsRecord rec = (MergeCellsRecord) mergedRecords.get(pos);
  520. rec.removeAreaAt(index - startNumRegions);
  521. numMergedRegions--;
  522. if (rec.getNumAreas() == 0)
  523. {
  524. mergedRecords.remove(pos);
  525. //get rid of the record from the sheet
  526. records.remove(merged);
  527. if (merged == rec) {
  528. //pull up the LAST record for operations when we finally
  529. //support continue records for mergedRegions
  530. if (mergedRecords.size() > 0) {
  531. merged = (MergeCellsRecord) mergedRecords.get(mergedRecords.size() - 1);
  532. } else {
  533. merged = null;
  534. }
  535. }
  536. }
  537. }
  538. public MergeCellsRecord.MergedRegion getMergedRegionAt(int index)
  539. {
  540. //safety checks
  541. if (index >= numMergedRegions || mergedRecords.size() == 0)
  542. return null;
  543. int pos = 0;
  544. int startNumRegions = 0;
  545. //optimisation for current record
  546. if (numMergedRegions - index < merged.getNumAreas())
  547. {
  548. pos = mergedRecords.size() - 1;
  549. startNumRegions = numMergedRegions - merged.getNumAreas();
  550. }
  551. else
  552. {
  553. for (int n = 0; n < mergedRecords.size(); n++)
  554. {
  555. MergeCellsRecord record = (MergeCellsRecord) mergedRecords.get(n);
  556. if (startNumRegions + record.getNumAreas() > index)
  557. {
  558. pos = n;
  559. break;
  560. }
  561. startNumRegions += record.getNumAreas();
  562. }
  563. }
  564. return ((MergeCellsRecord) mergedRecords.get(pos)).getAreaAt(index - startNumRegions);
  565. }
  566. public int getNumMergedRegions()
  567. {
  568. return numMergedRegions;
  569. }
  570. /**
  571. * Returns the number of low level binary records in this sheet. This adjusts things for the so called
  572. * AgregateRecords.
  573. *
  574. * @see loci.poi.hssf.record.Record
  575. */
  576. public int getNumRecords()
  577. {
  578. checkCells();
  579. checkRows();
  580. if (log.check( POILogger.DEBUG ))
  581. {
  582. log.log(POILogger.DEBUG, "Sheet.getNumRecords");
  583. log.logFormatted(POILogger.DEBUG, "returning % + % + % - 2 = %", new int[]
  584. {
  585. records.size(), cells.getPhysicalNumberOfCells(),
  586. rows.getPhysicalNumberOfRows(),
  587. records.size() + cells.getPhysicalNumberOfCells()
  588. + rows.getPhysicalNumberOfRows() - 2
  589. });
  590. }
  591. return records.size() + cells.getPhysicalNumberOfCells()
  592. + rows.getPhysicalNumberOfRows() - 2;
  593. }
  594. /**
  595. * Per an earlier reported bug in working with Andy Khan's excel read library. This
  596. * sets the values in the sheet's DimensionsRecord object to be correct. Excel doesn't
  597. * really care, but we want to play nice with other libraries.
  598. *
  599. * @see loci.poi.hssf.record.DimensionsRecord
  600. */
  601. //public void setDimensions(short firstrow, short firstcol, short lastrow,
  602. public void setDimensions(int firstrow, short firstcol, int lastrow,
  603. short lastcol)
  604. {
  605. if (log.check( POILogger.DEBUG ))
  606. {
  607. log.log(POILogger.DEBUG, "Sheet.setDimensions");
  608. log.log(POILogger.DEBUG,
  609. (new StringBuffer("firstrow")).append(firstrow)
  610. .append("firstcol").append(firstcol).append("lastrow")
  611. .append(lastrow).append("lastcol").append(lastcol)
  612. .toString());
  613. }
  614. dims.setFirstCol(firstcol);
  615. dims.setFirstRow(firstrow);
  616. dims.setLastCol(lastcol);
  617. dims.setLastRow(lastrow);
  618. if (log.check( POILogger.DEBUG ))
  619. log.log(POILogger.DEBUG, "Sheet.setDimensions exiting");
  620. }
  621. /**
  622. * set the locator for where we should look for the next value record. The
  623. * algorythm will actually start here and find the correct location so you
  624. * can set this to 0 and watch performance go down the tubes but it will work.
  625. * After a value is set this is automatically advanced. Its also set by the
  626. * create method. So you probably shouldn't mess with this unless you have
  627. * a compelling reason why or the help for the method you're calling says so.
  628. * Check the other methods for whether they care about
  629. * the loc pointer. Many of the "modify" and "remove" methods re-initialize this
  630. * to "dimsloc" which is the location of the Dimensions Record and presumably the
  631. * start of the value section (at or around 19 dec).
  632. *
  633. * @param loc the record number to start at
  634. *
  635. */
  636. public void setLoc(int loc)
  637. {
  638. valueRecIterator = null;
  639. if (log.check( POILogger.DEBUG ))
  640. log.log(POILogger.DEBUG, "sheet.setLoc(): " + loc);
  641. this.loc = loc;
  642. }
  643. /**
  644. * Returns the location pointer to the first record to look for when adding rows/values
  645. *
  646. */
  647. public int getLoc()
  648. {
  649. if (log.check( POILogger.DEBUG ))
  650. log.log(POILogger.DEBUG, "sheet.getLoc():" + loc);
  651. return loc;
  652. }
  653. /**
  654. * Set the preoffset when using DBCELL records (currently unused) - this is
  655. * the position of this sheet within the whole file.
  656. *
  657. * @param offset the offset of the sheet's BOF within the file.
  658. */
  659. public void setPreOffset(int offset)
  660. {
  661. this.preoffset = offset;
  662. }
  663. /**
  664. * get the preoffset when using DBCELL records (currently unused) - this is
  665. * the position of this sheet within the whole file.
  666. *
  667. * @return offset the offset of the sheet's BOF within the file.
  668. */
  669. public int getPreOffset()
  670. {
  671. return preoffset;
  672. }
  673. /**
  674. * Serializes all records in the sheet into one big byte array. Use this to write
  675. * the sheet out.
  676. *
  677. * @param offset to begin write at
  678. * @param data array containing the binary representation of the records in this sheet
  679. *
  680. */
  681. public int serialize(int offset, byte [] data)
  682. {
  683. if (log.check( POILogger.DEBUG ))
  684. log.log(POILogger.DEBUG, "Sheet.serialize using offsets");
  685. int pos = offset;
  686. boolean haveSerializedIndex = false;
  687. for (int k = 0; k < records.size(); k++)
  688. {
  689. Record record = (( Record ) records.get(k));
  690. //Once the rows have been found in the list of records, start
  691. //writing out the blocked row information. This includes the DBCell references
  692. if (record instanceof RowRecordsAggregate) {
  693. pos += ((RowRecordsAggregate)record).serialize(pos, data, cells); // rec.length;
  694. } else if (record instanceof ValueRecordsAggregate) {
  695. //Do nothing here. The records were serialized during the RowRecordAggregate block serialization
  696. } else {
  697. pos += record.serialize(pos, data ); // rec.length;
  698. }
  699. //If the BOF record was just serialized then add the IndexRecord
  700. if (record.getSid() == BOFRecord.sid) {
  701. //Can there be more than one BOF for a sheet? If not then we can
  702. //remove this guard. So be safe it is left here.
  703. if (rows != null && !haveSerializedIndex) {
  704. haveSerializedIndex = true;
  705. pos += serializeIndexRecord(k, pos, data);
  706. }
  707. }
  708. //// uncomment to test record sizes ////
  709. // System.out.println( record.getClass().getName() );
  710. // byte[] data2 = new byte[record.getRecordSize()];
  711. // record.serialize(0, data2 ); // rec.length;
  712. // if (LittleEndian.getUShort(data2, 2) != record.getRecordSize() - 4
  713. // && record instanceof RowRecordsAggregate == false
  714. // && record instanceof ValueRecordsAggregate == false
  715. // && record instanceof EscherAggregate == false)
  716. // {
  717. // throw new RuntimeException("Blah!!! Size off by " + ( LittleEndian.getUShort(data2, 2) - record.getRecordSize() - 4) + " records.");
  718. // }
  719. //asd: int len = record.serialize(pos + offset, data );
  720. ///// DEBUG BEGIN /////
  721. //asd: if (len != record.getRecordSize())
  722. //asd: throw new IllegalStateException("Record size does not match serialized bytes. Serialized size = " + len + " but getRecordSize() returns " + record.getRecordSize() + ". Record object is " + record.getClass());
  723. ///// DEBUG END /////
  724. //asd: pos += len; // rec.length;
  725. }
  726. if (log.check( POILogger.DEBUG ))
  727. log.log(POILogger.DEBUG, "Sheet.serialize returning ");
  728. return pos-offset;
  729. }
  730. private int serializeIndexRecord(final int BOFRecordIndex, final int offset, byte[] data) {
  731. IndexRecord index = new IndexRecord();
  732. index.setFirstRow(rows.getFirstRowNum());
  733. index.setLastRowAdd1(rows.getLastRowNum()+1);
  734. //Calculate the size of the records from the end of the BOF
  735. //and up to the RowRecordsAggregate...
  736. int sheetRecSize = 0;
  737. for (int j = BOFRecordIndex+1; j < records.size(); j++)
  738. {
  739. Record tmpRec = (( Record ) records.get(j));
  740. if (tmpRec instanceof RowRecordsAggregate)
  741. break;
  742. sheetRecSize+= tmpRec.getRecordSize();
  743. }
  744. //Add the references to the DBCells in the IndexRecord (one for each block)
  745. int blockCount = rows.getRowBlockCount();
  746. //Calculate the size of this IndexRecord
  747. int indexRecSize = IndexRecord.getRecordSizeForBlockCount(blockCount);
  748. int rowBlockOffset = 0;
  749. int cellBlockOffset = 0;
  750. int dbCellOffset = 0;
  751. for (int block=0;block<blockCount;block++) {
  752. rowBlockOffset += rows.getRowBlockSize(block);
  753. cellBlockOffset += null == cells ? 0 : cells.getRowCellBlockSize(rows.getStartRowNumberForBlock(block),
  754. rows.getEndRowNumberForBlock(block));
  755. //Note: The offsets are relative to the Workbook BOF. Assume that this is
  756. //0 for now.....
  757. index.addDbcell(offset + indexRecSize + sheetRecSize + dbCellOffset + rowBlockOffset + cellBlockOffset);
  758. //Add space required to write the dbcell record(s) (whose references were just added).
  759. dbCellOffset += (8 + (rows.getRowCountForBlock(block) * 2));
  760. }
  761. return index.serialize(offset, data);
  762. }
  763. /**
  764. * Create a row record. (does not add it to the records contained in this sheet)
  765. *
  766. * @param row number
  767. * @return RowRecord created for the passed in row number
  768. * @see loci.poi.hssf.record.RowRecord
  769. */
  770. public RowRecord createRow(int row)
  771. {
  772. return RowRecordsAggregate.createRow( row );
  773. }
  774. /**
  775. * Create a LABELSST Record (does not add it to the records contained in this sheet)
  776. *
  777. * @param row the row the LabelSST is a member of
  778. * @param col the column the LabelSST defines
  779. * @param index the index of the string within the SST (use workbook addSSTString method)
  780. * @return LabelSSTRecord newly created containing your SST Index, row,col.
  781. * @see loci.poi.hssf.record.SSTRecord
  782. */
  783. //public LabelSSTRecord createLabelSST(short row, short col, int index)
  784. public LabelSSTRecord createLabelSST(int row, short col, int index)
  785. {
  786. log.logFormatted(POILogger.DEBUG, "create labelsst row,col,index %,%,%",
  787. new int[]
  788. {
  789. row, col, index
  790. });
  791. LabelSSTRecord rec = new LabelSSTRecord();
  792. rec.setRow(row);
  793. rec.setColumn(col);
  794. rec.setSSTIndex(index);
  795. rec.setXFIndex(( short ) 0x0f);
  796. return rec;
  797. }
  798. /**
  799. * Create a NUMBER Record (does not add it to the records contained in this sheet)
  800. *
  801. * @param row the row the NumberRecord is a member of
  802. * @param col the column the NumberRecord defines
  803. * @param value for the number record
  804. *
  805. * @return NumberRecord for that row, col containing that value as added to the sheet
  806. */
  807. //public NumberRecord createNumber(short row, short col, double value)
  808. public NumberRecord createNumber(int row, short col, double value)
  809. {
  810. log.logFormatted(POILogger.DEBUG, "create number row,col,value %,%,%",
  811. new double[]
  812. {
  813. row, col, value
  814. });
  815. NumberRecord rec = new NumberRecord();
  816. //rec.setRow(( short ) row);
  817. rec.setRow(row);
  818. rec.setColumn(col);
  819. rec.setValue(value);
  820. rec.setXFIndex(( short ) 0x0f);
  821. return rec;
  822. }
  823. /**
  824. * create a BLANK record (does not add it to the records contained in this sheet)
  825. *
  826. * @param row - the row the BlankRecord is a member of
  827. * @param col - the column the BlankRecord is a member of
  828. */
  829. //public BlankRecord createBlank(short row, short col)
  830. public BlankRecord createBlank(int row, short col)
  831. {
  832. //log.logFormatted(POILogger.DEBUG, "create blank row,col %,%", new short[]
  833. log.logFormatted(POILogger.DEBUG, "create blank row,col %,%", new int[]
  834. {
  835. row, col
  836. });
  837. BlankRecord rec = new BlankRecord();
  838. //rec.setRow(( short ) row);
  839. rec.setRow(row);
  840. rec.setColumn(col);
  841. rec.setXFIndex(( short ) 0x0f);
  842. return rec;
  843. }
  844. /**
  845. * Attempts to parse the formula into PTGs and create a formula record
  846. * DOES NOT WORK YET
  847. *
  848. * @param row - the row for the formula record
  849. * @param col - the column of the formula record
  850. * @param formula - a String representing the formula. To be parsed to PTGs
  851. * @return bogus/useless formula record
  852. */
  853. //public FormulaRecord createFormula(short row, short col, String formula)
  854. public FormulaRecord createFormula(int row, short col, String formula)
  855. {
  856. log.logFormatted(POILogger.DEBUG, "create formula row,col,formula %,%,%",
  857. //new short[]
  858. new int[]
  859. {
  860. row, col
  861. }, formula);
  862. FormulaRecord rec = new FormulaRecord();
  863. rec.setRow(row);
  864. rec.setColumn(col);
  865. rec.setOptions(( short ) 2);
  866. rec.setValue(0);
  867. rec.setXFIndex(( short ) 0x0f);
  868. FormulaParser fp = new FormulaParser(formula,null); //fix - do we need this method?
  869. fp.parse();
  870. Ptg[] ptg = fp.getRPNPtg();
  871. int size = 0;
  872. for (int k = 0; k < ptg.length; k++)
  873. {
  874. size += ptg[ k ].getSize();
  875. rec.pushExpressionToken(ptg[ k ]);
  876. }
  877. rec.setExpressionLength(( short ) size);
  878. return rec;
  879. }
  880. /**
  881. * Adds a value record to the sheet's contained binary records
  882. * (i.e. LabelSSTRecord or NumberRecord).
  883. * <P>
  884. * This method is "loc" sensitive. Meaning you need to set LOC to where you
  885. * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
  886. * When adding several rows you can just start at the last one by leaving loc
  887. * at what this sets it to.
  888. *
  889. * @param row the row to add the cell value to
  890. * @param col the cell value record itself.
  891. */
  892. //public void addValueRecord(short row, CellValueRecordInterface col)
  893. public void addValueRecord(int row, CellValueRecordInterface col)
  894. {
  895. checkCells();
  896. if(log.check(POILogger.DEBUG))
  897. {
  898. log.logFormatted(POILogger.DEBUG, "add value record row,loc %,%", new int[]
  899. {
  900. row, loc
  901. });
  902. }
  903. DimensionsRecord d = ( DimensionsRecord ) records.get(getDimsLoc());
  904. if (col.getColumn() > d.getLastCol())
  905. {
  906. d.setLastCol(( short ) (col.getColumn() + 1));
  907. }
  908. if (col.getColumn() < d.getFirstCol())
  909. {
  910. d.setFirstCol(col.getColumn());
  911. }
  912. cells.insertCell(col);
  913. /*
  914. * for (int k = loc; k < records.size(); k++)
  915. * {
  916. * Record rec = ( Record ) records.get(k);
  917. *
  918. * if (rec.getSid() == RowRecord.sid)
  919. * {
  920. * RowRecord rowrec = ( RowRecord ) rec;
  921. *
  922. * if (rowrec.getRowNumber() == col.getRow())
  923. * {
  924. * records.add(k + 1, col);
  925. * loc = k;
  926. * if (rowrec.getLastCol() <= col.getColumn())
  927. * {
  928. * rowrec.setLastCol((( short ) (col.getColumn() + 1)));
  929. * }
  930. * break;
  931. * }
  932. * }
  933. * }
  934. */
  935. }
  936. /**
  937. * remove a value record from the records array.
  938. *
  939. * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
  940. *
  941. * @param row - the row of the value record you wish to remove
  942. * @param col - a record supporting the CellValueRecordInterface.
  943. * @see loci.poi.hssf.record.CellValueRecordInterface
  944. */
  945. //public void removeValueRecord(short row, CellValueRecordInterface col)
  946. public void removeValueRecord(int row, CellValueRecordInterface col)
  947. {
  948. checkCells();
  949. log.logFormatted(POILogger.DEBUG, "remove value record row,dimsloc %,%",
  950. new int[]{row, dimsloc} );
  951. loc = dimsloc;
  952. cells.removeCell(col);
  953. /*
  954. * for (int k = loc; k < records.size(); k++)
  955. * {
  956. * Record rec = ( Record ) records.get(k);
  957. *
  958. * // checkDimsLoc(rec,k);
  959. * if (rec.isValue())
  960. * {
  961. * CellValueRecordInterface cell =
  962. * ( CellValueRecordInterface ) rec;
  963. *
  964. * if ((cell.getRow() == col.getRow())
  965. * && (cell.getColumn() == col.getColumn()))
  966. * {
  967. * records.remove(k);
  968. * break;
  969. * }
  970. * }
  971. * }
  972. */
  973. }
  974. /**
  975. * replace a value record from the records array.
  976. *
  977. * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
  978. *
  979. * @param newval - a record supporting the CellValueRecordInterface. this will replace
  980. * the cell value with the same row and column. If there isn't one, one will
  981. * be added.
  982. */
  983. public void replaceValueRecord(CellValueRecordInterface newval)
  984. {
  985. checkCells();
  986. setLoc(dimsloc);
  987. if (log.check( POILogger.DEBUG ))
  988. log.log(POILogger.DEBUG, "replaceValueRecord ");
  989. //The ValueRecordsAggregate use a tree map underneath.
  990. //The tree Map uses the CellValueRecordInterface as both the
  991. //key and the value, if we dont do a remove, then
  992. //the previous instance of the key is retained, effectively using
  993. //double the memory
  994. cells.removeCell(newval);
  995. cells.insertCell(newval);
  996. /*
  997. * CellValueRecordInterface oldval = getNextValueRecord();
  998. *
  999. * while (oldval != null)
  1000. * {
  1001. * if (oldval.isEqual(newval))
  1002. * {
  1003. * records.set(( short ) (getLoc() - 1), newval);
  1004. * return;
  1005. * }
  1006. * oldval = getNextValueRecord();
  1007. * }
  1008. * addValueRecord(newval.getRow(), newval);
  1009. * setLoc(dimsloc);
  1010. */
  1011. }
  1012. /**
  1013. * Adds a row record to the sheet
  1014. *
  1015. * <P>
  1016. * This method is "loc" sensitive. Meaning you need to set LOC to where you
  1017. * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
  1018. * When adding several rows you can just start at the last one by leaving loc
  1019. * at what this sets it to.
  1020. *
  1021. * @param row the row record to be added
  1022. * @see #setLoc(int)
  1023. */
  1024. public void addRow(RowRecord row)
  1025. {
  1026. checkRows();
  1027. if (log.check( POILogger.DEBUG ))
  1028. log.log(POILogger.DEBUG, "addRow ");
  1029. DimensionsRecord d = ( DimensionsRecord ) records.get(getDimsLoc());
  1030. if (row.getRowNumber() >= d.getLastRow())
  1031. {
  1032. d.setLastRow(row.getRowNumber() + 1);
  1033. }
  1034. if (row.getRowNumber() < d.getFirstRow())
  1035. {
  1036. d.setFirstRow(row.getRowNumber());
  1037. }
  1038. //IndexRecord index = null;
  1039. //If the row exists remove it, so that any cells attached to the row are removed
  1040. RowRecord existingRow = rows.getRow(row.getRowNumber());
  1041. if (existingRow != null)
  1042. rows.removeRow(existingRow);
  1043. rows.insertRow(row);
  1044. /*
  1045. * for (int k = loc; k < records.size(); k++)
  1046. * {
  1047. * Record rec = ( Record ) records.get(k);
  1048. *
  1049. * if (rec.getSid() == IndexRecord.sid)
  1050. * {
  1051. * index = ( IndexRecord ) rec;
  1052. * }
  1053. * if (rec.getSid() == RowRecord.sid)
  1054. * {
  1055. * RowRecord rowrec = ( RowRecord ) rec;
  1056. *
  1057. * if (rowrec.getRowNumber() > row.getRowNumber())
  1058. * {
  1059. * records.add(k, row);
  1060. * loc = k;
  1061. * break;
  1062. * }
  1063. * }
  1064. * if (rec.getSid() == WindowTwoRecord.sid)
  1065. * {
  1066. * records.add(k, row);
  1067. * loc = k;
  1068. * break;
  1069. * }
  1070. * }
  1071. * if (index != null)
  1072. * {
  1073. * if (index.getLastRowAdd1() <= row.getRowNumber())
  1074. * {
  1075. * index.setLastRowAdd1(row.getRowNumber() + 1);
  1076. * }
  1077. * }
  1078. */
  1079. if (log.check( POILogger.DEBUG ))
  1080. log.log(POILogger.DEBUG, "exit addRow");
  1081. }
  1082. /**
  1083. * Removes a row record
  1084. *
  1085. * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
  1086. *
  1087. * @param row the row record to remove
  1088. */
  1089. public void removeRow(RowRecord row)
  1090. {
  1091. checkRows();
  1092. // IndexRecord index = null;
  1093. setLoc(getDimsLoc());
  1094. rows.removeRow(row);
  1095. /*
  1096. * for (int k = loc; k < records.size(); k++)
  1097. * {
  1098. * Record rec = ( Record ) records.get(k);
  1099. *
  1100. * // checkDimsLoc(rec,k);
  1101. * if (rec.getSid() == RowRecord.sid)
  1102. * {
  1103. * RowRecord rowrec = ( RowRecord ) rec;
  1104. *
  1105. * if (rowrec.getRowNumber() == row.getRowNumber())
  1106. * {
  1107. * records.remove(k);
  1108. * break;
  1109. * }
  1110. * }
  1111. * if (rec.getSid() == WindowTwoRecord.sid)
  1112. * {
  1113. * break;
  1114. * }
  1115. * }
  1116. */
  1117. }
  1118. /**
  1119. * get the NEXT value record (from LOC). The first record that is a value record
  1120. * (starting at LOC) will be returned.
  1121. *
  1122. * <P>
  1123. * This method is "loc" sensitive. Meaning you need to set LOC to where you
  1124. * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
  1125. * When adding several rows you can just start at the last one by leaving loc
  1126. * at what this sets it to. For this method, set loc to dimsloc to start with,
  1127. * subsequent calls will return values in (physical) sequence or NULL when you get to the end.
  1128. *
  1129. * @return CellValueRecordInterface representing the next value record or NULL if there are no more
  1130. * @see #setLoc(int)
  1131. */
  1132. public CellValueRecordInterface getNextValueRecord()
  1133. {
  1134. if (log.check( POILogger.DEBUG ))
  1135. log.log(POILogger.DEBUG, "getNextValue loc= " + loc);
  1136. if (valueRecIterator == null)
  1137. {
  1138. valueRecIterator = cells.getIterator();
  1139. }
  1140. if (!valueRecIterator.hasNext())
  1141. {
  1142. return null;
  1143. }
  1144. return ( CellValueRecordInterface ) valueRecIterator.next();
  1145. /*
  1146. * if (this.getLoc() < records.size())
  1147. * {
  1148. * for (int k = getLoc(); k < records.size(); k++)
  1149. * {
  1150. * Record rec = ( Record ) records.get(k);
  1151. *
  1152. * this.setLoc(k + 1);
  1153. * if (rec instanceof CellValueRecordInterface)
  1154. * {
  1155. * return ( CellValueRecordInterface ) rec;
  1156. * }
  1157. * }
  1158. * }
  1159. * return null;
  1160. */
  1161. }
  1162. /**
  1163. * get the NEXT RowRecord or CellValueRecord(from LOC). The first record that
  1164. * is a Row record or CellValueRecord(starting at LOC) will be returned.
  1165. * <P>
  1166. * This method is "loc" sensitive. Meaning you need to set LOC to where you
  1167. * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
  1168. * When adding several rows you can just start at the last one by leaving loc
  1169. * at what this sets it to. For this method, set loc to dimsloc to start with.
  1170. * subsequent calls will return rows in (physical) sequence or NULL when you get to the end.
  1171. *
  1172. * @return RowRecord representing the next row record or CellValueRecordInterface
  1173. * representing the next cellvalue or NULL if there are no more
  1174. * @see #setLoc(int)
  1175. *
  1176. */
  1177. /* public Record getNextRowOrValue()
  1178. {
  1179. POILogger.DEBUG((new StringBuffer("getNextRow loc= ")).append(loc)
  1180. .toString());
  1181. if (this.getLoc() < records.size())
  1182. {
  1183. for (int k = this.getLoc(); k < records.size(); k++)
  1184. {
  1185. Record rec = ( Record ) records.get(k);
  1186. this.setLoc(k + 1);
  1187. if (rec.getSid() == RowRecord.sid)
  1188. {
  1189. return rec;
  1190. }
  1191. else if (rec.isValue())
  1192. {
  1193. return rec;
  1194. }
  1195. }
  1196. }
  1197. return null;
  1198. }
  1199. */
  1200. /**
  1201. * get the NEXT RowRecord (from LOC). The first record that is a Row record
  1202. * (starting at LOC) will be returned.
  1203. * <P>
  1204. * This method is "loc" sensitive. Meaning you need to set LOC to where you
  1205. * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
  1206. * When adding several rows you can just start at the last one by leaving loc
  1207. * at what this sets it to. For this method, set loc to dimsloc to start with.
  1208. * subsequent calls will return rows in (physical) sequence or NULL when you get to the end.
  1209. *
  1210. * @return RowRecord representing the next row record or NULL if there are no more
  1211. * @see #setLoc(int)
  1212. *
  1213. */
  1214. public RowRecord getNextRow()
  1215. {
  1216. if (log.check( POILogger.DEBUG ))
  1217. log.log(POILogger.DEBUG, "getNextRow loc= " + loc);
  1218. if (rowRecIterator == null)
  1219. {
  1220. rowRecIterator = rows.getIterator();
  1221. }
  1222. if (!rowRecIterator.hasNext())
  1223. {
  1224. return null;
  1225. }
  1226. return ( RowRecord ) rowRecIterator.next();
  1227. /* if (this.getLoc() < records.size())
  1228. {…

Large files files are truncated, but you can click here to view the full file