KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > poi > hssf > model > Sheet


1
2 /* ====================================================================
3    Copyright 2002-2004 Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16 ==================================================================== */

17
18
19 package org.apache.poi.hssf.model;
20
21 import org.apache.poi.hssf.record.*;
22 import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
23 import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
24 import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
25 import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
26 import org.apache.poi.hssf.record.formula.Ptg;
27 import org.apache.poi.util.POILogFactory;
28 import org.apache.poi.util.POILogger;
29
30 import java.util.ArrayList JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33
34 /**
35  * Low level model implementation of a Sheet (one workbook contains many sheets)
36  * This file contains the low level binary records starting at the sheets BOF and
37  * ending with the sheets EOF. Use HSSFSheet for a high level representation.
38  * <P>
39  * The structures of the highlevel API use references to this to perform most of their
40  * operations. Its probably unwise to use these low level structures directly unless you
41  * really know what you're doing. I recommend you read the Microsoft Excel 97 Developer's
42  * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf
43  * before even attempting to use this.
44  * <P>
45  * @author Andrew C. Oliver (acoliver at apache dot org)
46  * @author Glen Stampoultzis (glens at apache.org)
47  * @author Shawn Laubach (slaubach at apache dot org) Gridlines, Headers, Footers, and PrintSetup
48  * @author Jason Height (jheight at chariot dot net dot au) Clone support. DBCell & Index Record writing support
49  * @author Brian Sanders (kestrel at burdell dot org) Active Cell support
50  *
51  * @see org.apache.poi.hssf.model.Workbook
52  * @see org.apache.poi.hssf.usermodel.HSSFSheet
53  * @version 1.0-pre
54  */

