0001: /* ====================================================================
0002: Licensed to the Apache Software Foundation (ASF) under one or more
0003: contributor license agreements. See the NOTICE file distributed with
0004: this work for additional information regarding copyright ownership.
0005: The ASF licenses this file to You under the Apache License, Version 2.0
0006: (the "License"); you may not use this file except in compliance with
0007: the License. You may obtain a copy of the License at
0008:
0009: http://www.apache.org/licenses/LICENSE-2.0
0010:
0011: Unless required by applicable law or agreed to in writing, software
0012: distributed under the License is distributed on an "AS IS" BASIS,
0013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: See the License for the specific language governing permissions and
0015: limitations under the License.
0016: ==================================================================== */
0017:
0018: package org.apache.poi.hssf.model;
0019:
0020: import org.apache.poi.hssf.record.*;
0021: import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
0022: import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
0023: import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
0024: import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
0025: import org.apache.poi.hssf.record.formula.Ptg;
0026: import org.apache.poi.hssf.util.PaneInformation;
0027:
0028: import org.apache.poi.util.POILogFactory;
0029: import org.apache.poi.util.POILogger;
0030:
0031: import java.util.ArrayList;
0032: import java.util.Iterator;
0033: import java.util.List; // normally I don't do this, buy we literally mean ALL
0034:
0035: /**
0036: * Low level model implementation of a Sheet (one workbook contains many sheets)
0037: * This file contains the low level binary records starting at the sheets BOF and
0038: * ending with the sheets EOF. Use HSSFSheet for a high level representation.
0039: * <P>
0040: * The structures of the highlevel API use references to this to perform most of their
0041: * operations. Its probably unwise to use these low level structures directly unless you
0042: * really know what you're doing. I recommend you read the Microsoft Excel 97 Developer's
0043: * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf
0044: * before even attempting to use this.
0045: * <P>
0046: * @author Andrew C. Oliver (acoliver at apache dot org)
0047: * @author Glen Stampoultzis (glens at apache.org)
0048: * @author Shawn Laubach (slaubach at apache dot org) Gridlines, Headers, Footers, PrintSetup, and Setting Default Column Styles
0049: * @author Jason Height (jheight at chariot dot net dot au) Clone support. DBCell & Index Record writing support
0050: * @author Brian Sanders (kestrel at burdell dot org) Active Cell support
0051: * @author Jean-Pierre Paris (jean-pierre.paris at m4x dot org) (Just a little)
0052: *
0053: * @see org.apache.poi.hssf.model.Workbook
0054: * @see org.apache.poi.hssf.usermodel.HSSFSheet
0055: * @version 1.0-pre
0056: */
0057:
0058: public class Sheet implements Model {
0059: public static final short LeftMargin = 0;
0060: public static final short RightMargin = 1;
0061: public static final short TopMargin = 2;
0062: public static final short BottomMargin = 3;
0063:
0064: private static POILogger log = POILogFactory.getLogger(Sheet.class);
0065:
0066: protected ArrayList records = null;
0067: int preoffset = 0; // offset of the sheet in a new file
0068: int loc = 0;
0069: protected int dimsloc = 0;
0070: protected DimensionsRecord dims;
0071: protected DefaultColWidthRecord defaultcolwidth = null;
0072: protected DefaultRowHeightRecord defaultrowheight = null;
0073: protected GridsetRecord gridset = null;
0074: protected PrintSetupRecord printSetup = null;
0075: protected HeaderRecord header = null;
0076: protected FooterRecord footer = null;
0077: protected PrintGridlinesRecord printGridlines = null;
0078: protected WindowTwoRecord windowTwo = null;
0079: protected MergeCellsRecord merged = null;
0080: protected Margin[] margins = null;
0081: protected List mergedRecords = new ArrayList();
0082: protected int numMergedRegions = 0;
0083: protected SelectionRecord selection = null;
0084: protected ColumnInfoRecordsAggregate columns = null;
0085: protected ValueRecordsAggregate cells = null;
0086: protected RowRecordsAggregate rows = null;
0087: private Iterator valueRecIterator = null;
0088: private Iterator rowRecIterator = null;
0089: protected int eofLoc = 0;
0090: protected ProtectRecord protect = null;
0091: protected PageBreakRecord rowBreaks = null;
0092: protected PageBreakRecord colBreaks = null;
0093: protected ObjectProtectRecord objprotect = null;
0094: protected ScenarioProtectRecord scenprotect = null;
0095: protected PasswordRecord password = null;
0096:
0097: public static final byte PANE_LOWER_RIGHT = (byte) 0;
0098: public static final byte PANE_UPPER_RIGHT = (byte) 1;
0099: public static final byte PANE_LOWER_LEFT = (byte) 2;
0100: public static final byte PANE_UPPER_LEFT = (byte) 3;
0101:
0102: /**
0103: * Creates new Sheet with no intialization --useless at this point
0104: * @see #createSheet(List,int,int)
0105: */
0106: public Sheet() {
0107: }
0108:
0109: /**
0110: * read support (offset used as starting point for search) for low level
0111: * API. Pass in an array of Record objects, the sheet number (0 based) and
0112: * a record offset (should be the location of the sheets BOF record). A Sheet
0113: * object is constructed and passed back with all of its initialization set
0114: * to the passed in records and references to those records held. This function
0115: * is normally called via Workbook.
0116: *
0117: * @param recs array containing those records in the sheet in sequence (normally obtained from RecordFactory)
0118: * @param sheetnum integer specifying the sheet's number (0,1 or 2 in this release)
0119: * @param offset of the sheet's BOF record
0120: *
0121: * @return Sheet object with all values set to those read from the file
0122: *
0123: * @see org.apache.poi.hssf.model.Workbook
0124: * @see org.apache.poi.hssf.record.Record
0125: */
0126: public static Sheet createSheet(List recs, int sheetnum, int offset) {
0127: if (log.check(POILogger.DEBUG))
0128: log.logFormatted(POILogger.DEBUG,
0129: "Sheet createSheet (existing file) with %",
0130: new Integer(recs.size()));
0131: Sheet retval = new Sheet();
0132: ArrayList records = new ArrayList(recs.size() / 5);
0133: boolean isfirstcell = true;
0134: boolean isfirstrow = true;
0135: int bofEofNestingLevel = 0;
0136:
0137: for (int k = offset; k < recs.size(); k++) {
0138: Record rec = (Record) recs.get(k);
0139:
0140: if (rec.getSid() == BOFRecord.sid) {
0141: bofEofNestingLevel++;
0142: if (log.check(POILogger.DEBUG))
0143: log.log(POILogger.DEBUG,
0144: "Hit BOF record. Nesting increased to "
0145: + bofEofNestingLevel);
0146: } else if (rec.getSid() == EOFRecord.sid) {
0147: --bofEofNestingLevel;
0148: if (log.check(POILogger.DEBUG))
0149: log.log(POILogger.DEBUG,
0150: "Hit EOF record. Nesting decreased to "
0151: + bofEofNestingLevel);
0152: if (bofEofNestingLevel == 0) {
0153: records.add(rec);
0154: retval.eofLoc = k;
0155: break;
0156: }
0157: } else if (rec.getSid() == DimensionsRecord.sid) {
0158: // Make a columns aggregate if one hasn't ready been created.
0159: if (retval.columns == null) {
0160: retval.columns = new ColumnInfoRecordsAggregate();
0161: records.add(retval.columns);
0162: }
0163:
0164: retval.dims = (DimensionsRecord) rec;
0165: retval.dimsloc = records.size();
0166: } else if (rec.getSid() == MergeCellsRecord.sid) {
0167: retval.mergedRecords.add(rec);
0168: retval.merged = (MergeCellsRecord) rec;
0169: retval.numMergedRegions += retval.merged.getNumAreas();
0170: } else if (rec.getSid() == ColumnInfoRecord.sid) {
0171: ColumnInfoRecord col = (ColumnInfoRecord) rec;
0172: if (retval.columns != null) {
0173: rec = null; //only add the aggregate once
0174: } else {
0175: rec = retval.columns = new ColumnInfoRecordsAggregate();
0176: }
0177: retval.columns.insertColumn(col);
0178: } else if (rec.getSid() == DefaultColWidthRecord.sid) {
0179: retval.defaultcolwidth = (DefaultColWidthRecord) rec;
0180: } else if (rec.getSid() == DefaultRowHeightRecord.sid) {
0181: retval.defaultrowheight = (DefaultRowHeightRecord) rec;
0182: } else if (rec.isValue() && bofEofNestingLevel == 1) {
0183: if (isfirstcell) {
0184: retval.cells = new ValueRecordsAggregate();
0185: rec = retval.cells;
0186: retval.cells.construct(k, recs);
0187: isfirstcell = false;
0188: } else {
0189: rec = null;
0190: }
0191: } else if (rec.getSid() == StringRecord.sid) {
0192: rec = null;
0193: } else if (rec.getSid() == RowRecord.sid) {
0194: RowRecord row = (RowRecord) rec;
0195: if (!isfirstrow)
0196: rec = null; //only add the aggregate once
0197:
0198: if (isfirstrow) {
0199: retval.rows = new RowRecordsAggregate();
0200: rec = retval.rows;
0201: isfirstrow = false;
0202: }
0203: retval.rows.insertRow(row);
0204: } else if (rec.getSid() == PrintGridlinesRecord.sid) {
0205: retval.printGridlines = (PrintGridlinesRecord) rec;
0206: } else if (rec.getSid() == GridsetRecord.sid) {
0207: retval.gridset = (GridsetRecord) rec;
0208: } else if (rec.getSid() == HeaderRecord.sid
0209: && bofEofNestingLevel == 1) {
0210: retval.header = (HeaderRecord) rec;
0211: } else if (rec.getSid() == FooterRecord.sid
0212: && bofEofNestingLevel == 1) {
0213: retval.footer = (FooterRecord) rec;
0214: } else if (rec.getSid() == PrintSetupRecord.sid
0215: && bofEofNestingLevel == 1) {
0216: retval.printSetup = (PrintSetupRecord) rec;
0217: } else if (rec.getSid() == LeftMarginRecord.sid) {
0218: retval.getMargins()[LeftMargin] = (LeftMarginRecord) rec;
0219: } else if (rec.getSid() == RightMarginRecord.sid) {
0220: retval.getMargins()[RightMargin] = (RightMarginRecord) rec;
0221: } else if (rec.getSid() == TopMarginRecord.sid) {
0222: retval.getMargins()[TopMargin] = (TopMarginRecord) rec;
0223: } else if (rec.getSid() == BottomMarginRecord.sid) {
0224: retval.getMargins()[BottomMargin] = (BottomMarginRecord) rec;
0225: } else if (rec.getSid() == SelectionRecord.sid) {
0226: retval.selection = (SelectionRecord) rec;
0227: } else if (rec.getSid() == WindowTwoRecord.sid) {
0228: retval.windowTwo = (WindowTwoRecord) rec;
0229: } else if (rec.getSid() == DBCellRecord.sid) {
0230: rec = null;
0231: } else if (rec.getSid() == IndexRecord.sid) {
0232: rec = null;
0233: }
0234:
0235: else if (rec.getSid() == ProtectRecord.sid) {
0236: retval.protect = (ProtectRecord) rec;
0237: } else if (rec.getSid() == ObjectProtectRecord.sid) {
0238: retval.objprotect = (ObjectProtectRecord) rec;
0239: } else if (rec.getSid() == ScenarioProtectRecord.sid) {
0240: retval.scenprotect = (ScenarioProtectRecord) rec;
0241: } else if (rec.getSid() == PasswordRecord.sid) {
0242: retval.password = (PasswordRecord) rec;
0243: } else if (rec.getSid() == PageBreakRecord.HORIZONTAL_SID) {
0244: retval.rowBreaks = (PageBreakRecord) rec;
0245: } else if (rec.getSid() == PageBreakRecord.VERTICAL_SID) {
0246: retval.colBreaks = (PageBreakRecord) rec;
0247: }
0248:
0249: if (rec != null) {
0250: records.add(rec);
0251: }
0252: }
0253: retval.records = records;
0254: // if (retval.rows == null)
0255: // {
0256: // retval.rows = new RowRecordsAggregate();
0257: // }
0258: retval.checkCells();
0259: retval.checkRows();
0260: // if (retval.cells == null)
0261: // {
0262: // retval.cells = new ValueRecordsAggregate();
0263: // }
0264: if (log.check(POILogger.DEBUG))
0265: log.log(POILogger.DEBUG,
0266: "sheet createSheet (existing file) exited");
0267: return retval;
0268: }
0269:
0270: /**
0271: * Clones the low level records of this sheet and returns the new sheet instance.
0272: * This method is implemented by adding methods for deep cloning to all records that
0273: * can be added to a sheet. The <b>Record</b> object does not implement cloneable.
0274: * When adding a new record, implement a public clone method if and only if the record
0275: * belongs to a sheet.
0276: */
0277: public Sheet cloneSheet() {
0278: ArrayList clonedRecords = new ArrayList(this .records.size());
0279: for (int i = 0; i < this .records.size(); i++) {
0280: Record rec = (Record) ((Record) this .records.get(i))
0281: .clone();
0282: //Need to pull out the Row record and the Value records from their
0283: //Aggregates.
0284: //This is probably the best way to do it since we probably dont want the createSheet
0285: //To cater for these artificial Record types
0286: if (rec instanceof RowRecordsAggregate) {
0287: RowRecordsAggregate rrAgg = (RowRecordsAggregate) rec;
0288: for (Iterator rowIter = rrAgg.getIterator(); rowIter
0289: .hasNext();) {
0290: Record rowRec = (Record) rowIter.next();
0291: clonedRecords.add(rowRec);
0292: }
0293: } else if (rec instanceof ValueRecordsAggregate) {
0294: ValueRecordsAggregate vrAgg = (ValueRecordsAggregate) rec;
0295: for (Iterator cellIter = vrAgg.getIterator(); cellIter
0296: .hasNext();) {
0297: Record valRec = (Record) cellIter.next();
0298:
0299: if (valRec instanceof FormulaRecordAggregate) {
0300: FormulaRecordAggregate fmAgg = (FormulaRecordAggregate) valRec;
0301: Record fmAggRec = fmAgg.getFormulaRecord();
0302: if (fmAggRec != null)
0303: clonedRecords.add(fmAggRec);
0304: fmAggRec = fmAgg.getStringRecord();
0305: if (fmAggRec != null)
0306: clonedRecords.add(fmAggRec);
0307: } else {
0308: clonedRecords.add(valRec);
0309: }
0310: }
0311: } else if (rec instanceof FormulaRecordAggregate) { //Is this required now??
0312: FormulaRecordAggregate fmAgg = (FormulaRecordAggregate) rec;
0313: Record fmAggRec = fmAgg.getFormulaRecord();
0314: if (fmAggRec != null)
0315: clonedRecords.add(fmAggRec);
0316: fmAggRec = fmAgg.getStringRecord();
0317: if (fmAggRec != null)
0318: clonedRecords.add(fmAggRec);
0319: } else {
0320: clonedRecords.add(rec);
0321: }
0322: }
0323: return createSheet(clonedRecords, 0, 0);
0324: }
0325:
0326: /**
0327: * read support (offset = 0) Same as createSheet(Record[] recs, int, int)
0328: * only the record offset is assumed to be 0.
0329: *
0330: * @param records array containing those records in the sheet in sequence (normally obtained from RecordFactory)
0331: * @param sheetnum integer specifying the sheet's number (0,1 or 2 in this release)
0332: * @return Sheet object
0333: */
0334:
0335: public static Sheet createSheet(List records, int sheetnum) {
0336: if (log.check(POILogger.DEBUG))
0337: log
0338: .log(POILogger.DEBUG,
0339: "Sheet createSheet (exisiting file) assumed offset 0");
0340: return createSheet(records, sheetnum, 0);
0341: }
0342:
0343: /**
0344: * Creates a sheet with all the usual records minus values and the "index"
0345: * record (not required). Sets the location pointer to where the first value
0346: * records should go. Use this to create a sheet from "scratch".
0347: *
0348: * @return Sheet object with all values set to defaults
0349: */
0350:
0351: public static Sheet createSheet() {
0352: if (log.check(POILogger.DEBUG))
0353: log.log(POILogger.DEBUG,
0354: "Sheet createsheet from scratch called");
0355: Sheet retval = new Sheet();
0356: ArrayList records = new ArrayList(30);
0357:
0358: records.add(retval.createBOF());
0359:
0360: // records.add(retval.createIndex());
0361: records.add(retval.createCalcMode());
0362: records.add(retval.createCalcCount());
0363: records.add(retval.createRefMode());
0364: records.add(retval.createIteration());
0365: records.add(retval.createDelta());
0366: records.add(retval.createSaveRecalc());
0367: records.add(retval.createPrintHeaders());
0368: retval.printGridlines = (PrintGridlinesRecord) retval
0369: .createPrintGridlines();
0370: records.add(retval.printGridlines);
0371: retval.gridset = (GridsetRecord) retval.createGridset();
0372: records.add(retval.gridset);
0373: records.add(retval.createGuts());
0374: retval.defaultrowheight = (DefaultRowHeightRecord) retval
0375: .createDefaultRowHeight();
0376: records.add(retval.defaultrowheight);
0377: records.add(retval.createWSBool());
0378:
0379: retval.rowBreaks = new PageBreakRecord(
0380: PageBreakRecord.HORIZONTAL_SID);
0381: records.add(retval.rowBreaks);
0382: retval.colBreaks = new PageBreakRecord(
0383: PageBreakRecord.VERTICAL_SID);
0384: records.add(retval.colBreaks);
0385:
0386: retval.header = (HeaderRecord) retval.createHeader();
0387: records.add(retval.header);
0388: retval.footer = (FooterRecord) retval.createFooter();
0389: records.add(retval.footer);
0390: records.add(retval.createHCenter());
0391: records.add(retval.createVCenter());
0392: retval.printSetup = (PrintSetupRecord) retval
0393: .createPrintSetup();
0394: records.add(retval.printSetup);
0395: retval.defaultcolwidth = (DefaultColWidthRecord) retval
0396: .createDefaultColWidth();
0397: records.add(retval.defaultcolwidth);
0398: ColumnInfoRecordsAggregate columns = new ColumnInfoRecordsAggregate();
0399: records.add(columns);
0400: retval.columns = columns;
0401: retval.dims = (DimensionsRecord) retval.createDimensions();
0402: records.add(retval.dims);
0403: retval.dimsloc = records.size() - 1;
0404: records.add(retval.windowTwo = retval.createWindowTwo());
0405: retval.setLoc(records.size() - 1);
0406: retval.selection = (SelectionRecord) retval.createSelection();
0407: records.add(retval.selection);
0408: retval.protect = (ProtectRecord) retval.createProtect();
0409: records.add(retval.protect);
0410: records.add(retval.createEOF());
0411:
0412: retval.records = records;
0413: if (log.check(POILogger.DEBUG))
0414: log.log(POILogger.DEBUG,
0415: "Sheet createsheet from scratch exit");
0416: return retval;
0417: }
0418:
0419: private void checkCells() {
0420: if (cells == null) {
0421: cells = new ValueRecordsAggregate();
0422: records.add(getDimsLoc() + 1, cells);
0423: }
0424: }
0425:
0426: private void checkRows() {
0427: if (rows == null) {
0428: rows = new RowRecordsAggregate();
0429: records.add(getDimsLoc() + 1, rows);
0430: }
0431: }
0432:
0433: //public int addMergedRegion(short rowFrom, short colFrom, short rowTo,
0434: public int addMergedRegion(int rowFrom, short colFrom, int rowTo,
0435: short colTo) {
0436: // Validate input
0437: if (rowTo < rowFrom) {
0438: throw new IllegalArgumentException("The row to (" + rowTo
0439: + ") must be >= the row from (" + rowFrom + ")");
0440: }
0441: if (colTo < colFrom) {
0442: throw new IllegalArgumentException("The col to (" + colTo
0443: + ") must be >= the col from (" + colFrom + ")");
0444: }
0445:
0446: if (merged == null || merged.getNumAreas() == 1027) {
0447: merged = (MergeCellsRecord) createMergedCells();
0448: mergedRecords.add(merged);
0449: records.add(records.size() - 1, merged);
0450: }
0451: merged.addArea(rowFrom, colFrom, rowTo, colTo);
0452: return numMergedRegions++;
0453: }
0454:
0455: public void removeMergedRegion(int index) {
0456: //safety checks
0457: if (index >= numMergedRegions || mergedRecords.size() == 0)
0458: return;
0459:
0460: int pos = 0;
0461: int startNumRegions = 0;
0462:
0463: //optimisation for current record
0464: if (numMergedRegions - index < merged.getNumAreas()) {
0465: pos = mergedRecords.size() - 1;
0466: startNumRegions = numMergedRegions - merged.getNumAreas();
0467: } else {
0468: for (int n = 0; n < mergedRecords.size(); n++) {
0469: MergeCellsRecord record = (MergeCellsRecord) mergedRecords
0470: .get(n);
0471: if (startNumRegions + record.getNumAreas() > index) {
0472: pos = n;
0473: break;
0474: }
0475: startNumRegions += record.getNumAreas();
0476: }
0477: }
0478:
0479: MergeCellsRecord rec = (MergeCellsRecord) mergedRecords
0480: .get(pos);
0481: rec.removeAreaAt(index - startNumRegions);
0482: numMergedRegions--;
0483: if (rec.getNumAreas() == 0) {
0484: mergedRecords.remove(pos);
0485: //get rid of the record from the sheet
0486: records.remove(merged);
0487: if (merged == rec) {
0488: //pull up the LAST record for operations when we finally
0489: //support continue records for mergedRegions
0490: if (mergedRecords.size() > 0) {
0491: merged = (MergeCellsRecord) mergedRecords
0492: .get(mergedRecords.size() - 1);
0493: } else {
0494: merged = null;
0495: }
0496: }
0497: }
0498: }
0499:
0500: public MergeCellsRecord.MergedRegion getMergedRegionAt(int index) {
0501: //safety checks
0502: if (index >= numMergedRegions || mergedRecords.size() == 0)
0503: return null;
0504:
0505: int pos = 0;
0506: int startNumRegions = 0;
0507:
0508: //optimisation for current record
0509: if (numMergedRegions - index < merged.getNumAreas()) {
0510: pos = mergedRecords.size() - 1;
0511: startNumRegions = numMergedRegions - merged.getNumAreas();
0512: } else {
0513: for (int n = 0; n < mergedRecords.size(); n++) {
0514: MergeCellsRecord record = (MergeCellsRecord) mergedRecords
0515: .get(n);
0516: if (startNumRegions + record.getNumAreas() > index) {
0517: pos = n;
0518: break;
0519: }
0520: startNumRegions += record.getNumAreas();
0521: }
0522: }
0523: return ((MergeCellsRecord) mergedRecords.get(pos))
0524: .getAreaAt(index - startNumRegions);
0525: }
0526:
0527: public int getNumMergedRegions() {
0528: return numMergedRegions;
0529: }
0530:
0531: /**
0532: * Returns the number of low level binary records in this sheet. This adjusts things for the so called
0533: * AgregateRecords.
0534: *
0535: * @see org.apache.poi.hssf.record.Record
0536: */
0537:
0538: public int getNumRecords() {
0539: checkCells();
0540: checkRows();
0541: if (log.check(POILogger.DEBUG)) {
0542: log.log(POILogger.DEBUG, "Sheet.getNumRecords");
0543: log.logFormatted(POILogger.DEBUG,
0544: "returning % + % + % - 2 = %", new int[] {
0545: records.size(),
0546: cells.getPhysicalNumberOfCells(),
0547: rows.getPhysicalNumberOfRows(),
0548: records.size()
0549: + cells.getPhysicalNumberOfCells()
0550: + rows.getPhysicalNumberOfRows()
0551: - 2 });
0552: }
0553: return records.size() + cells.getPhysicalNumberOfCells()
0554: + rows.getPhysicalNumberOfRows() - 2;
0555: }
0556:
0557: /**
0558: * Per an earlier reported bug in working with Andy Khan's excel read library. This
0559: * sets the values in the sheet's DimensionsRecord object to be correct. Excel doesn't
0560: * really care, but we want to play nice with other libraries.
0561: *
0562: * @see org.apache.poi.hssf.record.DimensionsRecord
0563: */
0564:
0565: //public void setDimensions(short firstrow, short firstcol, short lastrow,
0566: public void setDimensions(int firstrow, short firstcol,
0567: int lastrow, short lastcol) {
0568: if (log.check(POILogger.DEBUG)) {
0569: log.log(POILogger.DEBUG, "Sheet.setDimensions");
0570: log.log(POILogger.DEBUG, (new StringBuffer("firstrow"))
0571: .append(firstrow).append("firstcol").append(
0572: firstcol).append("lastrow").append(lastrow)
0573: .append("lastcol").append(lastcol).toString());
0574: }
0575: dims.setFirstCol(firstcol);
0576: dims.setFirstRow(firstrow);
0577: dims.setLastCol(lastcol);
0578: dims.setLastRow(lastrow);
0579: if (log.check(POILogger.DEBUG))
0580: log.log(POILogger.DEBUG, "Sheet.setDimensions exiting");
0581: }
0582:
0583: /**
0584: * set the locator for where we should look for the next value record. The
0585: * algorythm will actually start here and find the correct location so you
0586: * can set this to 0 and watch performance go down the tubes but it will work.
0587: * After a value is set this is automatically advanced. Its also set by the
0588: * create method. So you probably shouldn't mess with this unless you have
0589: * a compelling reason why or the help for the method you're calling says so.
0590: * Check the other methods for whether they care about
0591: * the loc pointer. Many of the "modify" and "remove" methods re-initialize this
0592: * to "dimsloc" which is the location of the Dimensions Record and presumably the
0593: * start of the value section (at or around 19 dec).
0594: *
0595: * @param loc the record number to start at
0596: *
0597: */
0598:
0599: public void setLoc(int loc) {
0600: valueRecIterator = null;
0601: if (log.check(POILogger.DEBUG))
0602: log.log(POILogger.DEBUG, "sheet.setLoc(): " + loc);
0603: this .loc = loc;
0604: }
0605:
0606: /**
0607: * Returns the location pointer to the first record to look for when adding rows/values
0608: *
0609: */
0610:
0611: public int getLoc() {
0612: if (log.check(POILogger.DEBUG))
0613: log.log(POILogger.DEBUG, "sheet.getLoc():" + loc);
0614: return loc;
0615: }
0616:
0617: /**
0618: * Set the preoffset when using DBCELL records (currently unused) - this is
0619: * the position of this sheet within the whole file.
0620: *
0621: * @param offset the offset of the sheet's BOF within the file.
0622: */
0623:
0624: public void setPreOffset(int offset) {
0625: this .preoffset = offset;
0626: }
0627:
0628: /**
0629: * get the preoffset when using DBCELL records (currently unused) - this is
0630: * the position of this sheet within the whole file.
0631: *
0632: * @return offset the offset of the sheet's BOF within the file.
0633: */
0634:
0635: public int getPreOffset() {
0636: return preoffset;
0637: }
0638:
0639: /**
0640: * Serializes all records in the sheet into one big byte array. Use this to write
0641: * the sheet out.
0642: *
0643: * @param offset to begin write at
0644: * @param data array containing the binary representation of the records in this sheet
0645: *
0646: */
0647:
0648: public int serialize(int offset, byte[] data) {
0649: if (log.check(POILogger.DEBUG))
0650: log.log(POILogger.DEBUG, "Sheet.serialize using offsets");
0651:
0652: int pos = offset;
0653: boolean haveSerializedIndex = false;
0654:
0655: for (int k = 0; k < records.size(); k++) {
0656: Record record = ((Record) records.get(k));
0657:
0658: //Once the rows have been found in the list of records, start
0659: //writing out the blocked row information. This includes the DBCell references
0660: if (record instanceof RowRecordsAggregate) {
0661: pos += ((RowRecordsAggregate) record).serialize(pos,
0662: data, cells); // rec.length;
0663: } else if (record instanceof ValueRecordsAggregate) {
0664: //Do nothing here. The records were serialized during the RowRecordAggregate block serialization
0665: } else {
0666: pos += record.serialize(pos, data); // rec.length;
0667: }
0668: //If the BOF record was just serialized then add the IndexRecord
0669: if (record.getSid() == BOFRecord.sid) {
0670: //Can there be more than one BOF for a sheet? If not then we can
0671: //remove this guard. So be safe it is left here.
0672: if (rows != null && !haveSerializedIndex) {
0673: haveSerializedIndex = true;
0674: pos += serializeIndexRecord(k, pos, data);
0675: }
0676: }
0677:
0678: //// uncomment to test record sizes ////
0679: // System.out.println( record.getClass().getName() );
0680: // byte[] data2 = new byte[record.getRecordSize()];
0681: // record.serialize(0, data2 ); // rec.length;
0682: // if (LittleEndian.getUShort(data2, 2) != record.getRecordSize() - 4
0683: // && record instanceof RowRecordsAggregate == false
0684: // && record instanceof ValueRecordsAggregate == false
0685: // && record instanceof EscherAggregate == false)
0686: // {
0687: // throw new RuntimeException("Blah!!! Size off by " + ( LittleEndian.getUShort(data2, 2) - record.getRecordSize() - 4) + " records.");
0688: // }
0689:
0690: //asd: int len = record.serialize(pos + offset, data );
0691:
0692: ///// DEBUG BEGIN /////
0693: //asd: if (len != record.getRecordSize())
0694: //asd: throw new IllegalStateException("Record size does not match serialized bytes. Serialized size = " + len + " but getRecordSize() returns " + record.getRecordSize() + ". Record object is " + record.getClass());
0695: ///// DEBUG END /////
0696:
0697: //asd: pos += len; // rec.length;
0698:
0699: }
0700: if (log.check(POILogger.DEBUG))
0701: log.log(POILogger.DEBUG, "Sheet.serialize returning ");
0702: return pos - offset;
0703: }
0704:
0705: private int serializeIndexRecord(final int BOFRecordIndex,
0706: final int offset, byte[] data) {
0707: IndexRecord index = new IndexRecord();
0708: index.setFirstRow(rows.getFirstRowNum());
0709: index.setLastRowAdd1(rows.getLastRowNum() + 1);
0710: //Calculate the size of the records from the end of the BOF
0711: //and up to the RowRecordsAggregate...
0712: int sheetRecSize = 0;
0713: for (int j = BOFRecordIndex + 1; j < records.size(); j++) {
0714: Record tmpRec = ((Record) records.get(j));
0715: if (tmpRec instanceof RowRecordsAggregate)
0716: break;
0717: sheetRecSize += tmpRec.getRecordSize();
0718: }
0719: //Add the references to the DBCells in the IndexRecord (one for each block)
0720: int blockCount = rows.getRowBlockCount();
0721: //Calculate the size of this IndexRecord
0722: int indexRecSize = IndexRecord
0723: .getRecordSizeForBlockCount(blockCount);
0724:
0725: int rowBlockOffset = 0;
0726: int cellBlockOffset = 0;
0727: int dbCellOffset = 0;
0728: for (int block = 0; block < blockCount; block++) {
0729: rowBlockOffset += rows.getRowBlockSize(block);
0730: cellBlockOffset += null == cells ? 0 : cells
0731: .getRowCellBlockSize(rows
0732: .getStartRowNumberForBlock(block), rows
0733: .getEndRowNumberForBlock(block));
0734: //Note: The offsets are relative to the Workbook BOF. Assume that this is
0735: //0 for now.....
0736: index.addDbcell(offset + indexRecSize + sheetRecSize
0737: + dbCellOffset + rowBlockOffset + cellBlockOffset);
0738: //Add space required to write the dbcell record(s) (whose references were just added).
0739: dbCellOffset += (8 + (rows.getRowCountForBlock(block) * 2));
0740: }
0741: return index.serialize(offset, data);
0742: }
0743:
0744: /**
0745: * Create a row record. (does not add it to the records contained in this sheet)
0746: *
0747: * @param row number
0748: * @return RowRecord created for the passed in row number
0749: * @see org.apache.poi.hssf.record.RowRecord
0750: */
0751:
0752: public RowRecord createRow(int row) {
0753: return RowRecordsAggregate.createRow(row);
0754: }
0755:
0756: /**
0757: * Create a LABELSST Record (does not add it to the records contained in this sheet)
0758: *
0759: * @param row the row the LabelSST is a member of
0760: * @param col the column the LabelSST defines
0761: * @param index the index of the string within the SST (use workbook addSSTString method)
0762: * @return LabelSSTRecord newly created containing your SST Index, row,col.
0763: * @see org.apache.poi.hssf.record.SSTRecord
0764: */
0765:
0766: //public LabelSSTRecord createLabelSST(short row, short col, int index)
0767: public LabelSSTRecord createLabelSST(int row, short col, int index) {
0768: log.logFormatted(POILogger.DEBUG,
0769: "create labelsst row,col,index %,%,%", new int[] { row,
0770: col, index });
0771: LabelSSTRecord rec = new LabelSSTRecord();
0772:
0773: rec.setRow(row);
0774: rec.setColumn(col);
0775: rec.setSSTIndex(index);
0776: rec.setXFIndex((short) 0x0f);
0777: return rec;
0778: }
0779:
0780: /**
0781: * Create a NUMBER Record (does not add it to the records contained in this sheet)
0782: *
0783: * @param row the row the NumberRecord is a member of
0784: * @param col the column the NumberRecord defines
0785: * @param value for the number record
0786: *
0787: * @return NumberRecord for that row, col containing that value as added to the sheet
0788: */
0789:
0790: //public NumberRecord createNumber(short row, short col, double value)
0791: public NumberRecord createNumber(int row, short col, double value) {
0792: log.logFormatted(POILogger.DEBUG,
0793: "create number row,col,value %,%,%", new double[] {
0794: row, col, value });
0795: NumberRecord rec = new NumberRecord();
0796:
0797: //rec.setRow(( short ) row);
0798: rec.setRow(row);
0799: rec.setColumn(col);
0800: rec.setValue(value);
0801: rec.setXFIndex((short) 0x0f);
0802: return rec;
0803: }
0804:
0805: /**
0806: * create a BLANK record (does not add it to the records contained in this sheet)
0807: *
0808: * @param row - the row the BlankRecord is a member of
0809: * @param col - the column the BlankRecord is a member of
0810: */
0811:
0812: //public BlankRecord createBlank(short row, short col)
0813: public BlankRecord createBlank(int row, short col) {
0814: //log.logFormatted(POILogger.DEBUG, "create blank row,col %,%", new short[]
0815: log.logFormatted(POILogger.DEBUG, "create blank row,col %,%",
0816: new int[] { row, col });
0817: BlankRecord rec = new BlankRecord();
0818:
0819: //rec.setRow(( short ) row);
0820: rec.setRow(row);
0821: rec.setColumn(col);
0822: rec.setXFIndex((short) 0x0f);
0823: return rec;
0824: }
0825:
0826: /**
0827: * Attempts to parse the formula into PTGs and create a formula record
0828: * DOES NOT WORK YET
0829: *
0830: * @param row - the row for the formula record
0831: * @param col - the column of the formula record
0832: * @param formula - a String representing the formula. To be parsed to PTGs
0833: * @return bogus/useless formula record
0834: */
0835:
0836: //public FormulaRecord createFormula(short row, short col, String formula)
0837: public FormulaRecord createFormula(int row, short col,
0838: String formula) {
0839: log.logFormatted(POILogger.DEBUG,
0840: "create formula row,col,formula %,%,%",
0841: //new short[]
0842: new int[] { row, col }, formula);
0843: FormulaRecord rec = new FormulaRecord();
0844:
0845: rec.setRow(row);
0846: rec.setColumn(col);
0847: rec.setOptions((short) 2);
0848: rec.setValue(0);
0849: rec.setXFIndex((short) 0x0f);
0850: FormulaParser fp = new FormulaParser(formula, null); //fix - do we need this method?
0851: fp.parse();
0852: Ptg[] ptg = fp.getRPNPtg();
0853: int size = 0;
0854:
0855: for (int k = 0; k < ptg.length; k++) {
0856: size += ptg[k].getSize();
0857: rec.pushExpressionToken(ptg[k]);
0858: }
0859: rec.setExpressionLength((short) size);
0860: return rec;
0861: }
0862:
0863: /**
0864: * Adds a value record to the sheet's contained binary records
0865: * (i.e. LabelSSTRecord or NumberRecord).
0866: * <P>
0867: * This method is "loc" sensitive. Meaning you need to set LOC to where you
0868: * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
0869: * When adding several rows you can just start at the last one by leaving loc
0870: * at what this sets it to.
0871: *
0872: * @param row the row to add the cell value to
0873: * @param col the cell value record itself.
0874: */
0875:
0876: //public void addValueRecord(short row, CellValueRecordInterface col)
0877: public void addValueRecord(int row, CellValueRecordInterface col) {
0878: checkCells();
0879: if (log.check(POILogger.DEBUG)) {
0880: log.logFormatted(POILogger.DEBUG,
0881: "add value record row,loc %,%", new int[] { row,
0882: loc });
0883: }
0884: DimensionsRecord d = (DimensionsRecord) records
0885: .get(getDimsLoc());
0886:
0887: if (col.getColumn() > d.getLastCol()) {
0888: d.setLastCol((short) (col.getColumn() + 1));
0889: }
0890: if (col.getColumn() < d.getFirstCol()) {
0891: d.setFirstCol(col.getColumn());
0892: }
0893: cells.insertCell(col);
0894:
0895: /*
0896: * for (int k = loc; k < records.size(); k++)
0897: * {
0898: * Record rec = ( Record ) records.get(k);
0899: *
0900: * if (rec.getSid() == RowRecord.sid)
0901: * {
0902: * RowRecord rowrec = ( RowRecord ) rec;
0903: *
0904: * if (rowrec.getRowNumber() == col.getRow())
0905: * {
0906: * records.add(k + 1, col);
0907: * loc = k;
0908: * if (rowrec.getLastCol() <= col.getColumn())
0909: * {
0910: * rowrec.setLastCol((( short ) (col.getColumn() + 1)));
0911: * }
0912: * break;
0913: * }
0914: * }
0915: * }
0916: */
0917: }
0918:
0919: /**
0920: * remove a value record from the records array.
0921: *
0922: * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
0923: *
0924: * @param row - the row of the value record you wish to remove
0925: * @param col - a record supporting the CellValueRecordInterface.
0926: * @see org.apache.poi.hssf.record.CellValueRecordInterface
0927: */
0928:
0929: //public void removeValueRecord(short row, CellValueRecordInterface col)
0930: public void removeValueRecord(int row, CellValueRecordInterface col) {
0931: checkCells();
0932: log.logFormatted(POILogger.DEBUG,
0933: "remove value record row,dimsloc %,%", new int[] { row,
0934: dimsloc });
0935: loc = dimsloc;
0936: cells.removeCell(col);
0937:
0938: /*
0939: * for (int k = loc; k < records.size(); k++)
0940: * {
0941: * Record rec = ( Record ) records.get(k);
0942: *
0943: * // checkDimsLoc(rec,k);
0944: * if (rec.isValue())
0945: * {
0946: * CellValueRecordInterface cell =
0947: * ( CellValueRecordInterface ) rec;
0948: *
0949: * if ((cell.getRow() == col.getRow())
0950: * && (cell.getColumn() == col.getColumn()))
0951: * {
0952: * records.remove(k);
0953: * break;
0954: * }
0955: * }
0956: * }
0957: */
0958: }
0959:
0960: /**
0961: * replace a value record from the records array.
0962: *
0963: * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
0964: *
0965: * @param newval - a record supporting the CellValueRecordInterface. this will replace
0966: * the cell value with the same row and column. If there isn't one, one will
0967: * be added.
0968: */
0969:
0970: public void replaceValueRecord(CellValueRecordInterface newval) {
0971: checkCells();
0972: setLoc(dimsloc);
0973: if (log.check(POILogger.DEBUG))
0974: log.log(POILogger.DEBUG, "replaceValueRecord ");
0975: //The ValueRecordsAggregate use a tree map underneath.
0976: //The tree Map uses the CellValueRecordInterface as both the
0977: //key and the value, if we dont do a remove, then
0978: //the previous instance of the key is retained, effectively using
0979: //double the memory
0980: cells.removeCell(newval);
0981: cells.insertCell(newval);
0982:
0983: /*
0984: * CellValueRecordInterface oldval = getNextValueRecord();
0985: *
0986: * while (oldval != null)
0987: * {
0988: * if (oldval.isEqual(newval))
0989: * {
0990: * records.set(( short ) (getLoc() - 1), newval);
0991: * return;
0992: * }
0993: * oldval = getNextValueRecord();
0994: * }
0995: * addValueRecord(newval.getRow(), newval);
0996: * setLoc(dimsloc);
0997: */
0998: }
0999:
1000: /**
1001: * Adds a row record to the sheet
1002: *
1003: * <P>
1004: * This method is "loc" sensitive. Meaning you need to set LOC to where you
1005: * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
1006: * When adding several rows you can just start at the last one by leaving loc
1007: * at what this sets it to.
1008: *
1009: * @param row the row record to be added
1010: * @see #setLoc(int)
1011: */
1012:
1013: public void addRow(RowRecord row) {
1014: checkRows();
1015: if (log.check(POILogger.DEBUG))
1016: log.log(POILogger.DEBUG, "addRow ");
1017: DimensionsRecord d = (DimensionsRecord) records
1018: .get(getDimsLoc());
1019:
1020: if (row.getRowNumber() >= d.getLastRow()) {
1021: d.setLastRow(row.getRowNumber() + 1);
1022: }
1023: if (row.getRowNumber() < d.getFirstRow()) {
1024: d.setFirstRow(row.getRowNumber());
1025: }
1026: //IndexRecord index = null;
1027: //If the row exists remove it, so that any cells attached to the row are removed
1028: RowRecord existingRow = rows.getRow(row.getRowNumber());
1029: if (existingRow != null)
1030: rows.removeRow(existingRow);
1031:
1032: rows.insertRow(row);
1033:
1034: /*
1035: * for (int k = loc; k < records.size(); k++)
1036: * {
1037: * Record rec = ( Record ) records.get(k);
1038: *
1039: * if (rec.getSid() == IndexRecord.sid)
1040: * {
1041: * index = ( IndexRecord ) rec;
1042: * }
1043: * if (rec.getSid() == RowRecord.sid)
1044: * {
1045: * RowRecord rowrec = ( RowRecord ) rec;
1046: *
1047: * if (rowrec.getRowNumber() > row.getRowNumber())
1048: * {
1049: * records.add(k, row);
1050: * loc = k;
1051: * break;
1052: * }
1053: * }
1054: * if (rec.getSid() == WindowTwoRecord.sid)
1055: * {
1056: * records.add(k, row);
1057: * loc = k;
1058: * break;
1059: * }
1060: * }
1061: * if (index != null)
1062: * {
1063: * if (index.getLastRowAdd1() <= row.getRowNumber())
1064: * {
1065: * index.setLastRowAdd1(row.getRowNumber() + 1);
1066: * }
1067: * }
1068: */
1069: if (log.check(POILogger.DEBUG))
1070: log.log(POILogger.DEBUG, "exit addRow");
1071: }
1072:
1073: /**
1074: * Removes a row record
1075: *
1076: * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
1077: *
1078: * @param row the row record to remove
1079: */
1080:
1081: public void removeRow(RowRecord row) {
1082: checkRows();
1083: // IndexRecord index = null;
1084:
1085: setLoc(getDimsLoc());
1086: rows.removeRow(row);
1087:
1088: /*
1089: * for (int k = loc; k < records.size(); k++)
1090: * {
1091: * Record rec = ( Record ) records.get(k);
1092: *
1093: * // checkDimsLoc(rec,k);
1094: * if (rec.getSid() == RowRecord.sid)
1095: * {
1096: * RowRecord rowrec = ( RowRecord ) rec;
1097: *
1098: * if (rowrec.getRowNumber() == row.getRowNumber())
1099: * {
1100: * records.remove(k);
1101: * break;
1102: * }
1103: * }
1104: * if (rec.getSid() == WindowTwoRecord.sid)
1105: * {
1106: * break;
1107: * }
1108: * }
1109: */
1110: }
1111:
1112: /**
1113: * get the NEXT value record (from LOC). The first record that is a value record
1114: * (starting at LOC) will be returned.
1115: *
1116: * <P>
1117: * This method is "loc" sensitive. Meaning you need to set LOC to where you
1118: * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
1119: * When adding several rows you can just start at the last one by leaving loc
1120: * at what this sets it to. For this method, set loc to dimsloc to start with,
1121: * subsequent calls will return values in (physical) sequence or NULL when you get to the end.
1122: *
1123: * @return CellValueRecordInterface representing the next value record or NULL if there are no more
1124: * @see #setLoc(int)
1125: */
1126:
1127: public CellValueRecordInterface getNextValueRecord() {
1128: if (log.check(POILogger.DEBUG))
1129: log.log(POILogger.DEBUG, "getNextValue loc= " + loc);
1130: if (valueRecIterator == null) {
1131: valueRecIterator = cells.getIterator();
1132: }
1133: if (!valueRecIterator.hasNext()) {
1134: return null;
1135: }
1136: return (CellValueRecordInterface) valueRecIterator.next();
1137:
1138: /*
1139: * if (this.getLoc() < records.size())
1140: * {
1141: * for (int k = getLoc(); k < records.size(); k++)
1142: * {
1143: * Record rec = ( Record ) records.get(k);
1144: *
1145: * this.setLoc(k + 1);
1146: * if (rec instanceof CellValueRecordInterface)
1147: * {
1148: * return ( CellValueRecordInterface ) rec;
1149: * }
1150: * }
1151: * }
1152: * return null;
1153: */
1154: }
1155:
1156: /**
1157: * get the NEXT RowRecord or CellValueRecord(from LOC). The first record that
1158: * is a Row record or CellValueRecord(starting at LOC) will be returned.
1159: * <P>
1160: * This method is "loc" sensitive. Meaning you need to set LOC to where you
1161: * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
1162: * When adding several rows you can just start at the last one by leaving loc
1163: * at what this sets it to. For this method, set loc to dimsloc to start with.
1164: * subsequent calls will return rows in (physical) sequence or NULL when you get to the end.
1165: *
1166: * @return RowRecord representing the next row record or CellValueRecordInterface
1167: * representing the next cellvalue or NULL if there are no more
1168: * @see #setLoc(int)
1169: *
1170: */
1171:
1172: /* public Record getNextRowOrValue()
1173: {
1174: POILogger.DEBUG((new StringBuffer("getNextRow loc= ")).append(loc)
1175: .toString());
1176: if (this.getLoc() < records.size())
1177: {
1178: for (int k = this.getLoc(); k < records.size(); k++)
1179: {
1180: Record rec = ( Record ) records.get(k);
1181:
1182: this.setLoc(k + 1);
1183: if (rec.getSid() == RowRecord.sid)
1184: {
1185: return rec;
1186: }
1187: else if (rec.isValue())
1188: {
1189: return rec;
1190: }
1191: }
1192: }
1193: return null;
1194: }
1195: */
1196:
1197: /**
1198: * get the NEXT RowRecord (from LOC). The first record that is a Row record
1199: * (starting at LOC) will be returned.
1200: * <P>
1201: * This method is "loc" sensitive. Meaning you need to set LOC to where you
1202: * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
1203: * When adding several rows you can just start at the last one by leaving loc
1204: * at what this sets it to. For this method, set loc to dimsloc to start with.
1205: * subsequent calls will return rows in (physical) sequence or NULL when you get to the end.
1206: *
1207: * @return RowRecord representing the next row record or NULL if there are no more
1208: * @see #setLoc(int)
1209: *
1210: */
1211:
1212: public RowRecord getNextRow() {
1213: if (log.check(POILogger.DEBUG))
1214: log.log(POILogger.DEBUG, "getNextRow loc= " + loc);
1215: if (rowRecIterator == null) {
1216: rowRecIterator = rows.getIterator();
1217: }
1218: if (!rowRecIterator.hasNext()) {
1219: return null;
1220: }
1221: return (RowRecord) rowRecIterator.next();
1222:
1223: /* if (this.getLoc() < records.size())
1224: {
1225: for (int k = this.getLoc(); k < records.size(); k++)
1226: {
1227: Record rec = ( Record ) records.get(k);
1228:
1229: this.setLoc(k + 1);
1230: if (rec.getSid() == RowRecord.sid)
1231: {
1232: return ( RowRecord ) rec;
1233: }
1234: }
1235: }*/
1236: }
1237:
1238: /**
1239: * get the NEXT (from LOC) RowRecord where rownumber matches the given rownum.
1240: * The first record that is a Row record (starting at LOC) that has the
1241: * same rownum as the given rownum will be returned.
1242: * <P>
1243: * This method is "loc" sensitive. Meaning you need to set LOC to where you
1244: * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
1245: * When adding several rows you can just start at the last one by leaving loc
1246: * at what this sets it to. For this method, set loc to dimsloc to start with.
1247: * subsequent calls will return rows in (physical) sequence or NULL when you get to the end.
1248: *
1249: * @param rownum which row to return (careful with LOC)
1250: * @return RowRecord representing the next row record or NULL if there are no more
1251: * @see #setLoc(int)
1252: *
1253: */
1254:
1255: //public RowRecord getRow(short rownum)
1256: public RowRecord getRow(int rownum) {
1257: if (log.check(POILogger.DEBUG))
1258: log.log(POILogger.DEBUG, "getNextRow loc= " + loc);
1259: return rows.getRow(rownum);
1260:
1261: /*
1262: * if (this.getLoc() < records.size())
1263: * {
1264: * for (int k = this.getLoc(); k < records.size(); k++)
1265: * {
1266: * Record rec = ( Record ) records.get(k);
1267: *
1268: * this.setLoc(k + 1);
1269: * if (rec.getSid() == RowRecord.sid)
1270: * {
1271: * if ((( RowRecord ) rec).getRowNumber() == rownum)
1272: * {
1273: * return ( RowRecord ) rec;
1274: * }
1275: * }
1276: * }
1277: * }
1278: */
1279:
1280: // return null;
1281: }
1282:
1283: /**
1284: * creates the BOF record
1285: * @see org.apache.poi.hssf.record.BOFRecord
1286: * @see org.apache.poi.hssf.record.Record
1287: * @return record containing a BOFRecord
1288: */
1289:
1290: protected Record createBOF() {
1291: BOFRecord retval = new BOFRecord();
1292:
1293: retval.setVersion((short) 0x600);
1294: retval.setType((short) 0x010);
1295:
1296: // retval.setBuild((short)0x10d3);
1297: retval.setBuild((short) 0x0dbb);
1298: retval.setBuildYear((short) 1996);
1299: retval.setHistoryBitMask(0xc1);
1300: retval.setRequiredVersion(0x6);
1301: return retval;
1302: }
1303:
1304: /**
1305: * creates the Index record - not currently used
1306: * @see org.apache.poi.hssf.record.IndexRecord
1307: * @see org.apache.poi.hssf.record.Record
1308: * @return record containing a IndexRecord
1309: */
1310:
1311: protected Record createIndex() {
1312: IndexRecord retval = new IndexRecord();
1313:
1314: retval.setFirstRow(0); // must be set explicitly
1315: retval.setLastRowAdd1(0);
1316: return retval;
1317: }
1318:
1319: /**
1320: * creates the CalcMode record and sets it to 1 (automatic formula caculation)
1321: * @see org.apache.poi.hssf.record.CalcModeRecord
1322: * @see org.apache.poi.hssf.record.Record
1323: * @return record containing a CalcModeRecord
1324: */
1325:
1326: protected Record createCalcMode() {
1327: CalcModeRecord retval = new CalcModeRecord();
1328:
1329: retval.setCalcMode((short) 1);
1330: return retval;
1331: }
1332:
1333: /**
1334: * creates the CalcCount record and sets it to 0x64 (default number of iterations)
1335: * @see org.apache.poi.hssf.record.CalcCountRecord
1336: * @see org.apache.poi.hssf.record.Record
1337: * @return record containing a CalcCountRecord
1338: */
1339:
1340: protected Record createCalcCount() {
1341: CalcCountRecord retval = new CalcCountRecord();
1342:
1343: retval.setIterations((short) 0x64); // default 64 iterations
1344: return retval;
1345: }
1346:
1347: /**
1348: * creates the RefMode record and sets it to A1 Mode (default reference mode)
1349: * @see org.apache.poi.hssf.record.RefModeRecord
1350: * @see org.apache.poi.hssf.record.Record
1351: * @return record containing a RefModeRecord
1352: */
1353:
1354: protected Record createRefMode() {
1355: RefModeRecord retval = new RefModeRecord();
1356:
1357: retval.setMode(RefModeRecord.USE_A1_MODE);
1358: return retval;
1359: }
1360:
1361: /**
1362: * creates the Iteration record and sets it to false (don't iteratively calculate formulas)
1363: * @see org.apache.poi.hssf.record.IterationRecord
1364: * @see org.apache.poi.hssf.record.Record
1365: * @return record containing a IterationRecord
1366: */
1367:
1368: protected Record createIteration() {
1369: IterationRecord retval = new IterationRecord();
1370:
1371: retval.setIteration(false);
1372: return retval;
1373: }
1374:
1375: /**
1376: * creates the Delta record and sets it to 0.0010 (default accuracy)
1377: * @see org.apache.poi.hssf.record.DeltaRecord
1378: * @see org.apache.poi.hssf.record.Record
1379: * @return record containing a DeltaRecord
1380: */
1381:
1382: protected Record createDelta() {
1383: DeltaRecord retval = new DeltaRecord();
1384:
1385: retval.setMaxChange(0.0010);
1386: return retval;
1387: }
1388:
1389: /**
1390: * creates the SaveRecalc record and sets it to true (recalculate before saving)
1391: * @see org.apache.poi.hssf.record.SaveRecalcRecord
1392: * @see org.apache.poi.hssf.record.Record
1393: * @return record containing a SaveRecalcRecord
1394: */
1395:
1396: protected Record createSaveRecalc() {
1397: SaveRecalcRecord retval = new SaveRecalcRecord();
1398:
1399: retval.setRecalc(true);
1400: return retval;
1401: }
1402:
1403: /**
1404: * creates the PrintHeaders record and sets it to false (we don't create headers yet so why print them)
1405: * @see org.apache.poi.hssf.record.PrintHeadersRecord
1406: * @see org.apache.poi.hssf.record.Record
1407: * @return record containing a PrintHeadersRecord
1408: */
1409:
1410: protected Record createPrintHeaders() {
1411: PrintHeadersRecord retval = new PrintHeadersRecord();
1412:
1413: retval.setPrintHeaders(false);
1414: return retval;
1415: }
1416:
1417: /**
1418: * creates the PrintGridlines record and sets it to false (that makes for ugly sheets). As far as I can
1419: * tell this does the same thing as the GridsetRecord
1420: *
1421: * @see org.apache.poi.hssf.record.PrintGridlinesRecord
1422: * @see org.apache.poi.hssf.record.Record
1423: * @return record containing a PrintGridlinesRecord
1424: */
1425:
1426: protected Record createPrintGridlines() {
1427: PrintGridlinesRecord retval = new PrintGridlinesRecord();
1428:
1429: retval.setPrintGridlines(false);
1430: return retval;
1431: }
1432:
1433: /**
1434: * creates the Gridset record and sets it to true (user has mucked with the gridlines)
1435: * @see org.apache.poi.hssf.record.GridsetRecord
1436: * @see org.apache.poi.hssf.record.Record
1437: * @return record containing a GridsetRecord
1438: */
1439:
1440: protected Record createGridset() {
1441: GridsetRecord retval = new GridsetRecord();
1442:
1443: retval.setGridset(true);
1444: return retval;
1445: }
1446:
1447: /**
1448: * creates the Guts record and sets leftrow/topcol guttter and rowlevelmax/collevelmax to 0
1449: * @see org.apache.poi.hssf.record.GutsRecord
1450: * @see org.apache.poi.hssf.record.Record
1451: * @return record containing a GutsRecordRecord
1452: */
1453:
1454: protected Record createGuts() {
1455: GutsRecord retval = new GutsRecord();
1456:
1457: retval.setLeftRowGutter((short) 0);
1458: retval.setTopColGutter((short) 0);
1459: retval.setRowLevelMax((short) 0);
1460: retval.setColLevelMax((short) 0);
1461: return retval;
1462: }
1463:
1464: /**
1465: * creates the DefaultRowHeight Record and sets its options to 0 and rowheight to 0xff
1466: * @see org.apache.poi.hssf.record.DefaultRowHeightRecord
1467: * @see org.apache.poi.hssf.record.Record
1468: * @return record containing a DefaultRowHeightRecord
1469: */
1470:
1471: protected Record createDefaultRowHeight() {
1472: DefaultRowHeightRecord retval = new DefaultRowHeightRecord();
1473:
1474: retval.setOptionFlags((short) 0);
1475: retval.setRowHeight((short) 0xff);
1476: return retval;
1477: }
1478:
1479: /**
1480: * creates the WSBoolRecord and sets its values to defaults
1481: * @see org.apache.poi.hssf.record.WSBoolRecord
1482: * @see org.apache.poi.hssf.record.Record
1483: * @return record containing a WSBoolRecord
1484: */
1485:
1486: protected Record createWSBool() {
1487: WSBoolRecord retval = new WSBoolRecord();
1488:
1489: retval.setWSBool1((byte) 0x4);
1490: retval.setWSBool2((byte) 0xffffffc1);
1491: return retval;
1492: }
1493:
1494: /**
1495: * creates the Header Record and sets it to nothing/0 length
1496: * @see org.apache.poi.hssf.record.HeaderRecord
1497: * @see org.apache.poi.hssf.record.Record
1498: * @return record containing a HeaderRecord
1499: */
1500:
1501: protected Record createHeader() {
1502: HeaderRecord retval = new HeaderRecord();
1503:
1504: retval.setHeaderLength((byte) 0);
1505: retval.setHeader(null);
1506: return retval;
1507: }
1508:
1509: /**
1510: * creates the Footer Record and sets it to nothing/0 length
1511: * @see org.apache.poi.hssf.record.FooterRecord
1512: * @see org.apache.poi.hssf.record.Record
1513: * @return record containing a FooterRecord
1514: */
1515:
1516: protected Record createFooter() {
1517: FooterRecord retval = new FooterRecord();
1518:
1519: retval.setFooterLength((byte) 0);
1520: retval.setFooter(null);
1521: return retval;
1522: }
1523:
1524: /**
1525: * creates the HCenter Record and sets it to false (don't horizontally center)
1526: * @see org.apache.poi.hssf.record.HCenterRecord
1527: * @see org.apache.poi.hssf.record.Record
1528: * @return record containing a HCenterRecord
1529: */
1530:
1531: protected Record createHCenter() {
1532: HCenterRecord retval = new HCenterRecord();
1533:
1534: retval.setHCenter(false);
1535: return retval;
1536: }
1537:
1538: /**
1539: * creates the VCenter Record and sets it to false (don't horizontally center)
1540: * @see org.apache.poi.hssf.record.VCenterRecord
1541: * @see org.apache.poi.hssf.record.Record
1542: * @return record containing a VCenterRecord
1543: */
1544:
1545: protected Record createVCenter() {
1546: VCenterRecord retval = new VCenterRecord();
1547:
1548: retval.setVCenter(false);
1549: return retval;
1550: }
1551:
1552: /**
1553: * creates the PrintSetup Record and sets it to defaults and marks it invalid
1554: * @see org.apache.poi.hssf.record.PrintSetupRecord
1555: * @see org.apache.poi.hssf.record.Record
1556: * @return record containing a PrintSetupRecord
1557: */
1558:
1559: protected Record createPrintSetup() {
1560: PrintSetupRecord retval = new PrintSetupRecord();
1561:
1562: retval.setPaperSize((short) 1);
1563: retval.setScale((short) 100);
1564: retval.setPageStart((short) 1);
1565: retval.setFitWidth((short) 1);
1566: retval.setFitHeight((short) 1);
1567: retval.setOptions((short) 2);
1568: retval.setHResolution((short) 300);
1569: retval.setVResolution((short) 300);
1570: retval.setHeaderMargin(0.5);
1571: retval.setFooterMargin(0.5);
1572: retval.setCopies((short) 0);
1573: return retval;
1574: }
1575:
1576: /**
1577: * creates the DefaultColWidth Record and sets it to 8
1578: * @see org.apache.poi.hssf.record.DefaultColWidthRecord
1579: * @see org.apache.poi.hssf.record.Record
1580: * @return record containing a DefaultColWidthRecord
1581: */
1582:
1583: protected Record createDefaultColWidth() {
1584: DefaultColWidthRecord retval = new DefaultColWidthRecord();
1585:
1586: retval.setColWidth((short) 8);
1587: return retval;
1588: }
1589:
1590: /**
1591: * creates the ColumnInfo Record and sets it to a default column/width
1592: * @see org.apache.poi.hssf.record.ColumnInfoRecord
1593: * @return record containing a ColumnInfoRecord
1594: */
1595:
1596: protected Record createColInfo() {
1597: return ColumnInfoRecordsAggregate.createColInfo();
1598: }
1599:
1600: /**
1601: * get the default column width for the sheet (if the columns do not define their own width)
1602: * @return default column width
1603: */
1604:
1605: public short getDefaultColumnWidth() {
1606: return defaultcolwidth.getColWidth();
1607: }
1608:
1609: /**
1610: * get whether gridlines are printed.
1611: * @return true if printed
1612: */
1613:
1614: public boolean isGridsPrinted() {
1615: if (gridset == null) {
1616: gridset = (GridsetRecord) createGridset();
1617: //Insert the newlycreated Gridset record at the end of the record (just before the EOF)
1618: int loc = findFirstRecordLocBySid(EOFRecord.sid);
1619: records.add(loc, gridset);
1620: }
1621: return !gridset.getGridset();
1622: }
1623:
1624: /**
1625: * set whether gridlines printed or not.
1626: * @param value True if gridlines printed.
1627: */
1628:
1629: public void setGridsPrinted(boolean value) {
1630: gridset.setGridset(!value);
1631: }
1632:
1633: /**
1634: * set the default column width for the sheet (if the columns do not define their own width)
1635: * @param dcw default column width
1636: */
1637:
1638: public void setDefaultColumnWidth(short dcw) {
1639: defaultcolwidth.setColWidth(dcw);
1640: }
1641:
1642: /**
1643: * set the default row height for the sheet (if the rows do not define their own height)
1644: */
1645:
1646: public void setDefaultRowHeight(short dch) {
1647: defaultrowheight.setRowHeight(dch);
1648: }
1649:
1650: /**
1651: * get the default row height for the sheet (if the rows do not define their own height)
1652: * @return default row height
1653: */
1654:
1655: public short getDefaultRowHeight() {
1656: return defaultrowheight.getRowHeight();
1657: }
1658:
1659: /**
1660: * get the width of a given column in units of 1/20th of a point width (twips?)
1661: * @param column index
1662: * @see org.apache.poi.hssf.record.DefaultColWidthRecord
1663: * @see org.apache.poi.hssf.record.ColumnInfoRecord
1664: * @see #setColumnWidth(short,short)
1665: * @return column width in units of 1/20th of a point (twips?)
1666: */
1667:
1668: public short getColumnWidth(short column) {
1669: short retval = 0;
1670: ColumnInfoRecord ci = null;
1671:
1672: if (columns != null) {
1673: int count = columns.getNumColumns();
1674: for (int k = 0; k < count; k++) {
1675: ci = columns.getColInfo(k);
1676: if ((ci.getFirstColumn() <= column)
1677: && (column <= ci.getLastColumn())) {
1678: break;
1679: }
1680: ci = null;
1681: }
1682: }
1683: if (ci != null) {
1684: retval = ci.getColumnWidth();
1685: } else {
1686: retval = defaultcolwidth.getColWidth();
1687: }
1688: return retval;
1689: }
1690:
1691: /**
1692: * get the index to the ExtendedFormatRecord "associated" with
1693: * the column at specified 0-based index. (In this case, an
1694: * ExtendedFormatRecord index is actually associated with a
1695: * ColumnInfoRecord which spans 1 or more columns)
1696: * <br/>
1697: * Returns the index to the default ExtendedFormatRecord (0xF)
1698: * if no ColumnInfoRecord exists that includes the column
1699: * index specified.
1700: * @param column
1701: * @return index of ExtendedFormatRecord associated with
1702: * ColumnInfoRecord that includes the column index or the
1703: * index of the default ExtendedFormatRecord (0xF)
1704: */
1705: public short getXFIndexForColAt(short column) {
1706: short retval = 0;
1707: ColumnInfoRecord ci = null;
1708: if (columns != null) {
1709: int count = columns.getNumColumns();
1710: for (int k = 0; k < count; k++) {
1711: ci = columns.getColInfo(k);
1712: if ((ci.getFirstColumn() <= column)
1713: && (column <= ci.getLastColumn())) {
1714: break;
1715: }
1716: ci = null;
1717: }
1718: }
1719: retval = (ci != null) ? ci.getXFIndex() : 0xF;
1720: return retval;
1721: }
1722:
1723: /**
1724: * set the width for a given column in 1/20th of a character width units
1725: * @param column - the column number
1726: * @param width (in units of 1/20th of a character width)
1727: */
1728: public void setColumnWidth(short column, short width) {
1729: setColumn(column, new Short(width), null, null, null);
1730: }
1731:
1732: /**
1733: * Get the hidden property for a given column.
1734: * @param column index
1735: * @see org.apache.poi.hssf.record.DefaultColWidthRecord
1736: * @see org.apache.poi.hssf.record.ColumnInfoRecord
1737: * @see #setColumnHidden(short,boolean)
1738: * @return whether the column is hidden or not.
1739: */
1740:
1741: public boolean isColumnHidden(short column) {
1742: boolean retval = false;
1743: ColumnInfoRecord ci = null;
1744:
1745: if (columns != null) {
1746: for (Iterator iterator = columns.getIterator(); iterator
1747: .hasNext();) {
1748: ci = (ColumnInfoRecord) iterator.next();
1749: if ((ci.getFirstColumn() <= column)
1750: && (column <= ci.getLastColumn())) {
1751: break;
1752: }
1753: ci = null;
1754: }
1755: }
1756: if (ci != null) {
1757: retval = ci.getHidden();
1758: }
1759: return retval;
1760: }
1761:
1762: /**
1763: * Get the hidden property for a given column.
1764: * @param column - the column number
1765: * @param hidden - whether the column is hidden or not
1766: */
1767: public void setColumnHidden(short column, boolean hidden) {
1768: setColumn(column, null, null, new Boolean(hidden), null);
1769: }
1770:
1771: public void setColumn(short column, Short width, Integer level,
1772: Boolean hidden, Boolean collapsed) {
1773: if (columns == null)
1774: columns = new ColumnInfoRecordsAggregate();
1775:
1776: columns
1777: .setColumn(column, null, width, level, hidden,
1778: collapsed);
1779: }
1780:
1781: public void setColumn(short column, Short xfStyle, Short width,
1782: Integer level, Boolean hidden, Boolean collapsed) {
1783: if (columns == null)
1784: columns = new ColumnInfoRecordsAggregate();
1785:
1786: columns.setColumn(column, xfStyle, width, level, hidden,
1787: collapsed);
1788: }
1789:
1790: /**
1791: * Creates an outline group for the specified columns.
1792: * @param fromColumn group from this column (inclusive)
1793: * @param toColumn group to this column (inclusive)
1794: * @param indent if true the group will be indented by one level,
1795: * if false indenting will be removed by one level.
1796: */
1797: public void groupColumnRange(short fromColumn, short toColumn,
1798: boolean indent) {
1799:
1800: // Set the level for each column
1801: columns.groupColumnRange(fromColumn, toColumn, indent);
1802:
1803: // Determine the maximum overall level
1804: int maxLevel = 0;
1805: int count = columns.getNumColumns();
1806: for (int k = 0; k < count; k++) {
1807: ColumnInfoRecord columnInfoRecord = columns.getColInfo(k);
1808: maxLevel = Math.max(columnInfoRecord.getOutlineLevel(),
1809: maxLevel);
1810: }
1811:
1812: GutsRecord guts = (GutsRecord) findFirstRecordBySid(GutsRecord.sid);
1813: guts.setColLevelMax((short) (maxLevel + 1));
1814: if (maxLevel == 0)
1815: guts.setTopColGutter((short) 0);
1816: else
1817: guts.setTopColGutter((short) (29 + (12 * (maxLevel - 1))));
1818: }
1819:
1820: /**
1821: * creates the Dimensions Record and sets it to bogus values (you should set this yourself
1822: * or let the high level API do it for you)
1823: * @see org.apache.poi.hssf.record.DimensionsRecord
1824: * @see org.apache.poi.hssf.record.Record
1825: * @return record containing a DimensionsRecord
1826: */
1827:
1828: protected Record createDimensions() {
1829: DimensionsRecord retval = new DimensionsRecord();
1830:
1831: retval.setFirstCol((short) 0);
1832: retval.setLastRow(1); // one more than it is
1833: retval.setFirstRow(0);
1834: retval.setLastCol((short) 1); // one more than it is
1835: return retval;
1836: }
1837:
1838: /**
1839: * creates the WindowTwo Record and sets it to: <P>
1840: * options = 0x6b6 <P>
1841: * toprow = 0 <P>
1842: * leftcol = 0 <P>
1843: * headercolor = 0x40 <P>
1844: * pagebreakzoom = 0x0 <P>
1845: * normalzoom = 0x0 <p>
1846: * @see org.apache.poi.hssf.record.WindowTwoRecord
1847: * @see org.apache.poi.hssf.record.Record
1848: * @return record containing a WindowTwoRecord
1849: */
1850:
1851: protected WindowTwoRecord createWindowTwo() {
1852: WindowTwoRecord retval = new WindowTwoRecord();
1853:
1854: retval.setOptions((short) 0x6b6);
1855: retval.setTopRow((short) 0);
1856: retval.setLeftCol((short) 0);
1857: retval.setHeaderColor(0x40);
1858: retval.setPageBreakZoom((short) 0);
1859: retval.setNormalZoom((short) 0);
1860: return retval;
1861: }
1862:
1863: /**
1864: * Creates the Selection record and sets it to nothing selected
1865: *
1866: * @see org.apache.poi.hssf.record.SelectionRecord
1867: * @see org.apache.poi.hssf.record.Record
1868: * @return record containing a SelectionRecord
1869: */
1870:
1871: protected Record createSelection() {
1872: SelectionRecord retval = new SelectionRecord();
1873:
1874: retval.setPane((byte) 0x3);
1875: retval.setActiveCellCol((short) 0x0);
1876: retval.setActiveCellRow((short) 0x0);
1877: retval.setNumRefs((short) 0x0);
1878: return retval;
1879: }
1880:
1881: public short getTopRow() {
1882: return (windowTwo == null) ? (short) 0 : windowTwo.getTopRow();
1883: }
1884:
1885: public void setTopRow(short topRow) {
1886: if (windowTwo != null) {
1887: windowTwo.setTopRow(topRow);
1888: }
1889: }
1890:
1891: /**
1892: * Sets the left column to show in desktop window pane.
1893: * @param leftCol the left column to show in desktop window pane
1894: */
1895: public void setLeftCol(short leftCol) {
1896: if (windowTwo != null) {
1897: windowTwo.setLeftCol(leftCol);
1898: }
1899: }
1900:
1901: public short getLeftCol() {
1902: return (windowTwo == null) ? (short) 0 : windowTwo.getLeftCol();
1903: }
1904:
1905: /**
1906: * Returns the active row
1907: *
1908: * @see org.apache.poi.hssf.record.SelectionRecord
1909: * @return row the active row index
1910: */
1911: public int getActiveCellRow() {
1912: if (selection == null) {
1913: return 0;
1914: }
1915: return selection.getActiveCellRow();
1916: }
1917:
1918: /**
1919: * Sets the active row
1920: *
1921: * @param row the row index
1922: * @see org.apache.poi.hssf.record.SelectionRecord
1923: */
1924: public void setActiveCellRow(int row) {
1925: //shouldn't have a sheet w/o a SelectionRecord, but best to guard anyway
1926: if (selection != null) {
1927: selection.setActiveCellRow(row);
1928: }
1929: }
1930:
1931: /**
1932: * Returns the active column
1933: *
1934: * @see org.apache.poi.hssf.record.SelectionRecord
1935: * @return row the active column index
1936: */
1937: public short getActiveCellCol() {
1938: if (selection == null) {
1939: return (short) 0;
1940: }
1941: return selection.getActiveCellCol();
1942: }
1943:
1944: /**
1945: * Sets the active column
1946: *
1947: * @param col the column index
1948: * @see org.apache.poi.hssf.record.SelectionRecord
1949: */
1950: public void setActiveCellCol(short col) {
1951: //shouldn't have a sheet w/o a SelectionRecord, but best to guard anyway
1952: if (selection != null) {
1953: selection.setActiveCellCol(col);
1954: }
1955: }
1956:
1957: protected Record createMergedCells() {
1958: MergeCellsRecord retval = new MergeCellsRecord();
1959: retval.setNumAreas((short) 0);
1960: return retval;
1961: }
1962:
1963: /**
1964: * creates the EOF record
1965: * @see org.apache.poi.hssf.record.EOFRecord
1966: * @see org.apache.poi.hssf.record.Record
1967: * @return record containing a EOFRecord
1968: */
1969:
1970: protected Record createEOF() {
1971: return new EOFRecord();
1972: }
1973:
1974: /**
1975: * get the location of the DimensionsRecord (which is the last record before the value section)
1976: * @return location in the array of records of the DimensionsRecord
1977: */
1978:
1979: public int getDimsLoc() {
1980: if (log.check(POILogger.DEBUG))
1981: log.log(POILogger.DEBUG, "getDimsLoc dimsloc= " + dimsloc);
1982: return dimsloc;
1983: }
1984:
1985: /**
1986: * in the event the record is a dimensions record, resets both the loc index and dimsloc index
1987: */
1988:
1989: public void checkDimsLoc(Record rec, int recloc) {
1990: if (rec.getSid() == DimensionsRecord.sid) {
1991: loc = recloc;
1992: dimsloc = recloc;
1993: }
1994: }
1995:
1996: public int getSize() {
1997: int retval = 0;
1998:
1999: for (int k = 0; k < records.size(); k++) {
2000: retval += ((Record) records.get(k)).getRecordSize();
2001: }
2002: //Add space for the IndexRecord
2003: if (rows != null) {
2004: final int blocks = rows.getRowBlockCount();
2005: retval += IndexRecord.getRecordSizeForBlockCount(blocks);
2006:
2007: //Add space for the DBCell records
2008: //Once DBCell per block.
2009: //8 bytes per DBCell (non variable section)
2010: //2 bytes per row reference
2011: retval += (8 * blocks);
2012: for (Iterator itr = rows.getIterator(); itr.hasNext();) {
2013: RowRecord row = (RowRecord) itr.next();
2014: if (cells != null
2015: && cells.rowHasCells(row.getRowNumber()))
2016: retval += 2;
2017: }
2018: }
2019: return retval;
2020: }
2021:
2022: public List getRecords() {
2023: return records;
2024: }
2025:
2026: /**
2027: * Gets the gridset record for this sheet.
2028: */
2029:
2030: public GridsetRecord getGridsetRecord() {
2031: return gridset;
2032: }
2033:
2034: /**
2035: * Returns the first occurance of a record matching a particular sid.
2036: */
2037:
2038: public Record findFirstRecordBySid(short sid) {
2039: for (Iterator iterator = records.iterator(); iterator.hasNext();) {
2040: Record record = (Record) iterator.next();
2041:
2042: if (record.getSid() == sid) {
2043: return record;
2044: }
2045: }
2046: return null;
2047: }
2048:
2049: /**
2050: * Sets the SCL record or creates it in the correct place if it does not
2051: * already exist.
2052: *
2053: * @param sclRecord The record to set.
2054: */
2055: public void setSCLRecord(SCLRecord sclRecord) {
2056: int oldRecordLoc = findFirstRecordLocBySid(SCLRecord.sid);
2057: if (oldRecordLoc == -1) {
2058: // Insert it after the window record
2059: int windowRecordLoc = findFirstRecordLocBySid(WindowTwoRecord.sid);
2060: records.add(windowRecordLoc + 1, sclRecord);
2061: } else {
2062: records.set(oldRecordLoc, sclRecord);
2063: }
2064:
2065: }
2066:
2067: /**
2068: * Finds the first occurance of a record matching a particular sid and
2069: * returns it's position.
2070: * @param sid the sid to search for
2071: * @return the record position of the matching record or -1 if no match
2072: * is made.
2073: */
2074: public int findFirstRecordLocBySid(short sid) {
2075: int index = 0;
2076: for (Iterator iterator = records.iterator(); iterator.hasNext();) {
2077: Record record = (Record) iterator.next();
2078:
2079: if (record.getSid() == sid) {
2080: return index;
2081: }
2082: index++;
2083: }
2084: return -1;
2085: }
2086:
2087: /**
2088: * Returns the HeaderRecord.
2089: * @return HeaderRecord for the sheet.
2090: */
2091: public HeaderRecord getHeader() {
2092: return header;
2093: }
2094:
2095: /**
2096: * Sets the HeaderRecord.
2097: * @param newHeader The new HeaderRecord for the sheet.
2098: */
2099: public void setHeader(HeaderRecord newHeader) {
2100: header = newHeader;
2101: }
2102:
2103: /**
2104: * Returns the FooterRecord.
2105: * @return FooterRecord for the sheet.
2106: */
2107: public FooterRecord getFooter() {
2108: return footer;
2109: }
2110:
2111: /**
2112: * Sets the FooterRecord.
2113: * @param newFooter The new FooterRecord for the sheet.
2114: */
2115: public void setFooter(FooterRecord newFooter) {
2116: footer = newFooter;
2117: }
2118:
2119: /**
2120: * Returns the PrintSetupRecord.
2121: * @return PrintSetupRecord for the sheet.
2122: */
2123: public PrintSetupRecord getPrintSetup() {
2124: return printSetup;
2125: }
2126:
2127: /**
2128: * Sets the PrintSetupRecord.
2129: * @param newPrintSetup The new PrintSetupRecord for the sheet.
2130: */
2131: public void setPrintSetup(PrintSetupRecord newPrintSetup) {
2132: printSetup = newPrintSetup;
2133: }
2134:
2135: /**
2136: * Returns the PrintGridlinesRecord.
2137: * @return PrintGridlinesRecord for the sheet.
2138: */
2139: public PrintGridlinesRecord getPrintGridlines() {
2140: return printGridlines;
2141: }
2142:
2143: /**
2144: * Sets the PrintGridlinesRecord.
2145: * @param newPrintGridlines The new PrintGridlinesRecord for the sheet.
2146: */
2147: public void setPrintGridlines(PrintGridlinesRecord newPrintGridlines) {
2148: printGridlines = newPrintGridlines;
2149: }
2150:
2151: /**
2152: * Sets whether the sheet is selected
2153: * @param sel True to select the sheet, false otherwise.
2154: */
2155: public void setSelected(boolean sel) {
2156: windowTwo.setSelected(sel);
2157: }
2158:
2159: /**
2160: * Gets the size of the margin in inches.
2161: * @param margin which margin to get
2162: * @return the size of the margin
2163: */
2164: public double getMargin(short margin) {
2165: if (getMargins()[margin] != null)
2166: return margins[margin].getMargin();
2167: else {
2168: switch (margin) {
2169: case LeftMargin:
2170: return .75;
2171: case RightMargin:
2172: return .75;
2173: case TopMargin:
2174: return 1.0;
2175: case BottomMargin:
2176: return 1.0;
2177: default:
2178: throw new RuntimeException("Unknown margin constant: "
2179: + margin);
2180: }
2181: }
2182: }
2183:
2184: /**
2185: * Sets the size of the margin in inches.
2186: * @param margin which margin to get
2187: * @param size the size of the margin
2188: */
2189: public void setMargin(short margin, double size) {
2190: Margin m = getMargins()[margin];
2191: if (m == null) {
2192: switch (margin) {
2193: case LeftMargin:
2194: m = new LeftMarginRecord();
2195: records.add(getDimsLoc() + 1, m);
2196: break;
2197: case RightMargin:
2198: m = new RightMarginRecord();
2199: records.add(getDimsLoc() + 1, m);
2200: break;
2201: case TopMargin:
2202: m = new TopMarginRecord();
2203: records.add(getDimsLoc() + 1, m);
2204: break;
2205: case BottomMargin:
2206: m = new BottomMarginRecord();
2207: records.add(getDimsLoc() + 1, m);
2208: break;
2209: default:
2210: throw new RuntimeException("Unknown margin constant: "
2211: + margin);
2212: }
2213: margins[margin] = m;
2214: }
2215: m.setMargin(size);
2216: }
2217:
2218: public int getEofLoc() {
2219: return eofLoc;
2220: }
2221:
2222: /**
2223: * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
2224: * @param colSplit Horizonatal position of split.
2225: * @param rowSplit Vertical position of split.
2226: * @param topRow Top row visible in bottom pane
2227: * @param leftmostColumn Left column visible in right pane.
2228: */
2229: public void createFreezePane(int colSplit, int rowSplit,
2230: int topRow, int leftmostColumn) {
2231: int paneLoc = findFirstRecordLocBySid(PaneRecord.sid);
2232: if (paneLoc != -1)
2233: records.remove(paneLoc);
2234:
2235: int loc = findFirstRecordLocBySid(WindowTwoRecord.sid);
2236: PaneRecord pane = new PaneRecord();
2237: pane.setX((short) colSplit);
2238: pane.setY((short) rowSplit);
2239: pane.setTopRow((short) topRow);
2240: pane.setLeftColumn((short) leftmostColumn);
2241: if (rowSplit == 0) {
2242: pane.setTopRow((short) 0);
2243: pane.setActivePane((short) 1);
2244: } else if (colSplit == 0) {
2245: pane.setLeftColumn((short) 64);
2246: pane.setActivePane((short) 2);
2247: } else {
2248: pane.setActivePane((short) 0);
2249: }
2250: records.add(loc + 1, pane);
2251:
2252: windowTwo.setFreezePanes(true);
2253: windowTwo.setFreezePanesNoSplit(true);
2254:
2255: SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
2256: sel.setPane((byte) pane.getActivePane());
2257:
2258: }
2259:
2260: /**
2261: * Creates a split pane. Any existing freezepane or split pane is overwritten.
2262: * @param xSplitPos Horizonatal position of split (in 1/20th of a point).
2263: * @param ySplitPos Vertical position of split (in 1/20th of a point).
2264: * @param topRow Top row visible in bottom pane
2265: * @param leftmostColumn Left column visible in right pane.
2266: * @param activePane Active pane. One of: PANE_LOWER_RIGHT,
2267: * PANE_UPPER_RIGHT, PANE_LOWER_LEFT, PANE_UPPER_LEFT
2268: * @see #PANE_LOWER_LEFT
2269: * @see #PANE_LOWER_RIGHT
2270: * @see #PANE_UPPER_LEFT
2271: * @see #PANE_UPPER_RIGHT
2272: */
2273: public void createSplitPane(int xSplitPos, int ySplitPos,
2274: int topRow, int leftmostColumn, int activePane) {
2275: int paneLoc = findFirstRecordLocBySid(PaneRecord.sid);
2276: if (paneLoc != -1)
2277: records.remove(paneLoc);
2278:
2279: int loc = findFirstRecordLocBySid(WindowTwoRecord.sid);
2280: PaneRecord r = new PaneRecord();
2281: r.setX((short) xSplitPos);
2282: r.setY((short) ySplitPos);
2283: r.setTopRow((short) topRow);
2284: r.setLeftColumn((short) leftmostColumn);
2285: r.setActivePane((short) activePane);
2286: records.add(loc + 1, r);
2287:
2288: windowTwo.setFreezePanes(false);
2289: windowTwo.setFreezePanesNoSplit(false);
2290:
2291: SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
2292: sel.setPane(PANE_LOWER_RIGHT);
2293:
2294: }
2295:
2296: /**
2297: * Returns the information regarding the currently configured pane (split or freeze).
2298: * @return null if no pane configured, or the pane information.
2299: */
2300: public PaneInformation getPaneInformation() {
2301: PaneRecord rec = (PaneRecord) findFirstRecordBySid(PaneRecord.sid);
2302: if (rec == null)
2303: return null;
2304:
2305: return new PaneInformation(rec.getX(), rec.getY(), rec
2306: .getTopRow(), rec.getLeftColumn(), (byte) rec
2307: .getActivePane(), windowTwo.getFreezePanes());
2308: }
2309:
2310: public SelectionRecord getSelection() {
2311: return selection;
2312: }
2313:
2314: public void setSelection(SelectionRecord selection) {
2315: this .selection = selection;
2316: }
2317:
2318: /**
2319: * creates a Protect record with protect set to false.
2320: * @see org.apache.poi.hssf.record.ProtectRecord
2321: * @see org.apache.poi.hssf.record.Record
2322: * @return a ProtectRecord
2323: */
2324: protected Record createProtect() {
2325: if (log.check(POILogger.DEBUG))
2326: log.log(POILogger.DEBUG,
2327: "create protect record with protection disabled");
2328: ProtectRecord retval = new ProtectRecord();
2329:
2330: retval.setProtect(false);
2331: return retval;
2332: }
2333:
2334: /**
2335: * creates an ObjectProtect record with protect set to false.
2336: * @see org.apache.poi.hssf.record.ObjectProtectRecord
2337: * @see org.apache.poi.hssf.record.Record
2338: * @return an ObjectProtectRecord
2339: */
2340: protected ObjectProtectRecord createObjectProtect() {
2341: if (log.check(POILogger.DEBUG))
2342: log.log(POILogger.DEBUG,
2343: "create protect record with protection disabled");
2344: ObjectProtectRecord retval = new ObjectProtectRecord();
2345:
2346: retval.setProtect(false);
2347: return retval;
2348: }
2349:
2350: /**
2351: * creates a ScenarioProtect record with protect set to false.
2352: * @see org.apache.poi.hssf.record.ScenarioProtectRecord
2353: * @see org.apache.poi.hssf.record.Record
2354: * @return a ScenarioProtectRecord
2355: */
2356: protected ScenarioProtectRecord createScenarioProtect() {
2357: if (log.check(POILogger.DEBUG))
2358: log.log(POILogger.DEBUG,
2359: "create protect record with protection disabled");
2360: ScenarioProtectRecord retval = new ScenarioProtectRecord();
2361:
2362: retval.setProtect(false);
2363: return retval;
2364: }
2365:
2366: /** Returns the ProtectRecord.
2367: * If one is not contained in the sheet, then one is created.
2368: */
2369: public ProtectRecord getProtect() {
2370: if (protect == null) {
2371: protect = (ProtectRecord) createProtect();
2372: //Insert the newlycreated protect record at the end of the record (just before the EOF)
2373: int loc = findFirstRecordLocBySid(EOFRecord.sid);
2374: records.add(loc, protect);
2375: }
2376: return protect;
2377: }
2378:
2379: /** Returns the PasswordRecord.
2380: * If one is not contained in the sheet, then one is created.
2381: */
2382: public PasswordRecord getPassword() {
2383: if (password == null) {
2384: password = createPassword();
2385: //Insert the newly created password record at the end of the record (just before the EOF)
2386: int loc = findFirstRecordLocBySid(EOFRecord.sid);
2387: records.add(loc, password);
2388: }
2389: return password;
2390: }
2391:
2392: /**
2393: * creates a Password record with password set to 00.
2394: * @see org.apache.poi.hssf.record.PasswordRecord
2395: * @see org.apache.poi.hssf.record.Record
2396: * @return a PasswordRecord
2397: */
2398: protected PasswordRecord createPassword() {
2399: if (log.check(POILogger.DEBUG))
2400: log.log(POILogger.DEBUG,
2401: "create password record with 00 password");
2402: PasswordRecord retval = new PasswordRecord();
2403:
2404: retval.setPassword((short) 00);
2405: return retval;
2406: }
2407:
2408: /**
2409:
2410: /**
2411: * Sets whether the gridlines are shown in a viewer.
2412: * @param show whether to show gridlines or not
2413: */
2414: public void setDisplayGridlines(boolean show) {
2415: windowTwo.setDisplayGridlines(show);
2416: }
2417:
2418: /**
2419: * Returns if gridlines are displayed.
2420: * @return whether gridlines are displayed
2421: */
2422: public boolean isDisplayGridlines() {
2423: return windowTwo.getDisplayGridlines();
2424: }
2425:
2426: /**
2427: * Sets whether the formulas are shown in a viewer.
2428: * @param show whether to show formulas or not
2429: */
2430: public void setDisplayFormulas(boolean show) {
2431: windowTwo.setDisplayFormulas(show);
2432: }
2433:
2434: /**
2435: * Returns if formulas are displayed.
2436: * @return whether formulas are displayed
2437: */
2438: public boolean isDisplayFormulas() {
2439: return windowTwo.getDisplayFormulas();
2440: }
2441:
2442: /**
2443: * Sets whether the RowColHeadings are shown in a viewer.
2444: * @param show whether to show RowColHeadings or not
2445: */
2446: public void setDisplayRowColHeadings(boolean show) {
2447: windowTwo.setDisplayRowColHeadings(show);
2448: }
2449:
2450: /**
2451: * Returns if RowColHeadings are displayed.
2452: * @return whether RowColHeadings are displayed
2453: */
2454: public boolean isDisplayRowColHeadings() {
2455: return windowTwo.getDisplayRowColHeadings();
2456: }
2457:
2458: /**
2459: * Returns the array of margins. If not created, will create.
2460: *
2461: * @return the array of marings.
2462: */
2463: protected Margin[] getMargins() {
2464: if (margins == null)
2465: margins = new Margin[4];
2466: return margins;
2467: }
2468:
2469: public int aggregateDrawingRecords(DrawingManager2 drawingManager) {
2470: int loc = findFirstRecordLocBySid(DrawingRecord.sid);
2471: boolean noDrawingRecordsFound = loc == -1;
2472: if (noDrawingRecordsFound) {
2473: EscherAggregate aggregate = new EscherAggregate(
2474: drawingManager);
2475: loc = findFirstRecordLocBySid(EscherAggregate.sid);
2476: if (loc == -1) {
2477: loc = findFirstRecordLocBySid(WindowTwoRecord.sid);
2478: } else {
2479: getRecords().remove(loc);
2480: }
2481: getRecords().add(loc, aggregate);
2482: return loc;
2483: } else {
2484: List records = getRecords();
2485: EscherAggregate r = EscherAggregate.createAggregate(
2486: records, loc, drawingManager);
2487: int startloc = loc;
2488: while (loc + 1 < records.size()
2489: && records.get(loc) instanceof DrawingRecord
2490: && records.get(loc + 1) instanceof ObjRecord) {
2491: loc += 2;
2492: }
2493: int endloc = loc - 1;
2494: for (int i = 0; i < (endloc - startloc + 1); i++)
2495: records.remove(startloc);
2496: records.add(startloc, r);
2497:
2498: return startloc;
2499: }
2500: }
2501:
2502: /**
2503: * Perform any work necessary before the sheet is about to be serialized.
2504: * For instance the escher aggregates size needs to be calculated before
2505: * serialization so that the dgg record (which occurs first) can be written.
2506: */
2507: public void preSerialize() {
2508: for (Iterator iterator = getRecords().iterator(); iterator
2509: .hasNext();) {
2510: Record r = (Record) iterator.next();
2511: if (r instanceof EscherAggregate)
2512: r.getRecordSize(); // Trigger flatterning of user model and corresponding update of dgg record.
2513: }
2514: }
2515:
2516: /**
2517: * Shifts all the page breaks in the range "count" number of rows/columns
2518: * @param breaks The page record to be shifted
2519: * @param start Starting "main" value to shift breaks
2520: * @param stop Ending "main" value to shift breaks
2521: * @param count number of units (rows/columns) to shift by
2522: */
2523: public void shiftBreaks(PageBreakRecord breaks, short start,
2524: short stop, int count) {
2525:
2526: if (rowBreaks == null)
2527: return;
2528: Iterator iterator = breaks.getBreaksIterator();
2529: List shiftedBreak = new ArrayList();
2530: while (iterator.hasNext()) {
2531: PageBreakRecord.Break breakItem = (PageBreakRecord.Break) iterator
2532: .next();
2533: short breakLocation = breakItem.main;
2534: boolean inStart = (breakLocation >= start);
2535: boolean inEnd = (breakLocation <= stop);
2536: if (inStart && inEnd)
2537: shiftedBreak.add(breakItem);
2538: }
2539:
2540: iterator = shiftedBreak.iterator();
2541: while (iterator.hasNext()) {
2542: PageBreakRecord.Break breakItem = (PageBreakRecord.Break) iterator
2543: .next();
2544: breaks.removeBreak(breakItem.main);
2545: breaks.addBreak((short) (breakItem.main + count),
2546: breakItem.subFrom, breakItem.subTo);
2547: }
2548: }
2549:
2550: /**
2551: * Sets a page break at the indicated row
2552: * @param row
2553: */
2554: public void setRowBreak(int row, short fromCol, short toCol) {
2555: if (rowBreaks == null) {
2556: int loc = findFirstRecordLocBySid(WindowTwoRecord.sid);
2557: rowBreaks = new PageBreakRecord(
2558: PageBreakRecord.HORIZONTAL_SID);
2559: records.add(loc, rowBreaks);
2560: }
2561: rowBreaks.addBreak((short) row, fromCol, toCol);
2562: }
2563:
2564: /**
2565: * Removes a page break at the indicated row
2566: * @param row
2567: */
2568: public void removeRowBreak(int row) {
2569: if (rowBreaks == null)
2570: throw new IllegalArgumentException(
2571: "Sheet does not define any row breaks");
2572: rowBreaks.removeBreak((short) row);
2573: }
2574:
2575: /**
2576: * Queries if the specified row has a page break
2577: * @param row
2578: * @return true if the specified row has a page break
2579: */
2580: public boolean isRowBroken(int row) {
2581: return (rowBreaks == null) ? false : rowBreaks
2582: .getBreak((short) row) != null;
2583: }
2584:
2585: /**
2586: * Sets a page break at the indicated column
2587: *
2588: */
2589: public void setColumnBreak(short column, short fromRow, short toRow) {
2590: if (colBreaks == null) {
2591: int loc = findFirstRecordLocBySid(WindowTwoRecord.sid);
2592: colBreaks = new PageBreakRecord(
2593: PageBreakRecord.VERTICAL_SID);
2594: records.add(loc, colBreaks);
2595: }
2596: colBreaks.addBreak(column, fromRow, toRow);
2597: }
2598:
2599: /**
2600: * Removes a page break at the indicated column
2601: *
2602: */
2603: public void removeColumnBreak(short column) {
2604: if (colBreaks == null)
2605: throw new IllegalArgumentException(
2606: "Sheet does not define any column breaks");
2607:
2608: colBreaks.removeBreak(column);
2609: }
2610:
2611: /**
2612: * Queries if the specified column has a page break
2613: *
2614: * @return true if the specified column has a page break
2615: */
2616: public boolean isColumnBroken(short column) {
2617: return (colBreaks == null) ? false
2618: : colBreaks.getBreak(column) != null;
2619: }
2620:
2621: /**
2622: * Shifts the horizontal page breaks for the indicated count
2623: * @param startingRow
2624: * @param endingRow
2625: * @param count
2626: */
2627: public void shiftRowBreaks(int startingRow, int endingRow, int count) {
2628: shiftBreaks(rowBreaks, (short) startingRow, (short) endingRow,
2629: (short) count);
2630: }
2631:
2632: /**
2633: * Shifts the vertical page breaks for the indicated count
2634: * @param startingCol
2635: * @param endingCol
2636: * @param count
2637: */
2638: public void shiftColumnBreaks(short startingCol, short endingCol,
2639: short count) {
2640: shiftBreaks(colBreaks, startingCol, endingCol, count);
2641: }
2642:
2643: /**
2644: * Returns all the row page breaks
2645: * @return all the row page breaks
2646: */
2647: public Iterator getRowBreaks() {
2648: return rowBreaks.getBreaksIterator();
2649: }
2650:
2651: /**
2652: * Returns the number of row page breaks
2653: * @return the number of row page breaks
2654: */
2655: public int getNumRowBreaks() {
2656: return (rowBreaks == null) ? 0 : (int) rowBreaks.getNumBreaks();
2657: }
2658:
2659: /**
2660: * Returns all the column page breaks
2661: * @return all the column page breaks
2662: */
2663: public Iterator getColumnBreaks() {
2664: return colBreaks.getBreaksIterator();
2665: }
2666:
2667: /**
2668: * Returns the number of column page breaks
2669: * @return the number of column page breaks
2670: */
2671: public int getNumColumnBreaks() {
2672: return (colBreaks == null) ? 0 : (int) colBreaks.getNumBreaks();
2673: }
2674:
2675: public void setColumnGroupCollapsed(short columnNumber,
2676: boolean collapsed) {
2677: if (collapsed) {
2678: columns.collapseColumn(columnNumber);
2679: } else {
2680: columns.expandColumn(columnNumber);
2681: }
2682: }
2683:
2684: /**
2685: * protect a spreadsheet with a password (not encypted, just sets protect
2686: * flags and the password.
2687: * @param password to set
2688: * @param objects are protected
2689: * @param scenarios are protected
2690: */
2691: public void protectSheet(String password, boolean objects,
2692: boolean scenarios) {
2693: int protIdx = -1;
2694: ProtectRecord prec = getProtect();
2695: PasswordRecord pass = getPassword();
2696: prec.setProtect(true);
2697: pass.setPassword(PasswordRecord.hashPassword(password));
2698: if ((objprotect == null && objects)
2699: || (scenprotect != null && scenarios)) {
2700: protIdx = records.indexOf(protect);
2701: }
2702: if (objprotect == null && objects) {
2703: ObjectProtectRecord rec = createObjectProtect();
2704: rec.setProtect(true);
2705: records.add(protIdx + 1, rec);
2706: objprotect = rec;
2707: }
2708: if (scenprotect == null && scenarios) {
2709: ScenarioProtectRecord srec = createScenarioProtect();
2710: srec.setProtect(true);
2711: records.add(protIdx + 2, srec);
2712: scenprotect = srec;
2713: }
2714: }
2715:
2716: /**
2717: * unprotect objects in the sheet (will not protect them, but any set to false are
2718: * unprotected.
2719: * @param sheet is unprotected (false = unprotect)
2720: * @param objects are unprotected (false = unprotect)
2721: * @param scenarios are unprotected (false = unprotect)
2722: */
2723: public void unprotectSheet(boolean sheet, boolean objects,
2724: boolean scenarios) {
2725: int protIdx = -1;
2726: if (!sheet) {
2727: ProtectRecord prec = getProtect();
2728: prec.setProtect(sheet);
2729: PasswordRecord pass = getPassword();
2730: pass.setPassword((short) 00);
2731: }
2732: if (objprotect != null && !objects) {
2733: objprotect.setProtect(false);
2734: }
2735: if (scenprotect != null && !scenarios) {
2736: scenprotect.setProtect(false);
2737: }
2738: }
2739:
2740: /**
2741: * @return {sheet is protected, objects are proteced, scenarios are protected}
2742: */
2743: public boolean[] isProtected() {
2744: return new boolean[] {
2745: (protect != null && protect.getProtect()),
2746: (objprotect != null && objprotect.getProtect()),
2747: (scenprotect != null && scenprotect.getProtect()) };
2748: }
2749:
2750: // private void collapseColumn( short columnNumber )
2751: // {
2752: // int idx = findColumnIdx( columnNumber, 0 );
2753: // if (idx == -1)
2754: // return;
2755: //
2756: // // Find the start of the group.
2757: // ColumnInfoRecord columnInfo = (ColumnInfoRecord) columnSizes.get( findStartOfColumnOutlineGroup( idx ) );
2758: //
2759: // // Hide all the columns until the end of the group
2760: // columnInfo = writeHidden( columnInfo, idx, true );
2761: //
2762: // // Write collapse field
2763: // setColumn( (short) ( columnInfo.getLastColumn() + 1 ), null, null, null, Boolean.TRUE);
2764: // }
2765:
2766: // private void expandColumn( short columnNumber )
2767: // {
2768: // int idx = findColumnIdx( columnNumber, 0 );
2769: // if (idx == -1)
2770: // return;
2771: //
2772: // // If it is already exapanded do nothing.
2773: // if (!isColumnGroupCollapsed(idx))
2774: // return;
2775: //
2776: // // Find the start of the group.
2777: // int startIdx = findStartOfColumnOutlineGroup( idx );
2778: // ColumnInfoRecord columnInfo = getColInfo( startIdx );
2779: //
2780: // // Find the end of the group.
2781: // int endIdx = findEndOfColumnOutlineGroup( idx );
2782: // ColumnInfoRecord endColumnInfo = getColInfo( endIdx );
2783: //
2784: // // expand:
2785: // // colapsed bit must be unset
2786: // // hidden bit gets unset _if_ surrounding groups are expanded you can determine
2787: // // this by looking at the hidden bit of the enclosing group. You will have
2788: // // to look at the start and the end of the current group to determine which
2789: // // is the enclosing group
2790: // // hidden bit only is altered for this outline level. ie. don't uncollapse contained groups
2791: // if (!isColumnGroupHiddenByParent( idx ))
2792: // {
2793: // for (int i = startIdx; i <= endIdx; i++)
2794: // {
2795: // if (columnInfo.getOutlineLevel() == getColInfo(i).getOutlineLevel())
2796: // getColInfo(i).setHidden( false );
2797: // }
2798: // }
2799: //
2800: // // Write collapse field
2801: // setColumn( (short) ( columnInfo.getLastColumn() + 1 ), null, null, null, Boolean.FALSE);
2802: // }
2803:
2804: // private boolean isColumnGroupCollapsed( int idx )
2805: // {
2806: // int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup( idx );
2807: // if (endOfOutlineGroupIdx >= columnSizes.size())
2808: // return false;
2809: // if (getColInfo(endOfOutlineGroupIdx).getLastColumn() + 1 != getColInfo(endOfOutlineGroupIdx + 1).getFirstColumn())
2810: // return false;
2811: // else
2812: // return getColInfo(endOfOutlineGroupIdx+1).getCollapsed();
2813: // }
2814:
2815: // private boolean isColumnGroupHiddenByParent( int idx )
2816: // {
2817: // // Look out outline details of end
2818: // int endLevel;
2819: // boolean endHidden;
2820: // int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup( idx );
2821: // if (endOfOutlineGroupIdx >= columnSizes.size())
2822: // {
2823: // endLevel = 0;
2824: // endHidden = false;
2825: // }
2826: // else if (getColInfo(endOfOutlineGroupIdx).getLastColumn() + 1 != getColInfo(endOfOutlineGroupIdx + 1).getFirstColumn())
2827: // {
2828: // endLevel = 0;
2829: // endHidden = false;
2830: // }
2831: // else
2832: // {
2833: // endLevel = getColInfo( endOfOutlineGroupIdx + 1).getOutlineLevel();
2834: // endHidden = getColInfo( endOfOutlineGroupIdx + 1).getHidden();
2835: // }
2836: //
2837: // // Look out outline details of start
2838: // int startLevel;
2839: // boolean startHidden;
2840: // int startOfOutlineGroupIdx = findStartOfColumnOutlineGroup( idx );
2841: // if (startOfOutlineGroupIdx <= 0)
2842: // {
2843: // startLevel = 0;
2844: // startHidden = false;
2845: // }
2846: // else if (getColInfo(startOfOutlineGroupIdx).getFirstColumn() - 1 != getColInfo(startOfOutlineGroupIdx - 1).getLastColumn())
2847: // {
2848: // startLevel = 0;
2849: // startHidden = false;
2850: // }
2851: // else
2852: // {
2853: // startLevel = getColInfo( startOfOutlineGroupIdx - 1).getOutlineLevel();
2854: // startHidden = getColInfo( startOfOutlineGroupIdx - 1 ).getHidden();
2855: // }
2856: //
2857: // if (endLevel > startLevel)
2858: // {
2859: // return endHidden;
2860: // }
2861: // else
2862: // {
2863: // return startHidden;
2864: // }
2865: // }
2866:
2867: // private ColumnInfoRecord getColInfo(int idx)
2868: // {
2869: // return columns.getColInfo( idx );
2870: // }
2871:
2872: // private int findStartOfColumnOutlineGroup(int idx)
2873: // {
2874: // // Find the start of the group.
2875: // ColumnInfoRecord columnInfo = (ColumnInfoRecord) columnSizes.get( idx );
2876: // int level = columnInfo.getOutlineLevel();
2877: // while (idx != 0)
2878: // {
2879: // ColumnInfoRecord prevColumnInfo = (ColumnInfoRecord) columnSizes.get( idx - 1 );
2880: // if (columnInfo.getFirstColumn() - 1 == prevColumnInfo.getLastColumn())
2881: // {
2882: // if (prevColumnInfo.getOutlineLevel() < level)
2883: // {
2884: // break;
2885: // }
2886: // idx--;
2887: // columnInfo = prevColumnInfo;
2888: // }
2889: // else
2890: // {
2891: // break;
2892: // }
2893: // }
2894: //
2895: // return idx;
2896: // }
2897:
2898: // private int findEndOfColumnOutlineGroup(int idx)
2899: // {
2900: // // Find the end of the group.
2901: // ColumnInfoRecord columnInfo = (ColumnInfoRecord) columnSizes.get( idx );
2902: // int level = columnInfo.getOutlineLevel();
2903: // while (idx < columnSizes.size() - 1)
2904: // {
2905: // ColumnInfoRecord nextColumnInfo = (ColumnInfoRecord) columnSizes.get( idx + 1 );
2906: // if (columnInfo.getLastColumn() + 1 == nextColumnInfo.getFirstColumn())
2907: // {
2908: // if (nextColumnInfo.getOutlineLevel() < level)
2909: // {
2910: // break;
2911: // }
2912: // idx++;
2913: // columnInfo = nextColumnInfo;
2914: // }
2915: // else
2916: // {
2917: // break;
2918: // }
2919: // }
2920: //
2921: // return idx;
2922: // }
2923:
2924: public void groupRowRange(int fromRow, int toRow, boolean indent) {
2925: checkRows();
2926: for (int rowNum = fromRow; rowNum <= toRow; rowNum++) {
2927: RowRecord row = getRow(rowNum);
2928: if (row == null) {
2929: row = createRow(rowNum);
2930: addRow(row);
2931: }
2932: int level = row.getOutlineLevel();
2933: if (indent)
2934: level++;
2935: else
2936: level--;
2937: level = Math.max(0, level);
2938: level = Math.min(7, level);
2939: row.setOutlineLevel((short) (level));
2940: }
2941:
2942: recalcRowGutter();
2943: }
2944:
2945: private void recalcRowGutter() {
2946: int maxLevel = 0;
2947: Iterator iterator = rows.getIterator();
2948: while (iterator.hasNext()) {
2949: RowRecord rowRecord = (RowRecord) iterator.next();
2950: maxLevel = Math.max(rowRecord.getOutlineLevel(), maxLevel);
2951: }
2952:
2953: GutsRecord guts = (GutsRecord) findFirstRecordBySid(GutsRecord.sid);
2954: guts.setRowLevelMax((short) (maxLevel + 1));
2955: guts.setLeftRowGutter((short) (29 + (12 * (maxLevel))));
2956: }
2957:
2958: public void setRowGroupCollapsed(int row, boolean collapse) {
2959: if (collapse) {
2960: rows.collapseRow(row);
2961: } else {
2962: rows.expandRow(row);
2963: }
2964: }
2965:
2966: // private void collapseRow( int rowNumber )
2967: // {
2968: //
2969: // // Find the start of the group.
2970: // int startRow = rows.findStartOfRowOutlineGroup( rowNumber );
2971: // RowRecord rowRecord = (RowRecord) rows.getRow( startRow );
2972: //
2973: // // Hide all the columns until the end of the group
2974: // int lastRow = rows.writeHidden( rowRecord, startRow, true );
2975: //
2976: // // Write collapse field
2977: // if (getRow(lastRow + 1) != null)
2978: // {
2979: // getRow(lastRow + 1).setColapsed( true );
2980: // }
2981: // else
2982: // {
2983: // RowRecord row = createRow( lastRow + 1);
2984: // row.setColapsed( true );
2985: // rows.insertRow( row );
2986: // }
2987: // }
2988:
2989: // private int findStartOfRowOutlineGroup(int row)
2990: // {
2991: // // Find the start of the group.
2992: // RowRecord rowRecord = rows.getRow( row );
2993: // int level = rowRecord.getOutlineLevel();
2994: // int currentRow = row;
2995: // while (rows.getRow( currentRow ) != null)
2996: // {
2997: // rowRecord = rows.getRow( currentRow );
2998: // if (rowRecord.getOutlineLevel() < level)
2999: // return currentRow + 1;
3000: // currentRow--;
3001: // }
3002: //
3003: // return currentRow + 1;
3004: // }
3005:
3006: // private int writeHidden( RowRecord rowRecord, int row, boolean hidden )
3007: // {
3008: // int level = rowRecord.getOutlineLevel();
3009: // while (rowRecord != null && rows.getRow(row).getOutlineLevel() >= level)
3010: // {
3011: // rowRecord.setZeroHeight( hidden );
3012: // row++;
3013: // rowRecord = rows.getRow( row );
3014: // }
3015: // return row - 1;
3016: // }
3017:
3018: // private int findEndOfRowOutlineGroup( int row )
3019: // {
3020: // int level = getRow( row ).getOutlineLevel();
3021: // int currentRow;
3022: // for (currentRow = row; currentRow < rows.getLastRowNum(); currentRow++)
3023: // {
3024: // if (getRow(currentRow) == null || getRow(currentRow).getOutlineLevel() < level)
3025: // {
3026: // break;
3027: // }
3028: // }
3029: //
3030: // return currentRow-1;
3031: // }
3032:
3033: // private boolean isRowGroupCollapsed( int row )
3034: // {
3035: // int collapseRow = rows.findEndOfRowOutlineGroup( row ) + 1;
3036: //
3037: // if (getRow(collapseRow) == null)
3038: // return false;
3039: // else
3040: // return getRow( collapseRow ).getColapsed();
3041: // }
3042:
3043: // private boolean isRowGroupHiddenByParent( int row )
3044: // {
3045: // // Look out outline details of end
3046: // int endLevel;
3047: // boolean endHidden;
3048: // int endOfOutlineGroupIdx = rows.findEndOfRowOutlineGroup( row );
3049: // if (getRow( endOfOutlineGroupIdx + 1 ) == null)
3050: // {
3051: // endLevel = 0;
3052: // endHidden = false;
3053: // }
3054: // else
3055: // {
3056: // endLevel = getRow( endOfOutlineGroupIdx + 1).getOutlineLevel();
3057: // endHidden = getRow( endOfOutlineGroupIdx + 1).getZeroHeight();
3058: // }
3059: //
3060: // // Look out outline details of start
3061: // int startLevel;
3062: // boolean startHidden;
3063: // int startOfOutlineGroupIdx = rows.findStartOfRowOutlineGroup( row );
3064: // if (startOfOutlineGroupIdx - 1 < 0 || getRow(startOfOutlineGroupIdx - 1) == null)
3065: // {
3066: // startLevel = 0;
3067: // startHidden = false;
3068: // }
3069: // else
3070: // {
3071: // startLevel = getRow( startOfOutlineGroupIdx - 1).getOutlineLevel();
3072: // startHidden = getRow( startOfOutlineGroupIdx - 1 ).getZeroHeight();
3073: // }
3074: //
3075: // if (endLevel > startLevel)
3076: // {
3077: // return endHidden;
3078: // }
3079: // else
3080: // {
3081: // return startHidden;
3082: // }
3083: // }
3084:
3085: }
|