55
56 public class Sheet implements Model
57 {
58     public static final short LeftMargin = 0;
59     public static final short RightMargin = 1;
60     public static final short TopMargin = 2;
61     public static final short BottomMargin = 3;
62
63     private static POILogger log = POILogFactory.getLogger(Sheet.class);
64
65     protected ArrayList JavaDoc records = null;
66               int preoffset = 0; // offset of the sheet in a new file
67
int loc = 0;
68     protected boolean containsLabels = false;
69     protected int dimsloc = 0;
70     protected DimensionsRecord dims;
71     protected DefaultColWidthRecord defaultcolwidth = null;
72     protected DefaultRowHeightRecord defaultrowheight = null;
73     protected GridsetRecord gridset = null;
74     protected PrintSetupRecord printSetup = null;
75     protected HeaderRecord header = null;
76     protected FooterRecord footer = null;
77     protected PrintGridlinesRecord printGridlines = null;
78     protected WindowTwoRecord windowTwo = null;
79     protected MergeCellsRecord merged = null;
80     protected Margin[] margins = null;
81     protected List JavaDoc mergedRecords = new ArrayList JavaDoc();
82     protected int numMergedRegions = 0;
83     protected SelectionRecord selection = null;
84     protected ColumnInfoRecordsAggregate columns = null;
85     protected ValueRecordsAggregate cells = null;
86     protected RowRecordsAggregate rows = null;
87     private Iterator JavaDoc valueRecIterator = null;
88     private Iterator JavaDoc rowRecIterator = null;
89     protected int eofLoc = 0;
90     protected ProtectRecord protect = null;
91     protected PageBreakRecord rowBreaks = null;
92     protected PageBreakRecord colBreaks = null;
93
94     
95     public static final byte PANE_LOWER_RIGHT = (byte)0;
96     public static final byte PANE_UPPER_RIGHT = (byte)1;
97     public static final byte PANE_LOWER_LEFT = (byte)2;
98     public static final byte PANE_UPPER_LEFT = (byte)3;
99
100     /**
101      * Creates new Sheet with no intialization --useless at this point
102      * @see #createSheet(List,int,int)
103      */

104     public Sheet()
105     {
106     }
107
108     /**
109      * read support (offset used as starting point for search) for low level
110      * API. Pass in an array of Record objects, the sheet number (0 based) and
111      * a record offset (should be the location of the sheets BOF record). A Sheet
112      * object is constructed and passed back with all of its initialization set
113      * to the passed in records and references to those records held. This function
114      * is normally called via Workbook.
115      *
116      * @param recs array containing those records in the sheet in sequence (normally obtained from RecordFactory)
117      * @param sheetnum integer specifying the sheet's number (0,1 or 2 in this release)
118      * @param offset of the sheet's BOF record
119      *
120      * @return Sheet object with all values set to those read from the file
121      *
122      * @see org.apache.poi.hssf.model.Workbook
123      * @see org.apache.poi.hssf.record.Record
124      */

125     public static Sheet createSheet(List JavaDoc recs, int sheetnum, int offset)
126     {
127         if (log.check( POILogger.DEBUG ))
128             log.logFormatted(POILogger.DEBUG,
129                     "Sheet createSheet (existing file) with %",
130                     new Integer JavaDoc(recs.size()));
131         Sheet retval = new Sheet();
132         ArrayList JavaDoc records = new ArrayList JavaDoc(recs.size() / 5);
133         boolean isfirstcell = true;
134         boolean isfirstrow = true;
135         int bofEofNestingLevel = 0;
136
137         for (int k = offset; k < recs.size(); k++)
138         {
139             Record rec = ( Record ) recs.get(k);
140
141             if (rec.getSid() == LabelRecord.sid)
142             {
143                 if (log.check( POILogger.DEBUG ))
144                     log.log(POILogger.DEBUG, "Hit label record.");
145                 retval.containsLabels = true;
146             }
147             else if (rec.getSid() == BOFRecord.sid)
148             {
149                 bofEofNestingLevel++;
150                 if (log.check( POILogger.DEBUG ))
151                     log.log(POILogger.DEBUG, "Hit BOF record. Nesting increased to " + bofEofNestingLevel);
152             }
153             else if (rec.getSid() == EOFRecord.sid)
154             {
155                 --bofEofNestingLevel;
156                 if (log.check( POILogger.DEBUG ))
157                     log.log(POILogger.DEBUG, "Hit EOF record. Nesting decreased to " + bofEofNestingLevel);
158                 if (bofEofNestingLevel == 0) {
159                     records.add(rec);
160                     retval.eofLoc = k;
161                     break;
162                 }
163             }
164             else if (rec.getSid() == DimensionsRecord.sid)
165             {
166                 // Make a columns aggregate if one hasn't ready been created.
167
if (retval.columns == null)
168                 {
169                     retval.columns = new ColumnInfoRecordsAggregate();
170                     records.add(retval.columns);
171                 }
172
173                 retval.dims = ( DimensionsRecord ) rec;
174                 retval.dimsloc = records.size();
175             }
176             else if (rec.getSid() == MergeCellsRecord.sid)
177             {
178                 retval.mergedRecords.add(rec);
179                 retval.merged = ( MergeCellsRecord ) rec;
180                 retval.numMergedRegions += retval.merged.getNumAreas();
181             }
182             else if (rec.getSid() == ColumnInfoRecord.sid)
183             {
184                 ColumnInfoRecord col = (ColumnInfoRecord)rec;
185                 if (retval.columns != null)
186                 {
187                     rec = null; //only add the aggregate once
188
}
189                 else
190                 {
191                     rec = retval.columns = new ColumnInfoRecordsAggregate();
192                 }
193                 retval.columns.insertColumn(col);
194             }
195             else if (rec.getSid() == DefaultColWidthRecord.sid)
196             {
197                 retval.defaultcolwidth = ( DefaultColWidthRecord ) rec;
198             }
199             else if (rec.getSid() == DefaultRowHeightRecord.sid)
200             {
201                 retval.defaultrowheight = ( DefaultRowHeightRecord ) rec;
202             }
203             else if ( rec.isValue() && bofEofNestingLevel == 1 )
204             {
205                 if ( isfirstcell )
206                 {
207                     retval.cells = new ValueRecordsAggregate();
208                     rec = retval.cells;
209                     retval.cells.construct( k, recs );
210                     isfirstcell = false;
211                 }
212                 else
213                 {
214                     rec = null;
215                 }
216             }
217             else if ( rec.getSid() == StringRecord.sid )
218             {
219                 rec = null;
220             }
221             else if ( rec.getSid() == RowRecord.sid )
222             {
223                 RowRecord row = (RowRecord)rec;
224                 if (!isfirstrow) rec = null; //only add the aggregate once
225

226                 if ( isfirstrow )
227                 {
228                     retval.rows = new RowRecordsAggregate();
229                     rec = retval.rows;
230                     isfirstrow = false;
231                 }
232                 retval.rows.insertRow(row);
233             }
234             else if ( rec.getSid() == PrintGridlinesRecord.sid )
235             {
236                 retval.printGridlines = (PrintGridlinesRecord) rec;
237             }
238             else if ( rec.getSid() == HeaderRecord.sid && bofEofNestingLevel == 1)
239             {
240                 retval.header = (HeaderRecord) rec;
241             }
242             else if ( rec.getSid() == FooterRecord.sid && bofEofNestingLevel == 1)
243             {
244                 retval.footer = (FooterRecord) rec;
245             }
246             else if ( rec.getSid() == PrintSetupRecord.sid && bofEofNestingLevel == 1)
247             {
248                 retval.printSetup = (PrintSetupRecord) rec;
249             }
250             else if ( rec.getSid() == LeftMarginRecord.sid)
251             {
252                 retval.getMargins()[LeftMargin] = (LeftMarginRecord) rec;
253             }
254             else if ( rec.getSid() == RightMarginRecord.sid)
255             {
256                 retval.getMargins()[RightMargin] = (RightMarginRecord) rec;
257             }
258             else if ( rec.getSid() == TopMarginRecord.sid)
259             {
260                 retval.getMargins()[TopMargin] = (TopMarginRecord) rec;
261             }
262             else if ( rec.getSid() == BottomMarginRecord.sid)
263             {
264                 retval.getMargins()[BottomMargin] = (BottomMarginRecord) rec;
265             }
266             else if ( rec.getSid() == SelectionRecord.sid )
267             {
268                 retval.selection = (SelectionRecord) rec;
269             }
270             else if ( rec.getSid() == WindowTwoRecord.sid )
271             {
272                 retval.windowTwo = (WindowTwoRecord) rec;
273             }
274             else if ( rec.getSid() == DBCellRecord.sid )
275             {
276                 rec = null;
277             }
278             else if ( rec.getSid() == IndexRecord.sid )
279             {
280                 rec = null;
281             }
282             
283             else if ( rec.getSid() == ProtectRecord.sid )
284             {
285                 retval.protect = (ProtectRecord) rec;
286             }
287             else if (rec.getSid() == PageBreakRecord.HORIZONTAL_SID)
288             {
289                 retval.rowBreaks = (PageBreakRecord)rec;
290             }
291             else if (rec.getSid() == PageBreakRecord.VERTICAL_SID)
292             {
293                 retval.colBreaks = (PageBreakRecord)rec;
294             }
295             
296             if (rec != null)
297             {
298                 records.add(rec);
299             }
300         }
301         retval.records = records;
302 // if (retval.rows == null)
303
// {
304
// retval.rows = new RowRecordsAggregate();
305
// }
306
retval.checkCells();
307         retval.checkRows();
308 // if (retval.cells == null)
309
// {
310
// retval.cells = new ValueRecordsAggregate();
311
// }
312
if (log.check( POILogger.DEBUG ))
313             log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited");
314         return retval;
315     }
316
317     /**
318      * Clones the low level records of this sheet and returns the new sheet instance.
319      * This method is implemented by adding methods for deep cloning to all records that
320      * can be added to a sheet. The <b>Record</b> object does not implement cloneable.
321      * When adding a new record, implement a public clone method if and only if the record
322      * belongs to a sheet.
323      */

324     public Sheet cloneSheet()
325     {
326       ArrayList JavaDoc clonedRecords = new ArrayList JavaDoc(this.records.size());
327       for (int i=0; i<this.records.size();i++) {
328         Record rec = (Record)((Record)this.records.get(i)).clone();
329         //Need to pull out the Row record and the Value records from their
330
//Aggregates.
331
//This is probably the best way to do it since we probably dont want the createSheet
332
//To cater for these artificial Record types
333
if (rec instanceof RowRecordsAggregate) {
334           RowRecordsAggregate rrAgg = (RowRecordsAggregate)rec;
335           for (Iterator JavaDoc rowIter = rrAgg.getIterator();rowIter.hasNext();) {
336             Record rowRec = (Record)rowIter.next();
337             clonedRecords.add(rowRec);
338           }
339         } else if (rec instanceof ValueRecordsAggregate) {
340           ValueRecordsAggregate vrAgg = (ValueRecordsAggregate)rec;
341           for (Iterator JavaDoc cellIter = vrAgg.getIterator();cellIter.hasNext();) {
342             Record valRec = (Record)cellIter.next();
343             clonedRecords.add(valRec);
344           }
345         } else if (rec instanceof FormulaRecordAggregate) {
346           FormulaRecordAggregate fmAgg = (FormulaRecordAggregate)rec;
347           Record fmAggRec = fmAgg.getFormulaRecord();
348           if (fmAggRec != null)
349             clonedRecords.add(fmAggRec);
350           fmAggRec = fmAgg.getStringRecord();
351           if (fmAggRec != null)
352             clonedRecords.add(fmAggRec);
353         } else {
354           clonedRecords.add(rec);
355         }
356       }
357       return createSheet(clonedRecords, 0, 0);
358     }
359
360
361     /**
362      * read support (offset = 0) Same as createSheet(Record[] recs, int, int)
363      * only the record offset is assumed to be 0.
364      *
365      * @param records array containing those records in the sheet in sequence (normally obtained from RecordFactory)
366      * @param sheetnum integer specifying the sheet's number (0,1 or 2 in this release)
367      * @return Sheet object
368      */

369
370     public static Sheet createSheet(List JavaDoc records, int sheetnum)
371     {
372         if (log.check( POILogger.DEBUG ))
373             log.log(POILogger.DEBUG,
374                     "Sheet createSheet (exisiting file) assumed offset 0");
375         return createSheet(records, sheetnum, 0);
376     }
377
378     /**
379      * Creates a sheet with all the usual records minus values and the "index"
380      * record (not required). Sets the location pointer to where the first value
381      * records should go. Use this to create a sheet from "scratch".
382      *
383      * @return Sheet object with all values set to defaults
384      */

385
386     public static Sheet createSheet()
387     {
388         if (log.check( POILogger.DEBUG ))
389             log.log(POILogger.DEBUG, "Sheet createsheet from scratch called");
390         Sheet retval = new Sheet();
391         ArrayList JavaDoc records = new ArrayList JavaDoc(30);
392
393         records.add(retval.createBOF());
394
395         // records.add(retval.createIndex());
396
records.add(retval.createCalcMode());
397         records.add(retval.createCalcCount() );
398         records.add( retval.createRefMode() );
399         records.add( retval.createIteration() );
400         records.add( retval.createDelta() );
401         records.add( retval.createSaveRecalc() );
402         records.add( retval.createPrintHeaders() );
403         retval.printGridlines = (PrintGridlinesRecord) retval.createPrintGridlines();
404         records.add( retval.printGridlines );
405         retval.gridset = (GridsetRecord) retval.createGridset();
406         records.add( retval.gridset );
407         records.add( retval.createGuts() );
408         retval.defaultrowheight =
409                 (DefaultRowHeightRecord) retval.createDefaultRowHeight();
410         records.add( retval.defaultrowheight );
411         records.add( retval.createWSBool() );
412
413         retval.rowBreaks = new PageBreakRecord(PageBreakRecord.HORIZONTAL_SID);
414         records.add(retval.rowBreaks);
415         retval.colBreaks = new PageBreakRecord(PageBreakRecord.VERTICAL_SID);
416         records.add(retval.colBreaks);
417         
418         retval.header = (HeaderRecord) retval.createHeader();
419         records.add( retval.header );
420         retval.footer = (FooterRecord) retval.createFooter();
421         records.add( retval.footer );
422         records.add( retval.createHCenter() );
423         records.add( retval.createVCenter() );
424         retval.printSetup = (PrintSetupRecord) retval.createPrintSetup();
425         records.add( retval.printSetup );
426         retval.defaultcolwidth =
427                 (DefaultColWidthRecord) retval.createDefaultColWidth();
428         records.add( retval.defaultcolwidth);
429         ColumnInfoRecordsAggregate columns = new ColumnInfoRecordsAggregate();
430         records.add( columns );
431         retval.columns = columns;
432         retval.dims = ( DimensionsRecord ) retval.createDimensions();
433         records.add(retval.dims);
434         retval.dimsloc = records.size()-1;
435         records.add(retval.windowTwo = retval.createWindowTwo());
436         retval.setLoc(records.size() - 1);
437         retval.selection =
438                 (SelectionRecord) retval.createSelection();
439         records.add(retval.selection);
440         retval.protect = (ProtectRecord) retval.createProtect();
441         records.add(retval.protect);
442         records.add(retval.createEOF());
443
444
445         retval.records = records;
446         if (log.check( POILogger.DEBUG ))
447             log.log(POILogger.DEBUG, "Sheet createsheet from scratch exit");
448         return retval;
449     }
450
451     private void checkCells()
452     {
453         if (cells == null)
454         {
455             cells = new ValueRecordsAggregate();
456             records.add(getDimsLoc() + 1, cells);
457         }
458     }
459
460     private void checkRows()
461     {
462         if (rows == null)
463         {
464             rows = new RowRecordsAggregate();
465             records.add(getDimsLoc() + 1, rows);
466         }
467     }
468
469     //public int addMergedRegion(short rowFrom, short colFrom, short rowTo,
470
public int addMergedRegion(int rowFrom, short colFrom, int rowTo,
471                                short colTo)
472     {
473         if (merged == null || merged.getNumAreas() == 1027)
474         {
475             merged = ( MergeCellsRecord ) createMergedCells();
476             mergedRecords.add(merged);
477             records.add(records.size() - 1, merged);
478         }
479         merged.addArea(rowFrom, colFrom, rowTo, colTo);
480         return numMergedRegions++;
481     }
482
483     public void removeMergedRegion(int index)
484     {
485         //safety checks
486
if (index >= numMergedRegions || mergedRecords.size() == 0)
487            return;
488             
489         int pos = 0;
490         int startNumRegions = 0;
491         
492         //optimisation for current record
493
if (numMergedRegions - index < merged.getNumAreas())
494         {
495             pos = mergedRecords.size() - 1;
496             startNumRegions = numMergedRegions - merged.getNumAreas();
497         }
498         else
499         {
500             for (int n = 0; n < mergedRecords.size(); n++)
501             {
502                 MergeCellsRecord record = (MergeCellsRecord) mergedRecords.get(n);
503                 if (startNumRegions + record.getNumAreas() > index)
504                 {
505                     pos = n;
506                     break;
507                 }
508                 startNumRegions += record.getNumAreas();
509             }
510         }
511
512         MergeCellsRecord rec = (MergeCellsRecord) mergedRecords.get(pos);
513         rec.removeAreaAt(index - startNumRegions);
514         numMergedRegions--;
515         if (rec.getNumAreas() == 0)
516         {
517             mergedRecords.remove(pos);
518             //get rid of the record from the sheet
519
records.remove(merged);
520             if (merged == rec) {
521                 //pull up the LAST record for operations when we finally
522
//support continue records for mergedRegions
523
if (mergedRecords.size() > 0) {
524                     merged = (MergeCellsRecord) mergedRecords.get(mergedRecords.size() - 1);
525                 } else {
526                     merged = null;
527                 }
528             }
529         }
530     }
531
532     public MergeCellsRecord.MergedRegion getMergedRegionAt(int index)
533     {
534         //safety checks
535
if (index >= numMergedRegions || mergedRecords.size() == 0)
536             return null;
537             
538         int pos = 0;
539         int startNumRegions = 0;
540         
541         //optimisation for current record
542
if (numMergedRegions - index < merged.getNumAreas())
543         {
544             pos = mergedRecords.size() - 1;
545             startNumRegions = numMergedRegions - merged.getNumAreas();
546         }
547         else
548         {
549             for (int n = 0; n < mergedRecords.size(); n++)
550             {
551                 MergeCellsRecord record = (MergeCellsRecord) mergedRecords.get(n);
552                 if (startNumRegions + record.getNumAreas() > index)
553                 {
554                     pos = n;
555                     break;
556                 }
557                 startNumRegions += record.getNumAreas();
558             }
559         }
560         return ((MergeCellsRecord) mergedRecords.get(pos)).getAreaAt(index - startNumRegions);
561     }
562
563     public int getNumMergedRegions()
564     {
565         return numMergedRegions;
566     }
567
568     /**
569      * This is basically a kludge to deal with the now obsolete Label records. If
570      * you have to read in a sheet that contains Label records, be aware that the rest
571      * of the API doesn't deal with them, the low level structure only provides read-only
572      * semi-immutable structures (the sets are there for interface conformance with NO
573      * impelmentation). In short, you need to call this function passing it a reference
574      * to the Workbook object. All labels will be converted to LabelSST records and their
575      * contained strings will be written to the Shared String tabel (SSTRecord) within
576      * the Workbook.
577      *
578      * @param wb sheet's matching low level Workbook structure containing the SSTRecord.
579      * @see org.apache.poi.hssf.record.LabelRecord
580      * @see org.apache.poi.hssf.record.LabelSSTRecord
581      * @see org.apache.poi.hssf.record.SSTRecord
582      */

583
584     public void convertLabelRecords(Workbook wb)
585     {
586         if (log.check( POILogger.DEBUG ))
587             log.log(POILogger.DEBUG, "convertLabelRecords called");
588         if (containsLabels)
589         {
590             for (int k = 0; k < records.size(); k++)
591             {
592                 Record rec = ( Record ) records.get(k);
593
594                 if (rec.getSid() == LabelRecord.sid)
595                 {
596                     LabelRecord oldrec = ( LabelRecord ) rec;
597
598                     records.remove(k);
599                     LabelSSTRecord newrec = new LabelSSTRecord();
600                     int stringid =
601                         wb.addSSTString(oldrec.getValue());
602
603                     newrec.setRow(oldrec.getRow());
604                     newrec.setColumn(oldrec.getColumn());
605                     newrec.setXFIndex(oldrec.getXFIndex());
606                     newrec.setSSTIndex(stringid);
607                           records.add(k, newrec);
608                 }
609             }
610         }
611         if (log.check( POILogger.DEBUG ))
612             log.log(POILogger.DEBUG, "convertLabelRecords exit");
613     }
614
615     /**
616      * Returns the number of low level binary records in this sheet. This adjusts things for the so called
617      * AgregateRecords.
618      *
619      * @see org.apache.poi.hssf.record.Record
620      */

621
622     public int getNumRecords()
623     {
624         checkCells();
625         checkRows();
626         if (log.check( POILogger.DEBUG ))
627         {
628             log.log(POILogger.DEBUG, "Sheet.getNumRecords");
629             log.logFormatted(POILogger.DEBUG, "returning % + % + % - 2 = %", new int[]
630             {
631                 records.size(), cells.getPhysicalNumberOfCells(),
632                 rows.getPhysicalNumberOfRows(),
633                 records.size() + cells.getPhysicalNumberOfCells()
634                 + rows.getPhysicalNumberOfRows() - 2
635             });
636         }
637         return records.size() + cells.getPhysicalNumberOfCells()
638                + rows.getPhysicalNumberOfRows() - 2;
639     }
640
641     /**
642      * Per an earlier reported bug in working with Andy Khan's excel read library. This
643      * sets the values in the sheet's DimensionsRecord object to be correct. Excel doesn't
644      * really care, but we want to play nice with other libraries.
645      *
646      * @see org.apache.poi.hssf.record.DimensionsRecord
647      */

648
649     //public void setDimensions(short firstrow, short firstcol, short lastrow,
650
public void setDimensions(int firstrow, short firstcol, int lastrow,
651                               short lastcol)
652     {
653         if (log.check( POILogger.DEBUG ))
654         {
655             log.log(POILogger.DEBUG, "Sheet.setDimensions");
656             log.log(POILogger.DEBUG,
657                     (new StringBuffer JavaDoc("firstrow")).append(firstrow)
658                         .append("firstcol").append(firstcol).append("lastrow")
659                         .append(lastrow).append("lastcol").append(lastcol)
660                         .toString());
661         }
662         dims.setFirstCol(firstcol);
663         dims.setFirstRow(firstrow);
664         dims.setLastCol(lastcol);
665         dims.setLastRow(lastrow);
666         if (log.check( POILogger.DEBUG ))
667             log.log(POILogger.DEBUG, "Sheet.setDimensions exiting");
668     }
669
670     /**
671      * set the locator for where we should look for the next value record. The
672      * algorythm will actually start here and find the correct location so you
673      * can set this to 0 and watch performance go down the tubes but it will work.
674      * After a value is set this is automatically advanced. Its also set by the
675      * create method. So you probably shouldn't mess with this unless you have
676      * a compelling reason why or the help for the method you're calling says so.
677      * Check the other methods for whether they care about
678      * the loc pointer. Many of the "modify" and "remove" methods re-initialize this
679      * to "dimsloc" which is the location of the Dimensions Record and presumably the
680      * start of the value section (at or around 19 dec).
681      *
682      * @param loc the record number to start at
683      *
684      */

685
686     public void setLoc(int loc)
687     {
688         valueRecIterator = null;
689         if (log.check( POILogger.DEBUG ))
690             log.log(POILogger.DEBUG, "sheet.setLoc(): " + loc);
691         this.loc = loc;
692     }
693
694     /**
695      * Returns the location pointer to the first record to look for when adding rows/values
696      *
697      */

698
699     public int getLoc()
700     {
701         if (log.check( POILogger.DEBUG ))
702             log.log(POILogger.DEBUG, "sheet.getLoc():" + loc);
703         return loc;
704     }
705
706     /**
707      * Set the preoffset when using DBCELL records (currently unused) - this is
708      * the position of this sheet within the whole file.
709      *
710      * @param offset the offset of the sheet's BOF within the file.
711      */

712
713     public void setPreOffset(int offset)
714     {
715         this.preoffset = offset;
716     }
717
718     /**
719      * get the preoffset when using DBCELL records (currently unused) - this is
720      * the position of this sheet within the whole file.
721      *
722      * @return offset the offset of the sheet's BOF within the file.
723      */

724
725     public int getPreOffset()
726     {
727         return preoffset;
728     }
729
730     /**
731      * Serializes all records in the sheet into one big byte array. Use this to write
732      * the sheet out.
733      *
734      * @param offset to begin write at
735      * @param data array containing the binary representation of the records in this sheet
736      *
737      */

738
739     public int serialize(int offset, byte [] data)
740     {
741         if (log.check( POILogger.DEBUG ))
742             log.log(POILogger.DEBUG, "Sheet.serialize using offsets");
743
744         int pos = offset;
745         boolean haveSerializedIndex = false;
746
747         for (int k = 0; k < records.size(); k++)
748         {
749             Record record = (( Record ) records.get(k));
750             
751             int startPos = pos;
752             //Once the rows have been found in the list of records, start
753
//writing out the blocked row information. This includes the DBCell references
754
if (record instanceof RowRecordsAggregate) {
755               pos += ((RowRecordsAggregate)record).serialize(pos, data, cells); // rec.length;
756
} else if (record instanceof ValueRecordsAggregate) {
757               //Do nothing here. The records were serialized during the RowRecordAggregate block serialization
758
} else {
759               pos += record.serialize(pos, data ); // rec.length;
760
}
761             //If the BOF record was just serialized then add the IndexRecord
762
if (record.getSid() == BOFRecord.sid) {
763               //Can there be more than one BOF for a sheet? If not then we can
764
//remove this guard. So be safe it is left here.
765
if ((rows != null) && (!haveSerializedIndex)) {
766                 haveSerializedIndex = true;
767                 pos += serializeIndexRecord(k, pos, data);
768               }
769             }
770
771
772         }
773         if (log.check( POILogger.DEBUG ))
774             log.log(POILogger.DEBUG, "Sheet.serialize returning ");
775         return pos-offset;
776     }
777     
778     private int serializeIndexRecord(final int BOFRecordIndex, final int offset, byte[] data) {
779       IndexRecord index = new IndexRecord();
780       index.setFirstRow(rows.getFirstRowNum());
781       index.setLastRowAdd1(rows.getLastRowNum()+1);
782       //Calculate the size of the records from the end of the BOF
783
//and up to the RowRecordsAggregate...
784
int sheetRecSize = 0;
785       for (int j = BOFRecordIndex+1; j < records.size(); j++)
786       {
787         Record tmpRec = (( Record ) records.get(j));
788         if (tmpRec instanceof RowRecordsAggregate)
789           break;
790         sheetRecSize+= tmpRec.getRecordSize();
791       }
792       //Add the references to the DBCells in the IndexRecord (one for each block)
793
int blockCount = rows.getRowBlockCount();
794       //Calculate the size of this IndexRecord
795
int indexRecSize = index.getRecordSizeForBlockCount(blockCount);
796
797       int rowBlockOffset = 0;
798       int cellBlockOffset = 0;
799       int dbCellOffset = 0;
800       for (int block=0;block<blockCount;block++) {
801         rowBlockOffset += rows.getRowBlockSize(block);
802         cellBlockOffset += cells.getRowCellBlockSize(rows.getStartRowNumberForBlock(block),
803                                                      rows.getEndRowNumberForBlock(block));
804         //Note: The offsets are relative to the Workbook BOF. Assume that this is
805
//0 for now.....
806
index.addDbcell(offset + indexRecSize + sheetRecSize + dbCellOffset + rowBlockOffset + cellBlockOffset);
807         //Add space required to write the dbcell record(s) (whose references were just added).
808
dbCellOffset += (8 + (rows.getRowCountForBlock(block) * 2));
809       }
810       return index.serialize(offset, data);
811     }
812     
813
814     /**
815      * Create a row record. (does not add it to the records contained in this sheet)
816      *
817      * @param row number
818      * @return RowRecord created for the passed in row number
819      * @see org.apache.poi.hssf.record.RowRecord
820      */

821
822     public RowRecord createRow(int row)
823     {
824         return RowRecordsAggregate.createRow( row );
825     }
826
827     /**
828      * Create a LABELSST Record (does not add it to the records contained in this sheet)
829      *
830      * @param row the row the LabelSST is a member of
831      * @param col the column the LabelSST defines
832      * @param index the index of the string within the SST (use workbook addSSTString method)
833      * @return LabelSSTRecord newly created containing your SST Index, row,col.
834      * @see org.apache.poi.hssf.record.SSTRecord
835      */

836
837     //public LabelSSTRecord createLabelSST(short row, short col, int index)
838
public LabelSSTRecord createLabelSST(int row, short col, int index)
839     {
840         log.logFormatted(POILogger.DEBUG, "create labelsst row,col,index %,%,%",
841                          new int[]
842         {
843             row, col, index
844         });
845         LabelSSTRecord rec = new LabelSSTRecord();
846
847         rec.setRow(row);
848         rec.setColumn(col);
849         rec.setSSTIndex(index);
850         rec.setXFIndex(( short ) 0x0f);
851         return rec;
852     }
853
854     /**
855      * Create a NUMBER Record (does not add it to the records contained in this sheet)
856      *
857      * @param row the row the NumberRecord is a member of
858      * @param col the column the NumberRecord defines
859      * @param value for the number record
860      *
861      * @return NumberRecord for that row, col containing that value as added to the sheet
862      */

863
864     //public NumberRecord createNumber(short row, short col, double value)
865
public NumberRecord createNumber(int row, short col, double value)
866     {
867         log.logFormatted(POILogger.DEBUG, "create number row,col,value %,%,%",
868                          new double[]
869         {
870             row, col, value
871         });
872         NumberRecord rec = new NumberRecord();
873
874         //rec.setRow(( short ) row);
875
rec.setRow(row);
876         rec.setColumn(col);
877         rec.setValue(value);
878         rec.setXFIndex(( short ) 0x0f);
879         return rec;
880     }
881
882     /**
883      * create a BLANK record (does not add it to the records contained in this sheet)
884      *
885      * @param row - the row the BlankRecord is a member of
886      * @param col - the column the BlankRecord is a member of
887      */

888
889     //public BlankRecord createBlank(short row, short col)
890
public BlankRecord createBlank(int row, short col)
891     {
892         //log.logFormatted(POILogger.DEBUG, "create blank row,col %,%", new short[]
893
log.logFormatted(POILogger.DEBUG, "create blank row,col %,%", new int[]
894         {
895             row, col
896         });
897         BlankRecord rec = new BlankRecord();
898
899         //rec.setRow(( short ) row);
900
rec.setRow(row);
901         rec.setColumn(col);
902         rec.setXFIndex(( short ) 0x0f);
903         return rec;
904     }
905
906     /**
907      * Attempts to parse the formula into PTGs and create a formula record
908      * DOES NOT WORK YET
909      *
910      * @param row - the row for the formula record
911      * @param col - the column of the formula record
912      * @param formula - a String representing the formula. To be parsed to PTGs
913      * @return bogus/useless formula record
914      */

915
916     //public FormulaRecord createFormula(short row, short col, String formula)
917
public FormulaRecord createFormula(int row, short col, String JavaDoc formula)
918     {
919         log.logFormatted(POILogger.DEBUG, "create formula row,col,formula %,%,%",
920                          //new short[]
921
new int[]
922         {
923             row, col
924         }, formula);
925         FormulaRecord rec = new FormulaRecord();
926
927         rec.setRow(row);
928         rec.setColumn(col);
929         rec.setOptions(( short ) 2);
930         rec.setValue(0);
931         rec.setXFIndex(( short ) 0x0f);
932         FormulaParser fp = new FormulaParser(formula,null); //fix - do we need this method?
933
fp.parse();
934         Ptg[] ptg = fp.getRPNPtg();
935         int size = 0;
936
937         for (int k = 0; k < ptg.length; k++)
938         {
939             size += ptg[ k ].getSize();
940             rec.pushExpressionToken(ptg[ k ]);
941         }
942         rec.setExpressionLength(( short ) size);
943         return rec;
944     }
945
946     /**
947      * Adds a value record to the sheet's contained binary records
948      * (i.e. LabelSSTRecord or NumberRecord).
949      * <P>
950      * This method is "loc" sensitive. Meaning you need to set LOC to where you
951      * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
952      * When adding several rows you can just start at the last one by leaving loc
953      * at what this sets it to.
954      *
955      * @param row the row to add the cell value to
956      * @param col the cell value record itself.
957      */

958
959     //public void addValueRecord(short row, CellValueRecordInterface col)
960
public void addValueRecord(int row, CellValueRecordInterface col)
961     {
962         checkCells();
963         log.logFormatted(POILogger.DEBUG, "add value record row,loc %,%", new int[]
964         {
965             row, loc
966         });
967         DimensionsRecord d = ( DimensionsRecord ) records.get(getDimsLoc());
968
969         if (col.getColumn() > d.getLastCol())
970         {
971             d.setLastCol(( short ) (col.getColumn() + 1));
972         }
973         if (col.getColumn() < d.getFirstCol())
974         {
975             d.setFirstCol(col.getColumn());
976         }
977         cells.insertCell(col);
978
979         /*
980          * for (int k = loc; k < records.size(); k++)
981          * {
982          * Record rec = ( Record ) records.get(k);
983          *
984          * if (rec.getSid() == RowRecord.sid)
985          * {
986          * RowRecord rowrec = ( RowRecord ) rec;
987          *
988          * if (rowrec.getRowNumber() == col.getRow())
989          * {
990          * records.add(k + 1, col);
991          * loc = k;
992          * if (rowrec.getLastCol() <= col.getColumn())
993          * {
994          * rowrec.setLastCol((( short ) (col.getColumn() + 1)));
995          * }
996          * break;
997          * }
998          * }
999          * }
1000         */

1001    }
1002
1003    /**
1004     * remove a value record from the records array.
1005     *
1006     * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
1007     *
1008     * @param row - the row of the value record you wish to remove
1009     * @param col - a record supporting the CellValueRecordInterface.
1010     * @see org.apache.poi.hssf.record.CellValueRecordInterface
1011     */

1012
1013    //public void removeValueRecord(short row, CellValueRecordInterface col)
1014
public void removeValueRecord(int row, CellValueRecordInterface col)
1015    {
1016        checkCells();
1017        log.logFormatted(POILogger.DEBUG, "remove value record row,dimsloc %,%",
1018                         new int[]{row, dimsloc} );
1019        loc = dimsloc;
1020        cells.removeCell(col);
1021
1022        /*
1023         * for (int k = loc; k < records.size(); k++)
1024         * {
1025         * Record rec = ( Record ) records.get(k);
1026         *
1027         * // checkDimsLoc(rec,k);
1028         * if (rec.isValue())
1029         * {
1030         * CellValueRecordInterface cell =
1031         * ( CellValueRecordInterface ) rec;
1032         *
1033         * if ((cell.getRow() == col.getRow())
1034         * && (cell.getColumn() == col.getColumn()))
1035         * {
1036         * records.remove(k);
1037         * break;
1038         * }
1039         * }
1040         * }
1041         */

1042    }
1043
1044    /**
1045     * replace a value record from the records array.
1046     *
1047     * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
1048     *
1049     * @param newval - a record supporting the CellValueRecordInterface. this will replace
1050     * the cell value with the same row and column. If there isn't one, one will
1051     * be added.
1052     */

1053
1054    public void replaceValueRecord(CellValueRecordInterface newval)
1055    {
1056        checkCells();
1057        setLoc(dimsloc);
1058        if (log.check( POILogger.DEBUG ))
1059            log.log(POILogger.DEBUG, "replaceValueRecord ");
1060        cells.insertCell(newval);
1061
1062        /*
1063         * CellValueRecordInterface oldval = getNextValueRecord();
1064         *
1065         * while (oldval != null)
1066         * {
1067         * if (oldval.isEqual(newval))
1068         * {
1069         * records.set(( short ) (getLoc() - 1), newval);
1070         * return;
1071         * }
1072         * oldval = getNextValueRecord();
1073         * }
1074         * addValueRecord(newval.getRow(), newval);
1075         * setLoc(dimsloc);
1076         */

1077    }
1078
1079    /**
1080     * Adds a row record to the sheet
1081     *
1082     * <P>
1083     * This method is "loc" sensitive. Meaning you need to set LOC to where you
1084     * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
1085     * When adding several rows you can just start at the last one by leaving loc
1086     * at what this sets it to.
1087     *
1088     * @param row the row record to be added
1089     * @see #setLoc(int)
1090     */

1091
1092    public void addRow(RowRecord row)
1093    {
1094        checkRows();
1095        if (log.check( POILogger.DEBUG ))
1096            log.log(POILogger.DEBUG, "addRow ");
1097        DimensionsRecord d = ( DimensionsRecord ) records.get(getDimsLoc());
1098
1099        if (row.getRowNumber() >= d.getLastRow())
1100        {
1101            d.setLastRow(row.getRowNumber() + 1);
1102        }
1103        if (row.getRowNumber() < d.getFirstRow())
1104        {
1105            d.setFirstRow(row.getRowNumber());
1106        }
1107        //IndexRecord index = null;
1108
//If the row exists remove it, so that any cells attached to the row are removed
1109
RowRecord existingRow = rows.getRow(row.getRowNumber());
1110         if (existingRow != null)
1111           rows.removeRow(existingRow);
1112
1113        rows.insertRow(row);
1114
1115        /*
1116         * for (int k = loc; k < records.size(); k++)
1117         * {
1118         * Record rec = ( Record ) records.get(k);
1119         *
1120         * if (rec.getSid() == IndexRecord.sid)
1121         * {
1122         * index = ( IndexRecord ) rec;
1123         * }
1124         * if (rec.getSid() == RowRecord.sid)
1125         * {
1126         * RowRecord rowrec = ( RowRecord ) rec;
1127         *
1128         * if (rowrec.getRowNumber() > row.getRowNumber())
1129         * {
1130         * records.add(k, row);
1131         * loc = k;
1132         * break;
1133         * }
1134         * }
1135         * if (rec.getSid() == WindowTwoRecord.sid)
1136         * {
1137         * records.add(k, row);
1138         * loc = k;
1139         * break;
1140         * }
1141         * }
1142         * if (index != null)
1143         * {
1144         * if (index.getLastRowAdd1() <= row.getRowNumber())
1145         * {
1146         * index.setLastRowAdd1(row.getRowNumber() + 1);
1147         * }
1148         * }
1149         */

1150        if (log.check( POILogger.DEBUG ))
1151            log.log(POILogger.DEBUG, "exit addRow");
1152    }
1153
1154    /**
1155     * Removes a row record
1156     *
1157     * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
1158     *
1159     * @param row the row record to remove
1160     */

1161
1162    public void removeRow(RowRecord row)
1163    {
1164        checkRows();
1165        // IndexRecord index = null;
1166

1167        setLoc(getDimsLoc());
1168        rows.removeRow(row);
1169
1170        /*
1171         * for (int k = loc; k < records.size(); k++)
1172         * {
1173         * Record rec = ( Record ) records.get(k);
1174         *
1175         * // checkDimsLoc(rec,k);
1176         * if (rec.getSid() == RowRecord.sid)
1177         * {
1178         * RowRecord rowrec = ( RowRecord ) rec;
1179         *
1180         * if (rowrec.getRowNumber() == row.getRowNumber())
1181         * {
1182         * records.remove(k);
1183         * break;
1184         * }
1185         * }
1186         * if (rec.getSid() == WindowTwoRecord.sid)
1187         * {
1188         * break;
1189         * }
1190         * }
1191         */

1192    }
1193
1194    /**
1195     * get the NEXT value record (from LOC). The first record that is a value record
1196     * (starting at LOC) will be returned.
1197     *
1198     * <P>
1199     * This method is "loc" sensitive. Meaning you need to set LOC to where you
1200     * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
1201     * When adding several rows you can just start at the last one by leaving loc
1202     * at what this sets it to. For this method, set loc to dimsloc to start with,
1203     * subsequent calls will return values in (physical) sequence or NULL when you get to the end.
1204     *
1205     * @return CellValueRecordInterface representing the next value record or NULL if there are no more
1206     * @see #setLoc(int)
1207     */

1208
1209    public CellValueRecordInterface getNextValueRecord()
1210    {
1211        if (log.check( POILogger.DEBUG ))
1212            log.log(POILogger.DEBUG, "getNextValue loc= " + loc);
1213        if (valueRecIterator == null)
1214        {
1215            valueRecIterator = cells.getIterator();
1216        }
1217        if (!valueRecIterator.hasNext())
1218        {
1219            return null;
1220        }
1221        return ( CellValueRecordInterface ) valueRecIterator.next();
1222
1223        /*
1224         * if (this.getLoc() < records.size())
1225         * {
1226         * for (int k = getLoc(); k < records.size(); k++)
1227         * {
1228         * Record rec = ( Record ) records.get(k);
1229         *
1230         * this.setLoc(k + 1);
1231         * if (rec instanceof CellValueRecordInterface)
1232         * {
1233         * return ( CellValueRecordInterface ) rec;
1234         * }
1235         * }
1236         * }
1237         * return null;
1238         */

1239    }
1240
1241    /**
1242     * get the NEXT RowRecord or CellValueRecord(from LOC). The first record that
1243     * is a Row record or CellValueRecord(starting at LOC) will be returned.
1244     * <P>
1245     * This method is "loc" sensitive. Meaning you need to set LOC to where you
1246     * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
1247     * When adding several rows you can just start at the last one by leaving loc
1248     * at what this sets it to. For this method, set loc to dimsloc to start with.
1249     * subsequent calls will return rows in (physical) sequence or NULL when you get to the end.
1250     *
1251     * @return RowRecord representing the next row record or CellValueRecordInterface
1252     * representing the next cellvalue or NULL if there are no more
1253     * @see #setLoc(int)
1254     *
1255     */

1256
1257/* public Record getNextRowOrValue()
1258    {
1259        POILogger.DEBUG((new StringBuffer("getNextRow loc= ")).append(loc)
1260            .toString());
1261        if (this.getLoc() < records.size())
1262        {
1263            for (int k = this.getLoc(); k < records.size(); k++)
1264            {
1265                Record rec = ( Record ) records.get(k);
1266
1267                this.setLoc(k + 1);
1268                if (rec.getSid() == RowRecord.sid)
1269                {
1270                    return rec;
1271                }
1272                else if (rec.isValue())
1273                {
1274                    return rec;
1275                }
1276            }
1277        }
1278        return null;
1279    }
1280 */

1281
1282    /**
1283     * get the NEXT RowRecord (from LOC). The first record that is a Row record
1284     * (starting at LOC) will be returned.
1285     * <P>
1286     * This method is "loc" sensitive. Meaning you need to set LOC to where you
1287     * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
1288     * When adding several rows you can just start at the last one by leaving loc
1289     * at what this sets it to. For this method, set loc to dimsloc to start with.
1290     * subsequent calls will return rows in (physical) sequence or NULL when you get to the end.
1291     *
1292     * @return RowRecord representing the next row record or NULL if there are no more
1293     * @see #setLoc(int)
1294     *
1295     */

1296
1297    public RowRecord getNextRow()
1298    {
1299        if (log.check( POILogger.DEBUG ))
1300            log.log(POILogger.DEBUG, "getNextRow loc= " + loc);
1301        if (rowRecIterator == null)
1302        {
1303            rowRecIterator = rows.getIterator();
1304        }
1305        if (!rowRecIterator.hasNext())
1306        {
1307            return null;
1308        }
1309        return ( RowRecord ) rowRecIterator.next();
1310
1311/* if (this.getLoc() < records.size())
1312        {
1313            for (int k = this.getLoc(); k < records.size(); k++)
1314            {
1315                Record rec = ( Record ) records.get(k);
1316
1317                this.setLoc(k + 1);
1318                if (rec.getSid() == RowRecord.sid)
1319                {
1320                    return ( RowRecord ) rec;
1321                }
1322            }
1323        }*/

1324    }
1325
1326    /**
1327     * get the NEXT (from LOC) RowRecord where rownumber matches the given rownum.
1328     * The first record that is a Row record (starting at LOC) that has the
1329     * same rownum as the given rownum will be returned.
1330     * <P>
1331     * This method is "loc" sensitive. Meaning you need to set LOC to where you
1332     * want it to start searching. If you don't know do this: setLoc(getDimsLoc).
1333     * When adding several rows you can just start at the last one by leaving loc
1334     * at what this sets it to. For this method, set loc to dimsloc to start with.
1335     * subsequent calls will return rows in (physical) sequence or NULL when you get to the end.
1336     *
1337     * @param rownum which row to return (careful with LOC)
1338     * @return RowRecord representing the next row record or NULL if there are no more
1339     * @see #setLoc(int)
1340     *
1341     */

1342
1343    //public RowRecord getRow(short rownum)
1344
public RowRecord getRow(int rownum)
1345    {
1346        if (log.check( POILogger.DEBUG ))
1347            log.log(POILogger.DEBUG, "getNextRow loc= " + loc);
1348        return rows.getRow(rownum);
1349
1350        /*
1351         * if (this.getLoc() < records.size())
1352         * {
1353         * for (int k = this.getLoc(); k < records.size(); k++)
1354         * {
1355         * Record rec = ( Record ) records.get(k);
1356         *
1357         * this.setLoc(k + 1);
1358         * if (rec.getSid() == RowRecord.sid)
1359         * {
1360         * if ((( RowRecord ) rec).getRowNumber() == rownum)
1361         * {
1362         * return ( RowRecord ) rec;
1363         * }
1364         * }
1365         * }
1366         * }
1367         */

1368
1369        // return null;
1370
}
1371
1372    /**
1373     * creates the BOF record
1374     * @see org.apache.poi.hssf.record.BOFRecord
1375     * @see org.apache.poi.hssf.record.Record
1376     * @return record containing a BOFRecord
1377     */

1378
1379    protected Record createBOF()
1380    {
1381        BOFRecord retval = new BOFRecord();
1382
1383        retval.setVersion(( short ) 0x600);
1384        retval.setType(( short ) 0x010);
1385
1386        // retval.setBuild((short)0x10d3);
1387
retval.setBuild(( short ) 0x0dbb);
1388        retval.setBuildYear(( short ) 1996);
1389        retval.setHistoryBitMask(0xc1);
1390        retval.setRequiredVersion(0x6);
1391        return retval;
1392    }
1393
1394    /**
1395     * creates the Index record - not currently used
1396     * @see org.apache.poi.hssf.record.IndexRecord
1397     * @see org.apache.poi.hssf.record.Record
1398     * @return record containing a IndexRecord
1399     */

1400
1401    protected Record createIndex()
1402    {
1403        IndexRecord retval = new IndexRecord();
1404
1405        retval.setFirstRow(0); // must be set explicitly
1406
retval.setLastRowAdd1(0);
1407        return retval;
1408    }
1409
1410    /**
1411     * creates the CalcMode record and sets it to 1 (automatic formula caculation)
1412     * @see org.apache.poi.hssf.record.CalcModeRecord
1413     * @see org.apache.poi.hssf.record.Record
1414     * @return record containing a CalcModeRecord
1415     */

1416
1417    protected Record createCalcMode()
1418    {
1419        CalcModeRecord retval = new CalcModeRecord();
1420
1421        retval.setCalcMode(( short ) 1);
1422        return retval;
1423    }
1424
1425    /**
1426     * creates the CalcCount record and sets it to 0x64 (default number of iterations)
1427     * @see org.apache.poi.hssf.record.CalcCountRecord
1428     * @see org.apache.poi.hssf.record.Record
1429     * @return record containing a CalcCountRecord
1430     */

1431
1432    protected Record createCalcCount()
1433    {
1434        CalcCountRecord retval = new CalcCountRecord();
1435
1436        retval.setIterations(( short ) 0x64); // default 64 iterations
1437
return retval;
1438    }
1439
1440    /**
1441     * creates the RefMode record and sets it to A1 Mode (default reference mode)
1442     * @see org.apache.poi.hssf.record.RefModeRecord
1443     * @see org.apache.poi.hssf.record.Record
1444     * @return record containing a RefModeRecord
1445     */

1446
1447    protected Record createRefMode()
1448    {
1449        RefModeRecord retval = new RefModeRecord();
1450
1451        retval.setMode(RefModeRecord.USE_A1_MODE);
1452        return retval;
1453    }
1454
1455    /**
1456     * creates the Iteration record and sets it to false (don't iteratively calculate formulas)
1457     * @see org.apache.poi.hssf.record.IterationRecord
1458     * @see org.apache.poi.hssf.record.Record
1459     * @return record containing a IterationRecord
1460     */

1461
1462    protected Record createIteration()
1463    {
1464        IterationRecord retval = new IterationRecord();
1465
1466        retval.setIteration(false);
1467        return retval;
1468    }
1469
1470    /**
1471     * creates the Delta record and sets it to 0.0010 (default accuracy)
1472     * @see org.apache.poi.hssf.record.DeltaRecord
1473     * @see org.apache.poi.hssf.record.Record
1474     * @return record containing a DeltaRecord
1475     */

1476
1477    protected Record createDelta()
1478    {
1479        DeltaRecord retval = new DeltaRecord();
1480
1481        retval.setMaxChange(0.0010);
1482        return retval;
1483    }
1484
1485    /**
1486     * creates the SaveRecalc record and sets it to true (recalculate before saving)
1487     * @see org.apache.poi.hssf.record.SaveRecalcRecord
1488     * @see org.apache.poi.hssf.record.Record
1489     * @return record containing a SaveRecalcRecord
1490     */

1491
1492    protected Record createSaveRecalc()
1493    {
1494        SaveRecalcRecord retval = new SaveRecalcRecord();
1495
1496        retval.setRecalc(true);
1497        return retval;
1498    }
1499
1500    /**
1501     * creates the PrintHeaders record and sets it to false (we don't create headers yet so why print them)
1502     * @see org.apache.poi.hssf.record.PrintHeadersRecord
1503     * @see org.apache.poi.hssf.record.Record
1504     * @return record containing a PrintHeadersRecord
1505     */

1506
1507    protected Record createPrintHeaders()
1508    {
1509        PrintHeadersRecord retval = new PrintHeadersRecord();
1510
1511        retval.setPrintHeaders(false);
1512        return retval;
1513    }
1514
1515    /**
1516     * creates the PrintGridlines record and sets it to false (that makes for ugly sheets). As far as I can
1517     * tell this does the same thing as the GridsetRecord
1518     *
1519     * @see org.apache.poi.hssf.record.PrintGridlinesRecord
1520     * @see org.apache.poi.hssf.record.Record
1521     * @return record containing a PrintGridlinesRecord
1522     */

1523
1524    protected Record createPrintGridlines()
1525    {
1526        PrintGridlinesRecord retval = new PrintGridlinesRecord();
1527
1528        retval.setPrintGridlines(false);
1529        return retval;
1530    }
1531
1532    /**
1533     * creates the Gridset record and sets it to true (user has mucked with the gridlines)
1534     * @see org.apache.poi.hssf.record.GridsetRecord
1535     * @see org.apache.poi.hssf.record.Record
1536     * @return record containing a GridsetRecord
1537     */

1538
1539    protected Record createGridset()
1540    {
1541        GridsetRecord retval = new GridsetRecord();
1542
1543        retval.setGridset(true);
1544        return retval;
1545    }
1546
1547    /**
1548     * creates the Guts record and sets leftrow/topcol guttter and rowlevelmax/collevelmax to 0
1549     * @see org.apache.poi.hssf.record.GutsRecord
1550     * @see org.apache.poi.hssf.record.Record
1551     * @return record containing a GutsRecordRecord
1552     */

1553
1554    protected Record createGuts()
1555    {
1556        GutsRecord retval = new GutsRecord();
1557
1558        retval.setLeftRowGutter(( short ) 0);
1559        retval.setTopColGutter(( short ) 0);
1560        retval.setRowLevelMax(( short ) 0);
1561        retval.setColLevelMax(( short ) 0);
1562        return retval;
1563    }
1564
1565    /**
1566     * creates the DefaultRowHeight Record and sets its options to 0 and rowheight to 0xff
1567     * @see org.apache.poi.hssf.record.DefaultRowHeightRecord
1568     * @see org.apache.poi.hssf.record.Record
1569     * @return record containing a DefaultRowHeightRecord
1570     */

1571
1572    protected Record createDefaultRowHeight()
1573    {
1574        DefaultRowHeightRecord retval = new DefaultRowHeightRecord();
1575
1576        retval.setOptionFlags(( short ) 0);
1577        retval.setRowHeight(( short ) 0xff);
1578        return retval;
1579    }
1580
1581    /**
1582     * creates the WSBoolRecord and sets its values to defaults
1583     * @see org.apache.poi.hssf.record.WSBoolRecord
1584     * @see org.apache.poi.hssf.record.Record
1585     * @return record containing a WSBoolRecord
1586     */

1587
1588    protected Record createWSBool()
1589    {
1590        WSBoolRecord retval = new WSBoolRecord();
1591
1592        retval.setWSBool1(( byte ) 0x4);
1593        retval.setWSBool2(( byte ) 0xffffffc1);
1594        return retval;
1595    }
1596
1597    /**
1598     * creates the Header Record and sets it to nothing/0 length
1599     * @see org.apache.poi.hssf.record.HeaderRecord
1600     * @see org.apache.poi.hssf.record.Record
1601     * @return record containing a HeaderRecord
1602     */

1603
1604    protected Record createHeader()
1605    {
1606        HeaderRecord retval = new HeaderRecord();
1607
1608        retval.setHeaderLength(( byte ) 0);
1609        retval.setHeader(null);
1610        return retval;
1611    }
1612
1613    /**
1614     * creates the Footer Record and sets it to nothing/0 length
1615     * @see org.apache.poi.hssf.record.FooterRecord
1616     * @see org.apache.poi.hssf.record.Record
1617     * @return record containing a FooterRecord
1618     */

1619
1620    protected Record createFooter()
1621    {
1622        FooterRecord retval = new FooterRecord();
1623
1624        retval.setFooterLength(( byte ) 0);
1625        retval.setFooter(null);
1626        return retval;
1627    }
1628
1629    /**
1630     * creates the HCenter Record and sets it to false (don't horizontally center)
1631     * @see org.apache.poi.hssf.record.HCenterRecord
1632     * @see org.apache.poi.hssf.record.Record
1633     * @return record containing a HCenterRecord
1634     */

1635
1636    protected Record createHCenter()
1637    {
1638        HCenterRecord retval = new HCenterRecord();
1639
1640        retval.setHCenter(false);
1641        return retval;
1642    }
1643
1644    /**
1645     * creates the VCenter Record and sets it to false (don't horizontally center)
1646     * @see org.apache.poi.hssf.record.VCenterRecord
1647     * @see org.apache.poi.hssf.record.Record
1648     * @return record containing a VCenterRecord
1649     */

1650
1651    protected Record createVCenter()
1652    {
1653        VCenterRecord retval = new VCenterRecord();
1654
1655        retval.setVCenter(false);
1656        return retval;
1657    }
1658
1659    /**
1660     * creates the PrintSetup Record and sets it to defaults and marks it invalid
1661     * @see org.apache.poi.hssf.record.PrintSetupRecord
1662     * @see org.apache.poi.hssf.record.Record
1663     * @return record containing a PrintSetupRecord
1664     */

1665
1666    protected Record createPrintSetup()
1667    {
1668        PrintSetupRecord retval = new PrintSetupRecord();
1669
1670        retval.setPaperSize(( short ) 1);
1671        retval.setScale(( short ) 100);
1672        retval.setPageStart(( short ) 1);
1673        retval.setFitWidth(( short ) 1);
1674        retval.setFitHeight(( short ) 1);
1675        retval.setOptions(( short ) 2);
1676        retval.setHResolution(( short ) 300);
1677        retval.setVResolution(( short ) 300);
1678        retval.setHeaderMargin( 0.5);
1679        retval.setFooterMargin( 0.5);
1680        retval.setCopies(( short ) 0);
1681        return retval;
1682    }
1683
1684    /**
1685     * creates the DefaultColWidth Record and sets it to 8
1686     * @see org.apache.poi.hssf.record.DefaultColWidthRecord
1687     * @see org.apache.poi.hssf.record.Record
1688     * @return record containing a DefaultColWidthRecord
1689     */

1690
1691    protected Record createDefaultColWidth()
1692    {
1693        DefaultColWidthRecord retval = new DefaultColWidthRecord();
1694
1695        retval.setColWidth(( short ) 8);
1696        return retval;
1697    }
1698
1699    /**
1700     * creates the ColumnInfo Record and sets it to a default column/width
1701     * @see org.apache.poi.hssf.record.ColumnInfoRecord
1702     * @return record containing a ColumnInfoRecord
1703     */

1704
1705    protected Record createColInfo()
1706    {
1707        return ColumnInfoRecordsAggregate.createColInfo();
1708    }
1709
1710    /**
1711     * get the default column width for the sheet (if the columns do not define their own width)
1712     * @return default column width
1713     */

1714
1715    public short getDefaultColumnWidth()
1716    {
1717        return defaultcolwidth.getColWidth();
1718    }
1719
1720    /**
1721     * get whether gridlines are printed.
1722     * @return true if printed
1723     */

1724
1725    public boolean isGridsPrinted()
1726    {
1727        return !gridset.getGridset();
1728    }
1729
1730    /**
1731     * set whether gridlines printed or not.
1732     * @param value True if gridlines printed.
1733     */

1734
1735    public void setGridsPrinted(boolean value)
1736    {
1737        gridset.setGridset(!value);
1738    }
1739
1740    /**
1741     * set the default column width for the sheet (if the columns do not define their own width)
1742     * @param dcw default column width
1743     */

1744
1745    public void setDefaultColumnWidth(short dcw)
1746    {
1747        defaultcolwidth.setColWidth(dcw);
1748    }
1749
1750    /**
1751     * set the default row height for the sheet (if the rows do not define their own height)
1752     */

1753
1754    public void setDefaultRowHeight(short dch)
1755    {
1756        defaultrowheight.setRowHeight(dch);
1757    }
1758
1759    /**
1760     * get the default row height for the sheet (if the rows do not define their own height)
1761     * @return default row height
1762     */

1763
1764    public short getDefaultRowHeight()
1765    {
1766        return defaultrowheight.getRowHeight();
1767    }
1768
1769    /**
1770     * get the width of a given column in units of 1/20th of a point width (twips?)
1771     * @param column index
1772     * @see org.apache.poi.hssf.record.DefaultColWidthRecord
1773     * @see org.apache.poi.hssf.record.ColumnInfoRecord
1774     * @see #setColumnWidth(short,short)
1775     * @return column width in units of 1/20th of a point (twips?)
1776     */

1777
1778    public short getColumnWidth(short column)
1779    {
1780        short retval = 0;
1781        ColumnInfoRecord ci = null;
1782
1783        if (columns != null)
1784        {
1785            for ( Iterator JavaDoc iterator = columns.getIterator(); iterator.hasNext(); )
1786            {
1787                ci = ( ColumnInfoRecord ) iterator.next();
1788                if ((ci.getFirstColumn() <= column)
1789                        && (column <= ci.getLastColumn()))
1790                {
1791                    break;
1792                }
1793                ci = null;
1794            }
1795        }
1796        if (ci != null)
1797        {
1798            retval = ci.getColumnWidth();
1799        }
1800        else
1801        {
1802            retval = defaultcolwidth.getColWidth();
1803        }
1804        return retval;
1805    }
1806
1807    /**
1808     * set the width for a given column in 1/20th of a character width units
1809     * @param column - the column number
1810     * @param width (in units of 1/20th of a character width)
1811     */

1812    public void setColumnWidth(short column, short width)
1813    {
1814        setColumn( column, new Short JavaDoc(width), null, null, null);
1815    }
1816
1817    public void setColumn(short column, Short JavaDoc width, Integer JavaDoc level, Boolean JavaDoc hidden, Boolean JavaDoc collapsed)
1818    {
1819        if (columns == null)
1820            columns = new ColumnInfoRecordsAggregate();
1821
1822        columns.setColumn( column, width, level, hidden, collapsed );
1823    }
1824
1825    /**
1826     * Creates an outline group for the specified columns.
1827     * @param fromColumn group from this column (inclusive)
1828     * @param toColumn group to this column (inclusive)
1829     * @param indent if true the group will be indented by one level,
1830     * if false indenting will be removed by one level.
1831     */

1832    public void groupColumnRange(short fromColumn, short toColumn, boolean indent)
1833    {
1834
1835        // Set the level for each column
1836
columns.groupColumnRange( fromColumn, toColumn, indent);
1837
1838        // Determine the maximum overall level
1839
int maxLevel = 0;
1840        for ( Iterator JavaDoc iterator = columns.getIterator(); iterator.hasNext(); )
1841        {
1842            ColumnInfoRecord columnInfoRecord = (ColumnInfoRecord) iterator.next();
1843            maxLevel = Math.max(columnInfoRecord.getOutlineLevel(), maxLevel);
1844        }
1845
1846        GutsRecord guts = (GutsRecord) findFirstRecordBySid( GutsRecord.sid );
1847        guts.setColLevelMax( (short) ( maxLevel+1 ) );
1848        if (maxLevel == 0)
1849            guts.setTopColGutter( (short)0 );
1850        else
1851            guts.setTopColGutter( (short) ( 29 + (12 * (maxLevel-1)) ) );
1852    }
1853
1854    /**
1855     * creates the Dimensions Record and sets it to bogus values (you should set this yourself
1856     * or let the high level API do it for you)
1857     * @see org.apache.poi.hssf.record.DimensionsRecord
1858     * @see org.apache.poi.hssf.record.Record
1859     * @return record containing a DimensionsRecord
1860     */

1861
1862    protected Record createDimensions()
1863    {
1864        DimensionsRecord retval = new DimensionsRecord();
1865
1866        retval.setFirstCol(( short ) 0);
1867        retval.setLastRow(1); // one more than it is
1868
retval.setFirstRow(0);
1869        retval.setLastCol(( short ) 1); // one more than it is
1870
return retval;
1871    }
1872
1873    /**
1874     * creates the WindowTwo Record and sets it to: <P>
1875     * options = 0x6b6 <P>
1876     * toprow = 0 <P>
1877     * leftcol = 0 <P>
1878     * headercolor = 0x40 <P>
1879     * pagebreakzoom = 0x0 <P>
1880     * normalzoom = 0x0 <p>
1881     * @see org.apache.poi.hssf.record.WindowTwoRecord
1882     * @see org.apache.poi.hssf.record.Record
1883     * @return record containing a WindowTwoRecord
1884     */

1885
1886    protected WindowTwoRecord createWindowTwo()
1887    {
1888        WindowTwoRecord retval = new WindowTwoRecord();
1889
1890        retval.setOptions(( short ) 0x6b6);
1891        retval.setTopRow(( short ) 0);
1892        retval.setLeftCol(( short ) 0);
1893        retval.setHeaderColor(0x40);
1894        retval.setPageBreakZoom(( short ) 0);
1895        retval.setNormalZoom(( short ) 0);
1896        return retval;
1897    }
1898
1899    /**
1900     * Creates the Selection record and sets it to nothing selected
1901     *
1902     * @see org.apache.poi.hssf.record.SelectionRecord
1903     * @see org.apache.poi.hssf.record.Record
1904     * @return record containing a SelectionRecord
1905     */

1906
1907    protected Record createSelection()
1908    {
1909        SelectionRecord retval = new SelectionRecord();
1910
1911        retval.setPane(( byte ) 0x3);
1912        retval.setActiveCellCol(( short ) 0x0);
1913        retval.setActiveCellRow(( short ) 0x0);
1914        retval.setNumRefs(( short ) 0x0);
1915        return retval;
1916    }
1917    
1918    /**
1919     * Returns the active row
1920     *
1921     * @see org.apache.poi.hssf.record.SelectionRecord
1922     * @return row the active row index
1923     */

1924    public int getActiveCellRow()
1925    {
1926        if (selection == null)
1927        {
1928            return 0;
1929        }
1930        return selection.getActiveCellRow();
1931    }
1932    
1933    /**
1934     * Sets the active row
1935     *
1936     * @param row the row index
1937     * @see org.apache.poi.hssf.record.SelectionRecord
1938     */

1939    public void setActiveCellRow(int row)
1940    {
1941        //shouldn't have a sheet w/o a SelectionRecord, but best to guard anyway
1942
if (selection != null)
1943        {
1944            selection.setActiveCellRow(row);
1945        }
1946    }
1947    
1948    /**
1949     * Returns the active column
1950     *
1951     * @see org.apache.poi.hssf.record.SelectionRecord
1952     * @return row the active column index
1953     */

1954    public short getActiveCellCol()
1955    {
1956        if (selection == null)
1957        {
1958            return (short) 0;
1959        }
1960        return selection.getActiveCellCol();
1961    }
1962    
1963    /**
1964     * Sets the active column
1965     *
1966     * @param col the column index
1967     * @see org.apache.poi.hssf.record.SelectionRecord
1968     */

1969    public void setActiveCellCol(short col)
1970    {
1971        //shouldn't have a sheet w/o a SelectionRecord, but best to guard anyway
1972
if (selection != null)
1973        {
1974            selection.setActiveCellCol(col);
1975        }
1976    }
1977
1978    protected Record createMergedCells()
1979    {
1980        MergeCellsRecord retval = new MergeCellsRecord();
1981        retval.setNumAreas(( short ) 0);
1982        return retval;
1983    }
1984
1985    /**
1986     * creates the EOF record
1987     * @see org.apache.poi.hssf.record.EOFRecord
1988     * @see org.apache.poi.hssf.record.Record
1989     * @return record containing a EOFRecord
1990     */

1991
1992    protected Record createEOF()
1993    {
1994        return new EOFRecord();
1995    }
1996
1997    /**
1998     * get the location of the DimensionsRecord (which is the last record before the value section)
1999     * @return location in the array of records of the DimensionsRecord
2000     */

2001
2002    public int getDimsLoc()
2003    {
2004        if (log.check( POILogger.DEBUG ))
2005            log.log(POILogger.DEBUG, "getDimsLoc dimsloc= " + dimsloc);
2006        return dimsloc;
2007    }
2008
2009    /**
2010     * in the event the record is a dimensions record, resets both the loc index and dimsloc index
2011     */

2012
2013    public void checkDimsLoc(Record rec, int recloc)
2014    {
2015        if (rec.getSid() == DimensionsRecord.sid)
2016        {
2017            loc = recloc;
2018            dimsloc = recloc;
2019        }
2020    }
2021
2022    public int getSize()
2023    {
2024        int retval = 0;
2025
2026        for (int k = 0; k < records.size(); k++)
2027        {
2028            retval += (( Record ) records.get(k)).getRecordSize();
2029        }
2030        //Add space for the IndexRecord
2031
if (rows != null) {
2032        final int blocks = rows.getRowBlockCount();
2033        retval += IndexRecord.getRecordSizeForBlockCount(blocks);
2034
2035        //Add space for the DBCell records
2036
//Once DBCell per block.
2037
//8 bytes per DBCell (non variable section)
2038
//2 bytes per row reference
2039
int startRetVal = retval;
2040        retval += (8 * blocks);
2041        for (Iterator JavaDoc itr = rows.getIterator(); itr.hasNext();) {
2042          RowRecord row = (RowRecord)itr.next();
2043          if (cells.rowHasCells(row.getRowNumber()))
2044            retval += 2;
2045        }
2046        }
2047        return retval;
2048    }
2049
2050    public List JavaDoc getRecords()
2051    {
2052        return records;
2053    }
2054
2055    /**
2056     * Gets the gridset record for this sheet.
2057     */

2058
2059    public GridsetRecord getGridsetRecord()
2060    {
2061        return gridset;
2062    }
2063
2064    /**
2065     * Returns the first occurance of a record matching a particular sid.
2066     */

2067
2068    public Record findFirstRecordBySid(short sid)
2069    {
2070        for (Iterator JavaDoc iterator = records.iterator(); iterator.hasNext(); )
2071        {
2072            Record record = ( Record ) iterator.next();
2073
2074            if (record.getSid() == sid)
2075            {
2076                return record;
2077            }
2078        }
2079        return null;
2080    }
2081
2082    /**
2083     * Sets the SCL record or creates it in the correct place if it does not
2084     * already exist.
2085     *
2086     * @param sclRecord The record to set.
2087     */

2088    public void setSCLRecord(SCLRecord sclRecord)
2089    {
2090        int oldRecordLoc = findFirstRecordLocBySid(SCLRecord.sid);
2091        if (oldRecordLoc == -1)
2092        {
2093            // Insert it after the window record
2094
int windowRecordLoc = findFirstRecordLocBySid(WindowTwoRecord.sid);
2095            records.add(windowRecordLoc+1, sclRecord);
2096        }
2097        else
2098        {
2099            records.set(oldRecordLoc, sclRecord);
2100        }
2101
2102    }
2103
2104    /**
2105     * Finds the first occurance of a record matching a particular sid and
2106     * returns it's position.
2107     * @param sid the sid to search for
2108     * @return the record position of the matching record or -1 if no match
2109     * is made.
2110     */

2111    public int findFirstRecordLocBySid( short sid )
2112    {
2113        int index = 0;
2114        for (Iterator JavaDoc iterator = records.iterator(); iterator.hasNext(); )
2115        {
2116            Record record = ( Record ) iterator.next();
2117
2118            if (record.getSid() == sid)
2119            {
2120                return index;
2121            }
2122            index++;
2123        }
2124        return -1;
2125    }
2126
2127    /**
2128     * Returns the HeaderRecord.
2129     * @return HeaderRecord for the sheet.
2130     */

2131    public HeaderRecord getHeader ()
2132    {
2133    return header;
2134    }
2135
2136    /**
2137     * Sets the HeaderRecord.
2138     * @param newHeader The new HeaderRecord for the sheet.
2139     */

2140    public void setHeader (HeaderRecord newHeader)
2141    {
2142        header = newHeader;
2143    }
2144
2145    /**
2146     * Returns the FooterRecord.
2147     * @return FooterRecord for the sheet.
2148     */

2149    public FooterRecord getFooter ()
2150    {
2151        return footer;
2152    }
2153
2154    /**
2155     * Sets the FooterRecord.
2156     * @param newFooter The new FooterRecord for the sheet.
2157     */

2158    public void setFooter (FooterRecord newFooter)
2159    {
2160        footer = newFooter;
2161    }
2162
2163    /**
2164     * Returns the PrintSetupRecord.
2165     * @return PrintSetupRecord for the sheet.
2166     */

2167    public PrintSetupRecord getPrintSetup ()
2168    {
2169        return printSetup;
2170    }
2171
2172    /**
2173     * Sets the PrintSetupRecord.
2174     * @param newPrintSetup The new PrintSetupRecord for the sheet.
2175     */

2176    public void setPrintSetup (PrintSetupRecord newPrintSetup)
2177    {
2178        printSetup = newPrintSetup;
2179    }
2180
2181    /**
2182     * Returns the PrintGridlinesRecord.
2183     * @return PrintGridlinesRecord for the sheet.
2184     */

2185    public PrintGridlinesRecord getPrintGridlines ()
2186    {
2187        return printGridlines;
2188    }
2189
2190    /**
2191     * Sets the PrintGridlinesRecord.
2192     * @param newPrintGridlines The new PrintGridlinesRecord for the sheet.
2193     */

2194    public void setPrintGridlines (PrintGridlinesRecord newPrintGridlines)
2195    {
2196        printGridlines = newPrintGridlines;
2197    }
2198
2199    /**
2200     * Sets whether the sheet is selected
2201     * @param sel True to select the sheet, false otherwise.
2202     */

2203    public void setSelected(boolean sel) {
2204        windowTwo.setSelected(sel);
2205    }
2206
2207     /**
2208      * Gets the size of the margin in inches.
2209      * @param margin which margin to get
2210      * @return the size of the margin
2211      */

2212    public double getMargin(short margin) {
2213    if (getMargins()[margin] != null)
2214        return margins[margin].getMargin();
2215    else {
2216        switch ( margin )
2217        {
2218        case LeftMargin:
2219            return .75;
2220        case RightMargin:
2221            return .75;
2222        case TopMargin:
2223            return 1.0;
2224        case BottomMargin:
2225            return 1.0;
2226        default :
2227            throw new RuntimeException JavaDoc( "Unknown margin constant: " + margin );
2228        }
2229    }
2230    }
2231
2232     /**
2233      * Sets the size of the margin in inches.
2234      * @param margin which margin to get
2235      * @param size the size of the margin
2236      */

2237    public void setMargin(short margin, double size) {
2238    Margin m = getMargins()[margin];
2239    if (m == null) {
2240        switch ( margin )
2241        {
2242        case LeftMargin:
2243            m = new LeftMarginRecord();
2244            records.add( getDimsLoc() + 1, m );
2245            break;
2246        case RightMargin:
2247            m = new RightMarginRecord();
2248            records.add( getDimsLoc() + 1, m );
2249            break;
2250        case TopMargin:
2251            m = new TopMarginRecord();
2252            records.add( getDimsLoc() + 1, m );
2253            break;
2254        case BottomMargin:
2255            m = new BottomMarginRecord();
2256            records.add( getDimsLoc() + 1, m );
2257            break;
2258        default :
2259            throw new RuntimeException JavaDoc( "Unknown margin constant: " + margin );
2260        }
2261        margins[margin] = m;
2262    }
2263    m.setMargin( size );
2264    }
2265
2266    public int getEofLoc()
2267    {
2268        return eofLoc;
2269    }
2270
2271    /**
2272     * Creates a split (freezepane).
2273     * @param colSplit Horizonatal position of split.
2274     * @param rowSplit Vertical position of split.
2275     * @param topRow Top row visible in bottom pane
2276     * @param leftmostColumn Left column visible in right pane.
2277     */

2278    public void createFreezePane(int colSplit, int rowSplit, int topRow, int leftmostColumn )
2279    {
2280        int loc = findFirstRecordLocBySid(WindowTwoRecord.sid);
2281        PaneRecord pane = new PaneRecord();
2282        pane.setX((short)colSplit);
2283        pane.setY((short)rowSplit);
2284        pane.setTopRow((short) topRow);
2285        pane.setLeftColumn((short) leftmostColumn);
2286        if (rowSplit == 0)
2287        {
2288            pane.setTopRow((short)0);
2289            pane.setActivePane((short)1);
2290        }
2291        else if (colSplit == 0)
2292        {
2293            pane.setLeftColumn((short)64);
2294            pane.setActivePane((short)2);
2295        }
2296        else
2297        {
2298            pane.setActivePane((short)0);
2299        }
2300        records.add(loc+1, pane);
2301
2302        windowTwo.setFreezePanes(true);
2303        windowTwo.setFreezePanesNoSplit(true);
2304
2305        SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
2306        sel.setPane((byte)pane.getActivePane());
2307
2308    }
2309
2310    /**
2311     * Creates a split pane.
2312     * @param xSplitPos Horizonatal position of split (in 1/20th of a point).
2313     * @param ySplitPos Vertical position of split (in 1/20th of a point).
2314     * @param topRow Top row visible in bottom pane
2315     * @param leftmostColumn Left column visible in right pane.
2316     * @param activePane Active pane. One of: PANE_LOWER_RIGHT,
2317     * PANE_UPPER_RIGHT, PANE_LOWER_LEFT, PANE_UPPER_LEFT
2318     * @see #PANE_LOWER_LEFT
2319     * @see #PANE_LOWER_RIGHT
2320     * @see #PANE_UPPER_LEFT
2321     * @see #PANE_UPPER_RIGHT
2322     */

2323    public void createSplitPane(int xSplitPos, int ySplitPos, int topRow, int leftmostColumn, int activePane )
2324    {
2325        int loc = findFirstRecordLocBySid(WindowTwoRecord.sid);
2326        PaneRecord r = new PaneRecord();
2327        r.setX((short)xSplitPos);
2328        r.setY((short)ySplitPos);
2329        r.setTopRow((short) topRow);
2330        r.setLeftColumn((short) leftmostColumn);
2331        r.setActivePane((short) activePane);
2332        records.add(loc+1, r);
2333
2334        windowTwo.setFreezePanes(false);
2335        windowTwo.setFreezePanesNoSplit(false);
2336
2337        SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
2338        sel.setPane(PANE_LOWER_RIGHT);
2339
2340    }
2341
2342    public SelectionRecord getSelection()
2343    {
2344        return selection;
2345    }
2346
2347    public void setSelection( SelectionRecord selection )
2348    {
2349        this.selection = selection;
2350    }
2351
2352    /**
2353     * creates a Protect record with protect set to false.
2354     * @see org.apache.poi.hssf.record.ProtectRecord
2355     * @see org.apache.poi.hssf.record.Record
2356     * @return a ProtectRecord
2357     */

2358    protected Record createProtect()
2359    {
2360        if (log.check( POILogger.DEBUG ))
2361            log.log(POILogger.DEBUG, "create protect record with protection disabled");
2362        ProtectRecord retval = new ProtectRecord();
2363
2364        retval.setProtect(false);
2365        // by default even when we support encryption we won't
2366
return retval;
2367    }
2368
2369    public ProtectRecord getProtect()
2370    {
2371        return protect;
2372    }
2373
2374    /**
2375     * Sets whether the gridlines are shown in a viewer.
2376     * @param show whether to show gridlines or not
2377     */

2378    public void setDisplayGridlines(boolean show) {
2379        windowTwo.setDisplayGridlines(show);
2380    }
2381
2382    /**
2383     * Returns if gridlines are displayed.
2384     * @return whether gridlines are displayed
2385     */

2386    public boolean isDisplayGridlines() {
2387    return windowTwo.getDisplayGridlines();
2388    }
2389
2390    /**
2391     * Sets whether the formulas are shown in a viewer.
2392     * @param show whether to show formulas or not
2393     */

2394    public void setDisplayFormulas(boolean show) {
2395        windowTwo.setDisplayFormulas(show);
2396    }
2397
2398    /**
2399     * Returns if formulas are displayed.
2400     * @return whether formulas are displayed
2401     */

2402    public boolean isDisplayFormulas() {
2403    return windowTwo.getDisplayFormulas();
2404    }
2405
2406    /**
2407     * Sets whether the RowColHeadings are shown in a viewer.
2408     * @param show whether to show RowColHeadings or not
2409     */

2410    public void setDisplayRowColHeadings(boolean show) {
2411        windowTwo.setDisplayRowColHeadings(show);
2412    }
2413
2414    /**
2415     * Returns if RowColHeadings are displayed.
2416     * @return whether RowColHeadings are displayed
2417     */

2418    public boolean isDisplayRowColHeadings() {
2419        return windowTwo.getDisplayRowColHeadings();
2420    }
2421
2422    /**
2423     * Returns the array of margins. If not created, will create.
2424     *
2425     * @return the array of marings.
2426     */

2427    protected Margin[] getMargins() {
2428        if (margins == null)
2429            margins = new Margin[4];
2430        return margins;
2431    }
2432
2433    public int aggregateDrawingRecords(DrawingManager drawingManager)
2434    {
2435        int loc = findFirstRecordLocBySid(DrawingRecord.sid);
2436        boolean noDrawingRecordsFound = loc == -1;
2437        if (noDrawingRecordsFound)
2438        {
2439            EscherAggregate aggregate = new EscherAggregate( drawingManager );
2440            loc = findFirstRecordLocBySid(EscherAggregate.sid);
2441            if (loc == -1)
2442            {
2443                loc = findFirstRecordLocBySid( WindowTwoRecord.sid );
2444            }
2445            else
2446            {
2447                getRecords().remove(loc);
2448            }
2449            getRecords().add( loc, aggregate );
2450            return loc;
2451        }
2452        else
2453        {
2454            List JavaDoc records = getRecords();
2455            EscherAggregate r = EscherAggregate.createAggregate( records, loc, drawingManager );
2456            int startloc = loc;
2457            while ( loc + 1 < records.size()
2458                    && records.get( loc ) instanceof DrawingRecord
2459                    && records.get( loc + 1 ) instanceof ObjRecord )
2460            {
2461                loc += 2;
2462            }
2463            int endloc = loc-1;
2464            for(int i = 0; i < (endloc - startloc + 1); i++)
2465                records.remove(startloc);
2466            records.add(startloc, r);
2467
2468            return startloc;
2469        }
2470    }
2471
2472    /**
2473     * Perform any work necessary before the sheet is about to be serialized.
2474     * For instance the escher aggregates size needs to be calculated before
2475     * serialization so that the dgg record (which occurs first) can be written.
2476     */

2477    public void preSerialize()
2478    {
2479        for ( Iterator JavaDoc iterator = getRecords().iterator(); iterator.hasNext(); )
2480        {
2481            Record r = (Record) iterator.next();
2482            if (r instanceof EscherAggregate)
2483                r.getRecordSize(); // Trigger flatterning of user model and corresponding update of dgg record.
2484
}
2485    }
2486
2487    /**
2488     * Shifts all the page breaks in the range "count" number of rows/columns
2489     * @param breaks The page record to be shifted
2490     * @param start Starting "main" value to shift breaks
2491     * @param stop Ending "main" value to shift breaks
2492     * @param count number of units (rows/columns) to shift by
2493     */

2494    public void shiftBreaks(PageBreakRecord breaks, short start, short stop, int count) {
2495    
2496        if(rowBreaks == null)
2497            return;
2498        Iterator JavaDoc iterator = breaks.getBreaksIterator();
2499        List JavaDoc shiftedBreak = new ArrayList JavaDoc();
2500        while(iterator.hasNext())
2501        {
2502            PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
2503            short breakLocation = breakItem.main;
2504            boolean inStart = (breakLocation >= start);
2505            boolean inEnd = (breakLocation <= stop);
2506            if(inStart && inEnd)
2507                shiftedBreak.add(breakItem);
2508        }
2509        
2510        iterator = shiftedBreak.iterator();
2511        while (iterator.hasNext()) {
2512            PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
2513            breaks.removeBreak(breakItem.main);
2514            breaks.addBreak((short)(breakItem.main+count), breakItem.subFrom, breakItem.subTo);
2515        }
2516    }
2517    
2518    /**
2519     * Sets a page break at the indicated row
2520     * @param row
2521     */

2522    public void setRowBreak(int row, short fromCol, short toCol) {
2523        rowBreaks.addBreak((short)row, fromCol, toCol);
2524    }
2525
2526    /**
2527     * Removes a page break at the indicated row
2528     * @param row
2529     */

2530    public void removeRowBreak(int row) {
2531        rowBreaks.removeBreak((short)row);
2532    }
2533
2534    /**
2535     * Queries if the specified row has a page break
2536     * @param row
2537     * @return true if the specified row has a page break
2538     */

2539    public boolean isRowBroken(int row) {
2540        return rowBreaks.getBreak((short)row) != null;
2541    }
2542
2543    /**
2544     * Sets a page break at the indicated column
2545     *
2546     */

2547    public void setColumnBreak(short column, short fromRow, short toRow) {
2548        colBreaks.addBreak(column, fromRow, toRow);
2549    }
2550
2551    /**
2552     * Removes a page break at the indicated column
2553     *
2554     */

2555    public void removeColumnBreak(short column) {
2556        colBreaks.removeBreak(column);
2557    }
2558
2559    /**
2560     * Queries if the specified column has a page break
2561     *
2562     * @return true if the specified column has a page break
2563     */

2564    public boolean isColumnBroken(short column) {
2565        return colBreaks.getBreak(column) != null;
2566    }
2567    
2568    /**
2569     * Shifts the horizontal page breaks for the indicated count
2570     * @param startingRow
2571     * @param endingRow
2572     * @param count
2573     */

2574    public void shiftRowBreaks(int startingRow, int endingRow, int count) {
2575        shiftBreaks(rowBreaks, (short)startingRow, (short)endingRow, (short)count);
2576    }
2577
2578    /**
2579     * Shifts the vertical page breaks for the indicated count
2580     * @param startingCol
2581     * @param endingCol
2582     * @param count
2583     */

2584    public void shiftColumnBreaks(short startingCol, short endingCol, short count) {
2585        shiftBreaks(colBreaks, startingCol, endingCol, count);
2586    }
2587    
2588    /**
2589     * Returns all the row page breaks
2590     * @return all the row page breaks
2591     */

2592    public Iterator JavaDoc getRowBreaks() {
2593        return rowBreaks.getBreaksIterator();
2594    }
2595    
2596    /**
2597     * Returns the number of row page breaks
2598     * @return the number of row page breaks
2599     */

2600    public int getNumRowBreaks(){
2601        return (int)rowBreaks.getNumBreaks();
2602    }
2603    
2604    /**
2605     * Returns all the column page breaks
2606     * @return all the column page breaks
2607     */

2608    public Iterator JavaDoc getColumnBreaks(){
2609        return colBreaks.getBreaksIterator();
2610    }
2611    
2612    /**
2613     * Returns the number of column page breaks
2614     * @return the number of column page breaks
2615     */

2616    public int getNumColumnBreaks(){
2617        return (int)colBreaks.getNumBreaks();
2618    }
2619
2620    public void setColumnGroupCollapsed( short columnNumber, boolean collapsed )
2621    {
2622        if (collapsed)
2623        {
2624            columns.collapseColumn( columnNumber );
2625        }
2626        else
2627        {
2628            columns.expandColumn( columnNumber );
2629        }
2630    }
2631
2632// private void collapseColumn( short columnNumber )
2633
// {
2634
// int idx = findColumnIdx( columnNumber, 0 );
2635
// if (idx == -1)
2636
// return;
2637
//
2638
// // Find the start of the group.
2639
// ColumnInfoRecord columnInfo = (ColumnInfoRecord) columnSizes.get( findStartOfColumnOutlineGroup( idx ) );
2640
//
2641
// // Hide all the columns until the end of the group
2642
// columnInfo = writeHidden( columnInfo, idx, true );
2643
//
2644
// // Write collapse field
2645
// setColumn( (short) ( columnInfo.getLastColumn() + 1 ), null, null, null, Boolean.TRUE);
2646
// }
2647

2648// private void expandColumn( short columnNumber )
2649
// {
2650
// int idx = findColumnIdx( columnNumber, 0 );
2651
// if (idx == -1)
2652
// return;
2653
//
2654
// // If it is already exapanded do nothing.
2655
// if (!isColumnGroupCollapsed(idx))
2656
// return;
2657
//
2658
// // Find the start of the group.
2659
// int startIdx = findStartOfColumnOutlineGroup( idx );
2660
// ColumnInfoRecord columnInfo = getColInfo( startIdx );
2661
//
2662
// // Find the end of the group.
2663
// int endIdx = findEndOfColumnOutlineGroup( idx );
2664
// ColumnInfoRecord endColumnInfo = getColInfo( endIdx );
2665
//
2666
// // expand:
2667
// // colapsed bit must be unset
2668
// // hidden bit gets unset _if_ surrounding groups are expanded you can determine
2669
// // this by looking at the hidden bit of the enclosing group. You will have
2670
// // to look at the start and the end of the current group to determine which
2671
// // is the enclosing group
2672
// // hidden bit only is altered for this outline level. ie. don't uncollapse contained groups
2673
// if (!isColumnGroupHiddenByParent( idx ))
2674
// {
2675
// for (int i = startIdx; i <= endIdx; i++)
2676
// {
2677
// if (columnInfo.getOutlineLevel() == getColInfo(i).getOutlineLevel())
2678
// getColInfo(i).setHidden( false );
2679
// }
2680
// }
2681
//
2682
// // Write collapse field
2683
// setColumn( (short) ( columnInfo.getLastColumn() + 1 ), null, null, null, Boolean.FALSE);
2684
// }
2685

2686// private boolean isColumnGroupCollapsed( int idx )
2687
// {
2688
// int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup( idx );
2689
// if (endOfOutlineGroupIdx >= columnSizes.size())
2690
// return false;
2691
// if (getColInfo(endOfOutlineGroupIdx).getLastColumn() + 1 != getColInfo(endOfOutlineGroupIdx + 1).getFirstColumn())
2692
// return false;
2693
// else
2694
// return getColInfo(endOfOutlineGroupIdx+1).getCollapsed();
2695
// }
2696

2697// private boolean isColumnGroupHiddenByParent( int idx )
2698
// {
2699
// // Look out outline details of end
2700
// int endLevel;
2701
// boolean endHidden;
2702
// int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup( idx );
2703
// if (endOfOutlineGroupIdx >= columnSizes.size())
2704
// {
2705
// endLevel = 0;
2706
// endHidden = false;
2707
// }
2708
// else if (getColInfo(endOfOutlineGroupIdx).getLastColumn() + 1 != getColInfo(endOfOutlineGroupIdx + 1).getFirstColumn())
2709
// {
2710
// endLevel = 0;
2711
// endHidden = false;
2712
// }
2713
// else
2714
// {
2715
// endLevel = getColInfo( endOfOutlineGroupIdx + 1).getOutlineLevel();
2716
// endHidden = getColInfo( endOfOutlineGroupIdx + 1).getHidden();
2717
// }
2718
//
2719
// // Look out outline details of start
2720
// int startLevel;
2721
// boolean startHidden;
2722
// int startOfOutlineGroupIdx = findStartOfColumnOutlineGroup( idx );
2723
// if (startOfOutlineGroupIdx <= 0)
2724
// {
2725
// startLevel = 0;
2726
// startHidden = false;
2727
// }
2728
// else if (getColInfo(startOfOutlineGroupIdx).getFirstColumn() - 1 != getColInfo(startOfOutlineGroupIdx - 1).getLastColumn())
2729
// {
2730
// startLevel = 0;
2731
// startHidden = false;
2732
// }
2733
// else
2734
// {
2735
// startLevel = getColInfo( startOfOutlineGroupIdx - 1).getOutlineLevel();
2736
// startHidden = getColInfo( startOfOutlineGroupIdx - 1 ).getHidden();
2737
// }
2738
//
2739
// if (endLevel > startLevel)
2740
// {
2741
// return endHidden;
2742
// }
2743
// else
2744
// {
2745
// return startHidden;
2746
// }
2747
// }
2748

2749// private ColumnInfoRecord getColInfo(int idx)
2750
// {
2751
// return columns.getColInfo( idx );
2752
// }
2753

2754// private int findStartOfColumnOutlineGroup(int idx)
2755
// {
2756
// // Find the start of the group.
2757
// ColumnInfoRecord columnInfo = (ColumnInfoRecord) columnSizes.get( idx );
2758
// int level = columnInfo.getOutlineLevel();
2759
// while (idx != 0)
2760
// {
2761
// ColumnInfoRecord prevColumnInfo = (ColumnInfoRecord) columnSizes.get( idx - 1 );
2762
// if (columnInfo.getFirstColumn() - 1 == prevColumnInfo.getLastColumn())
2763
// {
2764
// if (prevColumnInfo.getOutlineLevel() < level)
2765
// {
2766
// break;
2767
// }
2768
// idx--;
2769
// columnInfo = prevColumnInfo;
2770
// }
2771
// else
2772
// {
2773
// break;
2774
// }
2775
// }
2776
//
2777
// return idx;
2778
// }
2779

2780// private int findEndOfColumnOutlineGroup(int idx)
2781
// {
2782
// // Find the end of the group.
2783
// ColumnInfoRecord columnInfo = (ColumnInfoRecord) columnSizes.get( idx );
2784
// int level = columnInfo.getOutlineLevel();
2785
// while (idx < columnSizes.size() - 1)
2786
// {
2787
// ColumnInfoRecord nextColumnInfo = (ColumnInfoRecord) columnSizes.get( idx + 1 );
2788
// if (columnInfo.getLastColumn() + 1 == nextColumnInfo.getFirstColumn())
2789
// {
2790
// if (nextColumnInfo.getOutlineLevel() < level)
2791
// {
2792
// break;
2793
// }
2794
// idx++;
2795
// columnInfo = nextColumnInfo;
2796
// }
2797
// else
2798
// {
2799
// break;
2800
// }
2801
// }
2802
//
2803
// return idx;
2804
// }
2805

2806    public void groupRowRange(int fromRow, int toRow, boolean indent)
2807    {
2808        checkRows();
2809        for (int rowNum = fromRow; rowNum <= toRow; rowNum++)
2810        {
2811            RowRecord row = getRow( rowNum );
2812            if (row == null)
2813            {
2814                row = createRow( rowNum );
2815                addRow( row );
2816            }
2817            int level = row.getOutlineLevel();
2818            if (indent) level++; else level--;
2819            level = Math.max(0, level);
2820            level = Math.min(7, level);
2821            row.setOutlineLevel((short) ( level ));
2822        }
2823
2824        recalcRowGutter();
2825    }
2826
2827    private void recalcRowGutter()
2828    {
2829        int maxLevel = 0;
2830        Iterator JavaDoc iterator = rows.getIterator();
2831        while ( iterator.hasNext() )
2832        {
2833            RowRecord rowRecord = (RowRecord) iterator.next();
2834            maxLevel = Math.max(rowRecord.getOutlineLevel(), maxLevel);
2835        }
2836
2837        GutsRecord guts = (GutsRecord) findFirstRecordBySid( GutsRecord.sid );
2838        guts.setRowLevelMax( (short) ( maxLevel + 1 ) );
2839        guts.setLeftRowGutter( (short) ( 29 + (12 * (maxLevel)) ) );
2840    }
2841
2842    public void setRowGroupCollapsed( int row, boolean collapse )
2843    {
2844        if (collapse)
2845        {
2846            rows.collapseRow( row );
2847        }
2848        else
2849        {
2850            rows.expandRow( row );
2851        }
2852    }
2853
2854
2855// private void collapseRow( int rowNumber )
2856
// {
2857
//
2858
// // Find the start of the group.
2859
// int startRow = rows.findStartOfRowOutlineGroup( rowNumber );
2860
// RowRecord rowRecord = (RowRecord) rows.getRow( startRow );
2861
//
2862
// // Hide all the columns until the end of the group
2863
// int lastRow = rows.writeHidden( rowRecord, startRow, true );
2864
//
2865
// // Write collapse field
2866
// if (getRow(lastRow + 1) != null)
2867
// {
2868
// getRow(lastRow + 1).setColapsed( true );
2869
// }
2870
// else
2871
// {
2872
// RowRecord row = createRow( lastRow + 1);
2873
// row.setColapsed( true );
2874
// rows.insertRow( row );
2875
// }
2876
// }
2877

2878// private int findStartOfRowOutlineGroup(int row)
2879
// {
2880
// // Find the start of the group.
2881
// RowRecord rowRecord = rows.getRow( row );
2882
// int level = rowRecord.getOutlineLevel();
2883
// int currentRow = row;
2884
// while (rows.getRow( currentRow ) != null)
2885
// {
2886
// rowRecord = rows.getRow( currentRow );
2887
// if (rowRecord.getOutlineLevel() < level)
2888
// return currentRow + 1;
2889
// currentRow--;
2890
// }
2891
//
2892
// return currentRow + 1;
2893
// }
2894

2895// private int writeHidden( RowRecord rowRecord, int row, boolean hidden )
2896
// {
2897
// int level = rowRecord.getOutlineLevel();
2898
// while (rowRecord != null && rows.getRow(row).getOutlineLevel() >= level)
2899
// {
2900
// rowRecord.setZeroHeight( hidden );
2901
// row++;
2902
// rowRecord = rows.getRow( row );
2903
// }
2904
// return row - 1;
2905
// }
2906

2907// private int findEndOfRowOutlineGroup( int row )
2908
// {
2909
// int level = getRow( row ).getOutlineLevel();
2910
// int currentRow;
2911
// for (currentRow = row; currentRow < rows.getLastRowNum(); currentRow++)
2912
// {
2913
// if (getRow(currentRow) == null || getRow(currentRow).getOutlineLevel() < level)
2914
// {
2915
// break;
2916
// }
2917
// }
2918
//
2919
// return currentRow-1;
2920
// }
2921

2922// private boolean isRowGroupCollapsed( int row )
2923
// {
2924
// int collapseRow = rows.findEndOfRowOutlineGroup( row ) + 1;
2925
//
2926
// if (getRow(collapseRow) == null)
2927
// return false;
2928
// else
2929
// return getRow( collapseRow ).getColapsed();
2930
// }
2931

2932
2933// private boolean isRowGroupHiddenByParent( int row )
2934
// {
2935
// // Look out outline details of end
2936
// int endLevel;
2937
// boolean endHidden;
2938
// int endOfOutlineGroupIdx = rows.findEndOfRowOutlineGroup( row );
2939
// if (getRow( endOfOutlineGroupIdx + 1 ) == null)
2940
// {
2941
// endLevel = 0;
2942
// endHidden = false;
2943
// }
2944
// else
2945
// {
2946
// endLevel = getRow( endOfOutlineGroupIdx + 1).getOutlineLevel();
2947
// endHidden = getRow( endOfOutlineGroupIdx + 1).getZeroHeight();
2948
// }
2949
//
2950
// // Look out outline details of start
2951
// int startLevel;
2952
// boolean startHidden;
2953
// int startOfOutlineGroupIdx = rows.findStartOfRowOutlineGroup( row );
2954
// if (startOfOutlineGroupIdx - 1 < 0 || getRow(startOfOutlineGroupIdx - 1) == null)
2955
// {
2956
// startLevel = 0;
2957
// startHidden = false;
2958
// }
2959
// else
2960
// {
2961
// startLevel = getRow( startOfOutlineGroupIdx - 1).getOutlineLevel();
2962
// startHidden = getRow( startOfOutlineGroupIdx - 1 ).getZeroHeight();
2963
// }
2964
//
2965
// if (endLevel > startLevel)
2966
// {
2967
// return endHidden;
2968
// }
2969
// else
2970
// {
2971
// return startHidden;
2972
// }
2973
// }
2974

2975}
2976
Popular Tags