From: Glen Stampoultzis
Date: Wed, 28 Jul 2004 13:06:33 +0000 (+0000)
Subject: Support for outlining. Enjoy.
X-Git-Tag: REL_2_5_1~5
X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=babf0167eeaf456a0a7f8df8b373cce0a1b0cd66;p=poi.git
Support for outlining. Enjoy.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/branches/REL_2_BRANCH@353574 13f79535-47bb-0310-9956-ffa450edef68
---
diff --git a/src/documentation/content/xdocs/hssf/quick-guide.xml b/src/documentation/content/xdocs/hssf/quick-guide.xml
index ea5830e8d7..5dfbe81092 100644
--- a/src/documentation/content/xdocs/hssf/quick-guide.xml
+++ b/src/documentation/content/xdocs/hssf/quick-guide.xml
@@ -1,12 +1,12 @@
-
+
Busy Developers' Guide to HSSF Features
-
+
@@ -44,6 +44,7 @@
Drawing Shapes.
Styling Shapes.
Shapes and Graphics2d.
+ Outlining.
Features
@@ -902,6 +903,42 @@
using the POI logging infrastructure (disabled by default).
+
+
+ Outlining
+
+ Outlines are great for grouping sections of information
+ together and can be added easily to columns and rows
+ using the POI API. Here's how:
+
+
+
+ To collapse (or expand) an outline use the following calls:
+
+
+
+ The row/column you choose should contain an already
+ created group. It can be anywhere within the group.
+
+
diff --git a/src/examples/src/org/apache/poi/hssf/usermodel/examples/Outlines.java b/src/examples/src/org/apache/poi/hssf/usermodel/examples/Outlines.java
new file mode 100644
index 0000000000..de6195dc8a
--- /dev/null
+++ b/src/examples/src/org/apache/poi/hssf/usermodel/examples/Outlines.java
@@ -0,0 +1,284 @@
+
+/* ====================================================================
+ Copyright 2002-2004 Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+
+package org.apache.poi.hssf.usermodel.examples;
+
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Creates outlines.
+ *
+ * @author Glen Stampoultzis (glens at apache.org)
+ */
+public class Outlines
+{
+ private Outlines(){}
+
+ public static void main(String[] args)
+ throws IOException
+ {
+ createCase1( "outline1.xls" );
+ System.out.println( "outline1.xls written. Two expanded groups." );
+ createCase2( "outline2.xls" );
+ System.out.println( "outline2.xls written. Two groups. Inner group collapsed." );
+ createCase3( "outline3.xls" );
+ System.out.println( "outline3.xls written. Two groups. Both collapsed." );
+ createCase4( "outline4.xls" );
+ System.out.println( "outline4.xls written. Two groups. Collapsed then inner group expanded." );
+ createCase5( "outline5.xls" );
+ System.out.println( "outline5.xls written. Two groups. Collapsed then reexpanded." );
+ createCase6( "outline6.xls" );
+ System.out.println( "outline6.xls written. Two groups with matching end points. Second group collapsed." );
+ createCase7( "outline7.xls" );
+ System.out.println( "outline7.xls written. Row outlines." );
+ createCase8( "outline8.xls" );
+ System.out.println( "outline8.xls written. Row outlines. Inner group collapsed." );
+ createCase9( "outline9.xls" );
+ System.out.println( "outline9.xls written. Row outlines. Both collapsed." );
+ createCase10( "outline10.xls" );
+ System.out.println( "outline10.xls written. Row outlines. Collapsed then inner group expanded." );
+ createCase11( "outline11.xls" );
+ System.out.println( "outline11.xls written. Row outlines. Collapsed then expanded." );
+ createCase12( "outline12.xls" );
+ System.out.println( "outline12.xls written. Row outlines. Two row groups with matching end points. Second group collapsed." );
+ createCase13( "outline13.xls" );
+ System.out.println( "outline13.xls written. Mixed bag." );
+ }
+
+ private static void createCase1( String filename ) throws IOException{
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupColumn( (short)4, (short)7 );
+
+ for (int row = 0; row < 200; row++)
+ {
+ HSSFRow r = sheet1.createRow( row );
+ for (int column = 0; column < 200; column++)
+ {
+ HSSFCell c = r.createCell( (short) column );
+ c.setCellValue( column );
+ }
+ }
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+ private static void createCase2( String filename ) throws IOException{
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupColumn( (short)2, (short)10 );
+ sheet1.groupColumn( (short)4, (short)7 );
+ sheet1.setColumnGroupCollapsed( (short)4, true );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+ private static void createCase3( String filename ) throws IOException{
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupColumn( (short)2, (short)10 );
+ sheet1.groupColumn( (short)4, (short)7 );
+ sheet1.setColumnGroupCollapsed( (short)4, true );
+ sheet1.setColumnGroupCollapsed( (short)2, true );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+ private static void createCase4( String filename ) throws IOException{
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupColumn( (short)2, (short)10 );
+ sheet1.groupColumn( (short)4, (short)7 );
+ sheet1.setColumnGroupCollapsed( (short)4, true );
+ sheet1.setColumnGroupCollapsed( (short)2, true );
+
+ sheet1.setColumnGroupCollapsed( (short)4, false );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+ private static void createCase5( String filename ) throws IOException{
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupColumn( (short)2, (short)10 );
+ sheet1.groupColumn( (short)4, (short)7 );
+ sheet1.setColumnGroupCollapsed( (short)4, true );
+ sheet1.setColumnGroupCollapsed( (short)2, true );
+
+ sheet1.setColumnGroupCollapsed( (short)4, false );
+ sheet1.setColumnGroupCollapsed( (short)3, false );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+ private static void createCase6( String filename ) throws IOException{
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupColumn( (short)2, (short)10 );
+ sheet1.groupColumn( (short)4, (short)10 );
+ sheet1.setColumnGroupCollapsed( (short)4, true );
+ sheet1.setColumnGroupCollapsed( (short)2, true );
+
+ sheet1.setColumnGroupCollapsed( (short)3, false );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+ private static void createCase7( String filename )
+ throws IOException
+ {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupRow( 5, 14 );
+ sheet1.groupRow( 7, 10 );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+ private static void createCase8( String filename )
+ throws IOException
+ {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupRow( 5, 14 );
+ sheet1.groupRow( 7, 10 );
+ sheet1.setRowGroupCollapsed( 7, true );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+ private static void createCase9( String filename )
+ throws IOException
+ {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupRow( 5, 14 );
+ sheet1.groupRow( 7, 10 );
+ sheet1.setRowGroupCollapsed( 7, true );
+ sheet1.setRowGroupCollapsed( 5, true );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+
+ private static void createCase10( String filename )
+ throws IOException
+ {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupRow( 5, 14 );
+ sheet1.groupRow( 7, 10 );
+ sheet1.setRowGroupCollapsed( 7, true );
+ sheet1.setRowGroupCollapsed( 5, true );
+ sheet1.setRowGroupCollapsed( 8, false );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+ private static void createCase11( String filename )
+ throws IOException
+ {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupRow( 5, 14 );
+ sheet1.groupRow( 7, 10 );
+ sheet1.setRowGroupCollapsed( 7, true );
+ sheet1.setRowGroupCollapsed( 5, true );
+ sheet1.setRowGroupCollapsed( 8, false );
+ sheet1.setRowGroupCollapsed( 14, false );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+ private static void createCase12( String filename )
+ throws IOException
+ {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupRow( 5, 14 );
+ sheet1.groupRow( 7, 14 );
+ sheet1.setRowGroupCollapsed( 7, true );
+ sheet1.setRowGroupCollapsed( 5, true );
+ sheet1.setRowGroupCollapsed( 6, false );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+ private static void createCase13( String filename )
+ throws IOException
+ {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet1 = wb.createSheet("new sheet");
+
+ sheet1.groupRow( 5, 14 );
+ sheet1.groupRow( 7, 14 );
+ sheet1.groupRow( 16, 19 );
+
+ sheet1.groupColumn( (short)4, (short)7 );
+ sheet1.groupColumn( (short)9, (short)12 );
+ sheet1.groupColumn( (short)10, (short)11 );
+
+ FileOutputStream fileOut = new FileOutputStream(filename);
+ wb.write(fileOut);
+ fileOut.close();
+ }
+
+
+}
diff --git a/src/java/org/apache/poi/hssf/model/Sheet.java b/src/java/org/apache/poi/hssf/model/Sheet.java
index 90909662bc..1a44d6e57f 100644
--- a/src/java/org/apache/poi/hssf/model/Sheet.java
+++ b/src/java/org/apache/poi/hssf/model/Sheet.java
@@ -22,6 +22,7 @@ import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
+import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.util.IntList;
import org.apache.poi.util.POILogFactory;
@@ -60,36 +61,37 @@ public class Sheet implements Model
public static final short TopMargin = 2;
public static final short BottomMargin = 3;
- protected ArrayList records = null;
- int preoffset = 0; // offset of the sheet in a new file
- int loc = 0;
- protected boolean containsLabels = false;
- protected int dimsloc = 0;
- protected DimensionsRecord dims;
- protected DefaultColWidthRecord defaultcolwidth = null;
- protected DefaultRowHeightRecord defaultrowheight = null;
- protected GridsetRecord gridset = null;
- protected PrintSetupRecord printSetup = null;
- protected HeaderRecord header = null;
- protected FooterRecord footer = null;
- protected PrintGridlinesRecord printGridlines = null;
- protected WindowTwoRecord windowTwo = null;
- protected MergeCellsRecord merged = null;
- protected Margin margins[] = null;
- protected List mergedRecords = new ArrayList();
- protected int numMergedRegions = 0;
- protected SelectionRecord selection = null;
private static POILogger log = POILogFactory.getLogger(Sheet.class);
- private ArrayList columnSizes = null; // holds column info
- protected ValueRecordsAggregate cells = null;
- protected RowRecordsAggregate rows = null;
- private Iterator valueRecIterator = null;
- private Iterator rowRecIterator = null;
- protected int eofLoc = 0;
- protected ProtectRecord protect = null;
- protected PageBreakRecord rowBreaks = null;
- protected PageBreakRecord colBreaks = null;
-
+
+ protected ArrayList records = null;
+ int preoffset = 0; // offset of the sheet in a new file
+ int loc = 0;
+ protected boolean containsLabels = false;
+ protected int dimsloc = 0;
+ protected DimensionsRecord dims;
+ protected DefaultColWidthRecord defaultcolwidth = null;
+ protected DefaultRowHeightRecord defaultrowheight = null;
+ protected GridsetRecord gridset = null;
+ protected PrintSetupRecord printSetup = null;
+ protected HeaderRecord header = null;
+ protected FooterRecord footer = null;
+ protected PrintGridlinesRecord printGridlines = null;
+ protected WindowTwoRecord windowTwo = null;
+ protected MergeCellsRecord merged = null;
+ protected Margin[] margins = null;
+ protected List mergedRecords = new ArrayList();
+ protected int numMergedRegions = 0;
+ protected SelectionRecord selection = null;
+ protected ColumnInfoRecordsAggregate columns = null;
+ protected ValueRecordsAggregate cells = null;
+ protected RowRecordsAggregate rows = null;
+ private Iterator valueRecIterator = null;
+ private Iterator rowRecIterator = null;
+ protected int eofLoc = 0;
+ protected ProtectRecord protect = null;
+ protected PageBreakRecord rowBreaks = null;
+ protected PageBreakRecord colBreaks = null;
+
public static final byte PANE_LOWER_RIGHT = (byte)0;
public static final byte PANE_UPPER_RIGHT = (byte)1;
@@ -123,9 +125,10 @@ public class Sheet implements Model
*/
public static Sheet createSheet(List recs, int sheetnum, int offset)
{
- log.logFormatted(POILogger.DEBUG,
- "Sheet createSheet (existing file) with %",
- new Integer(recs.size()));
+ if (log.check( POILogger.DEBUG ))
+ log.logFormatted(POILogger.DEBUG,
+ "Sheet createSheet (existing file) with %",
+ new Integer(recs.size()));
Sheet retval = new Sheet();
ArrayList records = new ArrayList(recs.size() / 5);
boolean isfirstcell = true;
@@ -138,18 +141,21 @@ public class Sheet implements Model
if (rec.getSid() == LabelRecord.sid)
{
- log.log(POILogger.DEBUG, "Hit label record.");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "Hit label record.");
retval.containsLabels = true;
}
else if (rec.getSid() == BOFRecord.sid)
{
bofEofNestingLevel++;
- log.log(POILogger.DEBUG, "Hit BOF record. Nesting increased to " + bofEofNestingLevel);
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "Hit BOF record. Nesting increased to " + bofEofNestingLevel);
}
else if (rec.getSid() == EOFRecord.sid)
{
--bofEofNestingLevel;
- log.log(POILogger.DEBUG, "Hit EOF record. Nesting decreased to " + bofEofNestingLevel);
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "Hit EOF record. Nesting decreased to " + bofEofNestingLevel);
if (bofEofNestingLevel == 0) {
records.add(rec);
retval.eofLoc = k;
@@ -158,6 +164,13 @@ public class Sheet implements Model
}
else if (rec.getSid() == DimensionsRecord.sid)
{
+ // Make a columns aggregate if one hasn't ready been created.
+ if (retval.columns == null)
+ {
+ retval.columns = new ColumnInfoRecordsAggregate();
+ records.add(retval.columns);
+ }
+
retval.dims = ( DimensionsRecord ) rec;
retval.dimsloc = records.size();
}
@@ -169,11 +182,16 @@ public class Sheet implements Model
}
else if (rec.getSid() == ColumnInfoRecord.sid)
{
- if (retval.columnSizes == null)
+ ColumnInfoRecord col = (ColumnInfoRecord)rec;
+ if (retval.columns != null)
{
- retval.columnSizes = new ArrayList();
+ rec = null; //only add the aggregate once
}
- retval.columnSizes.add(rec);
+ else
+ {
+ rec = retval.columns = new ColumnInfoRecordsAggregate();
+ }
+ retval.columns.insertColumn(col);
}
else if (rec.getSid() == DefaultColWidthRecord.sid)
{
@@ -283,7 +301,8 @@ public class Sheet implements Model
// {
// retval.cells = new ValueRecordsAggregate();
// }
- log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited");
return retval;
}
@@ -342,8 +361,9 @@ public class Sheet implements Model
public static Sheet createSheet(List records, int sheetnum)
{
- log.log(POILogger.DEBUG,
- "Sheet createSheet (exisiting file) assumed offset 0");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG,
+ "Sheet createSheet (exisiting file) assumed offset 0");
return createSheet(records, sheetnum, 0);
}
@@ -357,7 +377,8 @@ public class Sheet implements Model
public static Sheet createSheet()
{
- log.log(POILogger.DEBUG, "Sheet createsheet from scratch called");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "Sheet createsheet from scratch called");
Sheet retval = new Sheet();
ArrayList records = new ArrayList(30);
@@ -397,7 +418,10 @@ public class Sheet implements Model
retval.defaultcolwidth =
(DefaultColWidthRecord) retval.createDefaultColWidth();
records.add( retval.defaultcolwidth);
- retval.dims = ( DimensionsRecord ) retval.createDimensions();
+ ColumnInfoRecordsAggregate columns = new ColumnInfoRecordsAggregate();
+ records.add( columns );
+ retval.columns = columns;
+ retval.dims = ( DimensionsRecord ) retval.createDimensions();
records.add(retval.dims);
retval.dimsloc = records.size()-1;
records.add(retval.windowTwo = retval.createWindowTwo());
@@ -408,9 +432,11 @@ public class Sheet implements Model
retval.protect = (ProtectRecord) retval.createProtect();
records.add(retval.protect);
records.add(retval.createEOF());
-
+
+
retval.records = records;
- log.log(POILogger.DEBUG, "Sheet createsheet from scratch exit");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "Sheet createsheet from scratch exit");
return retval;
}
@@ -549,7 +575,8 @@ public class Sheet implements Model
public void convertLabelRecords(Workbook wb)
{
- log.log(POILogger.DEBUG, "convertLabelRecords called");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "convertLabelRecords called");
if (containsLabels)
{
for (int k = 0; k < records.size(); k++)
@@ -573,7 +600,8 @@ public class Sheet implements Model
}
}
}
- log.log(POILogger.DEBUG, "convertLabelRecords exit");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "convertLabelRecords exit");
}
/**
@@ -587,14 +615,17 @@ public class Sheet implements Model
{
checkCells();
checkRows();
- log.log(POILogger.DEBUG, "Sheet.getNumRecords");
- log.logFormatted(POILogger.DEBUG, "returning % + % + % - 2 = %", new int[]
+ if (log.check( POILogger.DEBUG ))
{
- records.size(), cells.getPhysicalNumberOfCells(),
- rows.getPhysicalNumberOfRows(),
- records.size() + cells.getPhysicalNumberOfCells()
- + rows.getPhysicalNumberOfRows() - 2
- });
+ log.log(POILogger.DEBUG, "Sheet.getNumRecords");
+ log.logFormatted(POILogger.DEBUG, "returning % + % + % - 2 = %", new int[]
+ {
+ records.size(), cells.getPhysicalNumberOfCells(),
+ rows.getPhysicalNumberOfRows(),
+ records.size() + cells.getPhysicalNumberOfCells()
+ + rows.getPhysicalNumberOfRows() - 2
+ });
+ }
return records.size() + cells.getPhysicalNumberOfCells()
+ rows.getPhysicalNumberOfRows() - 2;
}
@@ -611,17 +642,21 @@ public class Sheet implements Model
public void setDimensions(int firstrow, short firstcol, int lastrow,
short lastcol)
{
- log.log(POILogger.DEBUG, "Sheet.setDimensions");
- log.log(POILogger.DEBUG,
- (new StringBuffer("firstrow")).append(firstrow)
- .append("firstcol").append(firstcol).append("lastrow")
- .append(lastrow).append("lastcol").append(lastcol)
- .toString());
+ if (log.check( POILogger.DEBUG ))
+ {
+ log.log(POILogger.DEBUG, "Sheet.setDimensions");
+ log.log(POILogger.DEBUG,
+ (new StringBuffer("firstrow")).append(firstrow)
+ .append("firstcol").append(firstcol).append("lastrow")
+ .append(lastrow).append("lastcol").append(lastcol)
+ .toString());
+ }
dims.setFirstCol(firstcol);
dims.setFirstRow(firstrow);
dims.setLastCol(lastcol);
dims.setLastRow(lastrow);
- log.log(POILogger.DEBUG, "Sheet.setDimensions exiting");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "Sheet.setDimensions exiting");
}
/**
@@ -643,7 +678,8 @@ public class Sheet implements Model
public void setLoc(int loc)
{
valueRecIterator = null;
- log.log(POILogger.DEBUG, "sheet.setLoc(): " + loc);
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "sheet.setLoc(): " + loc);
this.loc = loc;
}
@@ -654,7 +690,8 @@ public class Sheet implements Model
public int getLoc()
{
- log.log(POILogger.DEBUG, "sheet.getLoc():" + loc);
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "sheet.getLoc():" + loc);
return loc;
}
@@ -692,7 +729,8 @@ public class Sheet implements Model
public byte [] serialize()
{
- log.log(POILogger.DEBUG, "Sheet.serialize");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "Sheet.serialize");
// addDBCellRecords();
byte[] retval = null;
@@ -721,7 +759,8 @@ public class Sheet implements Model
pos += (( Record ) records.get(k)).serialize(pos,
retval); // rec.length;
}
- log.log(POILogger.DEBUG, "Sheet.serialize returning " + retval);
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "Sheet.serialize returning " + retval);
return retval;
}
@@ -736,7 +775,8 @@ public class Sheet implements Model
public int serialize(int offset, byte [] data)
{
- log.log(POILogger.DEBUG, "Sheet.serialize using offsets");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "Sheet.serialize using offsets");
// addDBCellRecords();
// ArrayList bytes = new ArrayList(4096);
@@ -775,7 +815,8 @@ public class Sheet implements Model
pos += record.serialize(pos + offset, data ); // rec.length;
}
- log.log(POILogger.DEBUG, "Sheet.serialize returning ");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "Sheet.serialize returning ");
return pos;
}
@@ -789,16 +830,7 @@ public class Sheet implements Model
public RowRecord createRow(int row)
{
- log.log(POILogger.DEBUG, "create row number " + row);
- RowRecord rowrec = new RowRecord();
-
- //rowrec.setRowNumber(( short ) row);
- rowrec.setRowNumber(row);
- rowrec.setHeight(( short ) 0xff);
- rowrec.setOptimize(( short ) 0x0);
- rowrec.setOptionFlags(( short ) 0x0);
- rowrec.setXFIndex(( short ) 0x0);
- return rowrec;
+ return RowRecordsAggregate.createRow( row );
}
/**
@@ -1032,7 +1064,8 @@ public class Sheet implements Model
{
checkCells();
setLoc(dimsloc);
- log.log(POILogger.DEBUG, "replaceValueRecord ");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "replaceValueRecord ");
cells.insertCell(newval);
/*
@@ -1068,7 +1101,8 @@ public class Sheet implements Model
public void addRow(RowRecord row)
{
checkRows();
- log.log(POILogger.DEBUG, "addRow ");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "addRow ");
DimensionsRecord d = ( DimensionsRecord ) records.get(getDimsLoc());
if (row.getRowNumber() > d.getLastRow())
@@ -1122,7 +1156,8 @@ public class Sheet implements Model
* }
* }
*/
- log.log(POILogger.DEBUG, "exit addRow");
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "exit addRow");
}
/**
@@ -1182,7 +1217,8 @@ public class Sheet implements Model
public CellValueRecordInterface getNextValueRecord()
{
- log.log(POILogger.DEBUG, "getNextValue loc= " + loc);
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "getNextValue loc= " + loc);
if (valueRecIterator == null)
{
valueRecIterator = cells.getIterator();
@@ -1269,7 +1305,8 @@ public class Sheet implements Model
public RowRecord getNextRow()
{
- log.log(POILogger.DEBUG, "getNextRow loc= " + loc);
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "getNextRow loc= " + loc);
if (rowRecIterator == null)
{
rowRecIterator = rows.getIterator();
@@ -1315,7 +1352,8 @@ public class Sheet implements Model
//public RowRecord getRow(short rownum)
public RowRecord getRow(int rownum)
{
- log.log(POILogger.DEBUG, "getNextRow loc= " + loc);
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "getNextRow loc= " + loc);
return rows.getRow(rownum);
/*
@@ -1787,12 +1825,7 @@ public class Sheet implements Model
protected Record createColInfo()
{
- ColumnInfoRecord retval = new ColumnInfoRecord();
-
- retval.setColumnWidth(( short ) 0x8);
- retval.setOptions(( short ) 6);
- retval.setXFIndex(( short ) 0x0f);
- return retval;
+ return ColumnInfoRecordsAggregate.createColInfo();
}
/**
@@ -1867,13 +1900,12 @@ public class Sheet implements Model
{
short retval = 0;
ColumnInfoRecord ci = null;
- int k = 0;
- if (columnSizes != null)
+ if (columns != null)
{
- for (k = 0; k < columnSizes.size(); k++)
+ for ( Iterator iterator = columns.getIterator(); iterator.hasNext(); )
{
- ci = ( ColumnInfoRecord ) columnSizes.get(k);
+ ci = ( ColumnInfoRecord ) iterator.next();
if ((ci.getFirstColumn() <= column)
&& (column <= ci.getLastColumn()))
{
@@ -1898,104 +1930,46 @@ public class Sheet implements Model
* @param column - the column number
* @param width (in units of 1/20th of a character width)
*/
-
public void setColumnWidth(short column, short width)
{
- ColumnInfoRecord ci = null;
- int k = 0;
-
- if (columnSizes == null)
- {
- columnSizes = new ArrayList();
- }
- //int cioffset = getDimsLoc() - columnSizes.size();
+ setColumn( column, new Short(width), null, null, null);
+ }
- for (k = 0; k < columnSizes.size(); k++)
- {
- ci = ( ColumnInfoRecord ) columnSizes.get(k);
- if ((ci.getFirstColumn() <= column)
- && (column <= ci.getLastColumn()))
- {
- break;
- }
- ci = null;
- }
- if (ci != null)
- {
- if (ci.getColumnWidth() == width)
- {
+ public void setColumn(short column, Short width, Integer level, Boolean hidden, Boolean collapsed)
+ {
+ if (columns == null)
+ columns = new ColumnInfoRecordsAggregate();
- // do nothing...the cell's width is equal to what we're setting it to.
- }
- else if ((ci.getFirstColumn() == column)
- && (ci.getLastColumn() == column))
- { // if its only for this cell then
- ci.setColumnWidth(width); // who cares, just change the width
- }
- else if ((ci.getFirstColumn() == column)
- || (ci.getLastColumn() == column))
- {
+ columns.setColumn( column, width, level, hidden, collapsed );
+ }
- // okay so the width is different but the first or last column == the column we'return setting
- // we'll just divide the info and create a new one
- if (ci.getFirstColumn() == column)
- {
- ci.setFirstColumn(( short ) (column + 1));
- }
- else
- {
- ci.setLastColumn(( short ) (column - 1));
- }
- ColumnInfoRecord nci = ( ColumnInfoRecord ) createColInfo();
-
- nci.setFirstColumn(column);
- nci.setLastColumn(column);
- nci.setOptions(ci.getOptions());
- nci.setXFIndex(ci.getXFIndex());
- nci.setColumnWidth(width);
- columnSizes.add(k, nci);
- records.add((1 + getDimsLoc() - columnSizes.size()) + k, nci);
- dimsloc++;
- }
- else{
- //split to 3 records
- short lastcolumn = ci.getLastColumn();
- ci.setLastColumn(( short ) (column - 1));
-
- ColumnInfoRecord nci = ( ColumnInfoRecord ) createColInfo();
- nci.setFirstColumn(column);
- nci.setLastColumn(column);
- nci.setOptions(ci.getOptions());
- nci.setXFIndex(ci.getXFIndex());
- nci.setColumnWidth(width);
- columnSizes.add(k, nci);
- records.add((1 + getDimsLoc() - columnSizes.size()) + k, nci);
- dimsloc++;
-
- nci = ( ColumnInfoRecord ) createColInfo();
- nci.setFirstColumn((short)(column+1));
- nci.setLastColumn(lastcolumn);
- nci.setOptions(ci.getOptions());
- nci.setXFIndex(ci.getXFIndex());
- nci.setColumnWidth(ci.getColumnWidth());
- columnSizes.add(k, nci);
- records.add((1 + getDimsLoc() - columnSizes.size()) + k, nci);
- dimsloc++;
- }
- }
- else
- {
+ /**
+ * Creates an outline group for the specified columns.
+ * @param fromColumn group from this column (inclusive)
+ * @param toColumn group to this column (inclusive)
+ * @param indent if true the group will be indented by one level,
+ * if false indenting will be removed by one level.
+ */
+ public void groupColumnRange(short fromColumn, short toColumn, boolean indent)
+ {
- // okay so there ISN'T a column info record that cover's this column so lets create one!
- ColumnInfoRecord nci = ( ColumnInfoRecord ) createColInfo();
+ // Set the level for each column
+ columns.groupColumnRange( fromColumn, toColumn, indent);
- nci.setFirstColumn(column);
- nci.setLastColumn(column);
- nci.setColumnWidth(width);
- columnSizes.add(k, nci);
- records.add((1 + getDimsLoc() - columnSizes.size()) + k, nci);
- dimsloc++;
+ // Determine the maximum overall level
+ int maxLevel = 0;
+ for ( Iterator iterator = columns.getIterator(); iterator.hasNext(); )
+ {
+ ColumnInfoRecord columnInfoRecord = (ColumnInfoRecord) iterator.next();
+ maxLevel = Math.max(columnInfoRecord.getOutlineLevel(), maxLevel);
}
+
+ GutsRecord guts = (GutsRecord) findFirstRecordBySid( GutsRecord.sid );
+ guts.setColLevelMax( (short) ( maxLevel+1 ) );
+ if (maxLevel == 0)
+ guts.setTopColGutter( (short)0 );
+ else
+ guts.setTopColGutter( (short) ( 29 + (12 * (maxLevel-1)) ) );
}
/**
@@ -2125,7 +2099,6 @@ public class Sheet implements Model
protected Record createMergedCells()
{
MergeCellsRecord retval = new MergeCellsRecord();
-
retval.setNumAreas(( short ) 0);
return retval;
}
@@ -2149,7 +2122,8 @@ public class Sheet implements Model
public int getDimsLoc()
{
- log.log(POILogger.DEBUG, "getDimsLoc dimsloc= " + dimsloc);
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "getDimsLoc dimsloc= " + dimsloc);
return dimsloc;
}
@@ -2433,25 +2407,8 @@ public class Sheet implements Model
windowTwo.setFreezePanesNoSplit(true);
SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
-// SelectionRecord sel2 = (SelectionRecord) sel.clone();
-// SelectionRecord sel3 = (SelectionRecord) sel.clone();
-// SelectionRecord sel4 = (SelectionRecord) sel.clone();
-// sel.setPane(PANE_LOWER_RIGHT); // 0
-// sel3.setPane(PANE_UPPER_RIGHT); // 1
- sel.setPane((byte)pane.getActivePane()); // 2
-// sel2.setPane(PANE_UPPER_LEFT); // 3
-// sel4.setActiveCellCol((short)Math.max(sel3.getActiveCellCol(), colSplit));
-// sel3.setActiveCellRow((short)Math.max(sel4.getActiveCellRow(), rowSplit));
-
- int selLoc = findFirstRecordLocBySid(SelectionRecord.sid);
-// sel.setActiveCellCol((short)15);
-// sel.setActiveCellRow((short)15);
-// sel2.setActiveCellCol((short)0);
-// sel2.setActiveCellRow((short)0);
+ sel.setPane((byte)pane.getActivePane());
-// records.add(selLoc+1,sel2);
-// records.add(selLoc+2,sel3);
-// records.add(selLoc+3,sel4);
}
/**
@@ -2482,25 +2439,8 @@ public class Sheet implements Model
windowTwo.setFreezePanesNoSplit(false);
SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
-// SelectionRecord sel2 = (SelectionRecord) sel.clone();
-// SelectionRecord sel3 = (SelectionRecord) sel.clone();
-// SelectionRecord sel4 = (SelectionRecord) sel.clone();
- sel.setPane(PANE_LOWER_RIGHT); // 0
-// sel3.setPane(PANE_UPPER_RIGHT); // 1
-// sel4.setPane(PANE_LOWER_LEFT); // 2
-// sel2.setPane(PANE_UPPER_LEFT); // 3
-// sel4.setActiveCellCol((short)Math.max(sel3.getActiveCellCol(), colSplit));
-// sel3.setActiveCellRow((short)Math.max(sel4.getActiveCellRow(), rowSplit));
-
- int selLoc = findFirstRecordLocBySid(SelectionRecord.sid);
-// sel.setActiveCellCol((short)15);
-// sel.setActiveCellRow((short)15);
-// sel2.setActiveCellCol((short)0);
-// sel2.setActiveCellRow((short)0);
-
-// records.add(selLoc+1,sel2);
-// records.add(selLoc+2,sel3);
-// records.add(selLoc+3,sel4);
+ sel.setPane(PANE_LOWER_RIGHT);
+
}
public SelectionRecord getSelection()
@@ -2512,27 +2452,28 @@ public class Sheet implements Model
{
this.selection = selection;
}
- /**
- * creates a Protect record with protect set to false.
- * @see org.apache.poi.hssf.record.ProtectRecord
- * @see org.apache.poi.hssf.record.Record
- * @return a ProtectRecord
- */
- protected Record createProtect()
- {
- log.log(POILogger.DEBUG, "create protect record with protection disabled");
- ProtectRecord retval = new ProtectRecord();
+ /**
+ * creates a Protect record with protect set to false.
+ * @see org.apache.poi.hssf.record.ProtectRecord
+ * @see org.apache.poi.hssf.record.Record
+ * @return a ProtectRecord
+ */
+ protected Record createProtect()
+ {
+ if (log.check( POILogger.DEBUG ))
+ log.log(POILogger.DEBUG, "create protect record with protection disabled");
+ ProtectRecord retval = new ProtectRecord();
- retval.setProtect(false);
- // by default even when we support encryption we won't
- return retval;
- }
+ retval.setProtect(false);
+ // by default even when we support encryption we won't
+ return retval;
+ }
- public ProtectRecord getProtect()
- {
- return protect;
- }
+ public ProtectRecord getProtect()
+ {
+ return protect;
+ }
/**
* Sets whether the gridlines are shown in a viewer.
@@ -2705,7 +2646,7 @@ public class Sheet implements Model
/**
* Sets a page break at the indicated column
- * @param row
+ *
*/
public void setColumnBreak(short column, short fromRow, short toRow) {
colBreaks.addBreak(column, fromRow, toRow);
@@ -2713,7 +2654,7 @@ public class Sheet implements Model
/**
* Removes a page break at the indicated column
- * @param row
+ *
*/
public void removeColumnBreak(short column) {
colBreaks.removeBreak(column);
@@ -2721,7 +2662,7 @@ public class Sheet implements Model
/**
* Queries if the specified column has a page break
- * @param row
+ *
* @return true if the specified column has a page break
*/
public boolean isColumnBroken(short column) {
@@ -2779,4 +2720,360 @@ public class Sheet implements Model
public int getNumColumnBreaks(){
return (int)colBreaks.getNumBreaks();
}
+
+ public void setColumnGroupCollapsed( short columnNumber, boolean collapsed )
+ {
+ if (collapsed)
+ {
+ columns.collapseColumn( columnNumber );
+ }
+ else
+ {
+ columns.expandColumn( columnNumber );
+ }
+ }
+
+// private void collapseColumn( short columnNumber )
+// {
+// int idx = findColumnIdx( columnNumber, 0 );
+// if (idx == -1)
+// return;
+//
+// // Find the start of the group.
+// ColumnInfoRecord columnInfo = (ColumnInfoRecord) columnSizes.get( findStartOfColumnOutlineGroup( idx ) );
+//
+// // Hide all the columns until the end of the group
+// columnInfo = writeHidden( columnInfo, idx, true );
+//
+// // Write collapse field
+// setColumn( (short) ( columnInfo.getLastColumn() + 1 ), null, null, null, Boolean.TRUE);
+// }
+
+// private void expandColumn( short columnNumber )
+// {
+// int idx = findColumnIdx( columnNumber, 0 );
+// if (idx == -1)
+// return;
+//
+// // If it is already exapanded do nothing.
+// if (!isColumnGroupCollapsed(idx))
+// return;
+//
+// // Find the start of the group.
+// int startIdx = findStartOfColumnOutlineGroup( idx );
+// ColumnInfoRecord columnInfo = getColInfo( startIdx );
+//
+// // Find the end of the group.
+// int endIdx = findEndOfColumnOutlineGroup( idx );
+// ColumnInfoRecord endColumnInfo = getColInfo( endIdx );
+//
+// // expand:
+// // colapsed bit must be unset
+// // hidden bit gets unset _if_ surrounding groups are expanded you can determine
+// // this by looking at the hidden bit of the enclosing group. You will have
+// // to look at the start and the end of the current group to determine which
+// // is the enclosing group
+// // hidden bit only is altered for this outline level. ie. don't uncollapse contained groups
+// if (!isColumnGroupHiddenByParent( idx ))
+// {
+// for (int i = startIdx; i <= endIdx; i++)
+// {
+// if (columnInfo.getOutlineLevel() == getColInfo(i).getOutlineLevel())
+// getColInfo(i).setHidden( false );
+// }
+// }
+//
+// // Write collapse field
+// setColumn( (short) ( columnInfo.getLastColumn() + 1 ), null, null, null, Boolean.FALSE);
+// }
+
+// private boolean isColumnGroupCollapsed( int idx )
+// {
+// int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup( idx );
+// if (endOfOutlineGroupIdx >= columnSizes.size())
+// return false;
+// if (getColInfo(endOfOutlineGroupIdx).getLastColumn() + 1 != getColInfo(endOfOutlineGroupIdx + 1).getFirstColumn())
+// return false;
+// else
+// return getColInfo(endOfOutlineGroupIdx+1).getCollapsed();
+// }
+
+// private boolean isColumnGroupHiddenByParent( int idx )
+// {
+// // Look out outline details of end
+// int endLevel;
+// boolean endHidden;
+// int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup( idx );
+// if (endOfOutlineGroupIdx >= columnSizes.size())
+// {
+// endLevel = 0;
+// endHidden = false;
+// }
+// else if (getColInfo(endOfOutlineGroupIdx).getLastColumn() + 1 != getColInfo(endOfOutlineGroupIdx + 1).getFirstColumn())
+// {
+// endLevel = 0;
+// endHidden = false;
+// }
+// else
+// {
+// endLevel = getColInfo( endOfOutlineGroupIdx + 1).getOutlineLevel();
+// endHidden = getColInfo( endOfOutlineGroupIdx + 1).getHidden();
+// }
+//
+// // Look out outline details of start
+// int startLevel;
+// boolean startHidden;
+// int startOfOutlineGroupIdx = findStartOfColumnOutlineGroup( idx );
+// if (startOfOutlineGroupIdx <= 0)
+// {
+// startLevel = 0;
+// startHidden = false;
+// }
+// else if (getColInfo(startOfOutlineGroupIdx).getFirstColumn() - 1 != getColInfo(startOfOutlineGroupIdx - 1).getLastColumn())
+// {
+// startLevel = 0;
+// startHidden = false;
+// }
+// else
+// {
+// startLevel = getColInfo( startOfOutlineGroupIdx - 1).getOutlineLevel();
+// startHidden = getColInfo( startOfOutlineGroupIdx - 1 ).getHidden();
+// }
+//
+// if (endLevel > startLevel)
+// {
+// return endHidden;
+// }
+// else
+// {
+// return startHidden;
+// }
+// }
+
+// private ColumnInfoRecord getColInfo(int idx)
+// {
+// return columns.getColInfo( idx );
+// }
+
+// private int findStartOfColumnOutlineGroup(int idx)
+// {
+// // Find the start of the group.
+// ColumnInfoRecord columnInfo = (ColumnInfoRecord) columnSizes.get( idx );
+// int level = columnInfo.getOutlineLevel();
+// while (idx != 0)
+// {
+// ColumnInfoRecord prevColumnInfo = (ColumnInfoRecord) columnSizes.get( idx - 1 );
+// if (columnInfo.getFirstColumn() - 1 == prevColumnInfo.getLastColumn())
+// {
+// if (prevColumnInfo.getOutlineLevel() < level)
+// {
+// break;
+// }
+// idx--;
+// columnInfo = prevColumnInfo;
+// }
+// else
+// {
+// break;
+// }
+// }
+//
+// return idx;
+// }
+
+// private int findEndOfColumnOutlineGroup(int idx)
+// {
+// // Find the end of the group.
+// ColumnInfoRecord columnInfo = (ColumnInfoRecord) columnSizes.get( idx );
+// int level = columnInfo.getOutlineLevel();
+// while (idx < columnSizes.size() - 1)
+// {
+// ColumnInfoRecord nextColumnInfo = (ColumnInfoRecord) columnSizes.get( idx + 1 );
+// if (columnInfo.getLastColumn() + 1 == nextColumnInfo.getFirstColumn())
+// {
+// if (nextColumnInfo.getOutlineLevel() < level)
+// {
+// break;
+// }
+// idx++;
+// columnInfo = nextColumnInfo;
+// }
+// else
+// {
+// break;
+// }
+// }
+//
+// return idx;
+// }
+
+ public void groupRowRange(int fromRow, int toRow, boolean indent)
+ {
+ checkRows();
+ for (int rowNum = fromRow; rowNum <= toRow; rowNum++)
+ {
+ RowRecord row = getRow( rowNum );
+ if (row == null)
+ {
+ row = createRow( rowNum );
+ addRow( row );
+ }
+ int level = row.getOutlineLevel();
+ if (indent) level++; else level--;
+ level = Math.max(0, level);
+ level = Math.min(7, level);
+ row.setOutlineLevel((short) ( level ));
+ }
+
+ recalcRowGutter();
+ }
+
+ private void recalcRowGutter()
+ {
+ int maxLevel = 0;
+ Iterator iterator = rows.getIterator();
+ while ( iterator.hasNext() )
+ {
+ RowRecord rowRecord = (RowRecord) iterator.next();
+ maxLevel = Math.max(rowRecord.getOutlineLevel(), maxLevel);
+ }
+
+ GutsRecord guts = (GutsRecord) findFirstRecordBySid( GutsRecord.sid );
+ guts.setRowLevelMax( (short) ( maxLevel + 1 ) );
+ guts.setLeftRowGutter( (short) ( 29 + (12 * (maxLevel)) ) );
+ }
+
+ public void setRowGroupCollapsed( int row, boolean collapse )
+ {
+ if (collapse)
+ {
+ rows.collapseRow( row );
+ }
+ else
+ {
+ rows.expandRow( row );
+ }
+ }
+
+
+// private void collapseRow( int rowNumber )
+// {
+//
+// // Find the start of the group.
+// int startRow = rows.findStartOfRowOutlineGroup( rowNumber );
+// RowRecord rowRecord = (RowRecord) rows.getRow( startRow );
+//
+// // Hide all the columns until the end of the group
+// int lastRow = rows.writeHidden( rowRecord, startRow, true );
+//
+// // Write collapse field
+// if (getRow(lastRow + 1) != null)
+// {
+// getRow(lastRow + 1).setColapsed( true );
+// }
+// else
+// {
+// RowRecord row = createRow( lastRow + 1);
+// row.setColapsed( true );
+// rows.insertRow( row );
+// }
+// }
+
+// private int findStartOfRowOutlineGroup(int row)
+// {
+// // Find the start of the group.
+// RowRecord rowRecord = rows.getRow( row );
+// int level = rowRecord.getOutlineLevel();
+// int currentRow = row;
+// while (rows.getRow( currentRow ) != null)
+// {
+// rowRecord = rows.getRow( currentRow );
+// if (rowRecord.getOutlineLevel() < level)
+// return currentRow + 1;
+// currentRow--;
+// }
+//
+// return currentRow + 1;
+// }
+
+// private int writeHidden( RowRecord rowRecord, int row, boolean hidden )
+// {
+// int level = rowRecord.getOutlineLevel();
+// while (rowRecord != null && rows.getRow(row).getOutlineLevel() >= level)
+// {
+// rowRecord.setZeroHeight( hidden );
+// row++;
+// rowRecord = rows.getRow( row );
+// }
+// return row - 1;
+// }
+
+// private int findEndOfRowOutlineGroup( int row )
+// {
+// int level = getRow( row ).getOutlineLevel();
+// int currentRow;
+// for (currentRow = row; currentRow < rows.getLastRowNum(); currentRow++)
+// {
+// if (getRow(currentRow) == null || getRow(currentRow).getOutlineLevel() < level)
+// {
+// break;
+// }
+// }
+//
+// return currentRow-1;
+// }
+
+// private boolean isRowGroupCollapsed( int row )
+// {
+// int collapseRow = rows.findEndOfRowOutlineGroup( row ) + 1;
+//
+// if (getRow(collapseRow) == null)
+// return false;
+// else
+// return getRow( collapseRow ).getColapsed();
+// }
+
+
+// private boolean isRowGroupHiddenByParent( int row )
+// {
+// // Look out outline details of end
+// int endLevel;
+// boolean endHidden;
+// int endOfOutlineGroupIdx = rows.findEndOfRowOutlineGroup( row );
+// if (getRow( endOfOutlineGroupIdx + 1 ) == null)
+// {
+// endLevel = 0;
+// endHidden = false;
+// }
+// else
+// {
+// endLevel = getRow( endOfOutlineGroupIdx + 1).getOutlineLevel();
+// endHidden = getRow( endOfOutlineGroupIdx + 1).getZeroHeight();
+// }
+//
+// // Look out outline details of start
+// int startLevel;
+// boolean startHidden;
+// int startOfOutlineGroupIdx = rows.findStartOfRowOutlineGroup( row );
+// if (startOfOutlineGroupIdx - 1 < 0 || getRow(startOfOutlineGroupIdx - 1) == null)
+// {
+// startLevel = 0;
+// startHidden = false;
+// }
+// else
+// {
+// startLevel = getRow( startOfOutlineGroupIdx - 1).getOutlineLevel();
+// startHidden = getRow( startOfOutlineGroupIdx - 1 ).getZeroHeight();
+// }
+//
+// if (endLevel > startLevel)
+// {
+// return endHidden;
+// }
+// else
+// {
+// return startHidden;
+// }
+// }
+
}
diff --git a/src/java/org/apache/poi/hssf/model/Workbook.java b/src/java/org/apache/poi/hssf/model/Workbook.java
index 8ce327270a..9b0a18f362 100644
--- a/src/java/org/apache/poi/hssf/model/Workbook.java
+++ b/src/java/org/apache/poi/hssf/model/Workbook.java
@@ -122,8 +122,9 @@ public class Workbook implements Model
* @return Workbook object
*/
public static Workbook createWorkbook(List recs) {
- log.log(DEBUG, "Workbook (readfile) created with reclen=",
- new Integer(recs.size()));
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "Workbook (readfile) created with reclen=",
+ new Integer(recs.size()));
Workbook retval = new Workbook();
ArrayList records = new ArrayList(recs.size() / 3);
@@ -132,85 +133,100 @@ public class Workbook implements Model
if (rec.getSid() == EOFRecord.sid) {
records.add(rec);
- log.log(DEBUG, "found workbook eof record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found workbook eof record at " + k);
break;
}
switch (rec.getSid()) {
case BoundSheetRecord.sid :
- log.log(DEBUG, "found boundsheet record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found boundsheet record at " + k);
retval.boundsheets.add(rec);
retval.records.setBspos( k );
break;
case SSTRecord.sid :
- log.log(DEBUG, "found sst record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found sst record at " + k);
retval.sst = ( SSTRecord ) rec;
break;
case FontRecord.sid :
- log.log(DEBUG, "found font record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found font record at " + k);
retval.records.setFontpos( k );
retval.numfonts++;
break;
case ExtendedFormatRecord.sid :
- log.log(DEBUG, "found XF record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found XF record at " + k);
retval.records.setXfpos( k );
retval.numxfs++;
break;
case TabIdRecord.sid :
- log.log(DEBUG, "found tabid record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found tabid record at " + k);
retval.records.setTabpos( k );
break;
case ProtectRecord.sid :
- log.log(DEBUG, "found protect record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found protect record at " + k);
retval.records.setProtpos( k );
break;
case BackupRecord.sid :
- log.log(DEBUG, "found backup record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found backup record at " + k);
retval.records.setBackuppos( k );
break;
case ExternSheetRecord.sid :
- log.log(DEBUG, "found extern sheet record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found extern sheet record at " + k);
retval.externSheet = ( ExternSheetRecord ) rec;
break;
case NameRecord.sid :
- log.log(DEBUG, "found name record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found name record at " + k);
retval.names.add(rec);
-// retval.records.namepos = k;
+ // retval.records.namepos = k;
break;
case SupBookRecord.sid :
- log.log(DEBUG, "found SupBook record at " + k);
-// retval.records.supbookpos = k;
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found SupBook record at " + k);
+ // retval.records.supbookpos = k;
+ break;
+ case FormatRecord.sid :
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found format record at " + k);
+ retval.formats.add(rec);
+ retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode();
break;
- case FormatRecord.sid :
- log.log(DEBUG, "found format record at " + k);
- retval.formats.add(rec);
- retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode();
- break;
case DateWindow1904Record.sid :
- log.log(DEBUG, "found datewindow1904 record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found datewindow1904 record at " + k);
retval.uses1904datewindowing = ((DateWindow1904Record)rec).getWindowing() == 1;
break;
case PaletteRecord.sid:
- log.log(DEBUG, "found palette record at " + k);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "found palette record at " + k);
retval.records.setPalettepos( k );
default :
}
records.add(rec);
}
//What if we dont have any ranges and supbooks
-// if (retval.records.supbookpos == 0) {
-// retval.records.supbookpos = retval.records.bspos + 1;
-// retval.records.namepos = retval.records.supbookpos + 1;
-// }
+ // if (retval.records.supbookpos == 0) {
+ // retval.records.supbookpos = retval.records.bspos + 1;
+ // retval.records.namepos = retval.records.supbookpos + 1;
+ // }
retval.records.setRecords(records);
- log.log(DEBUG, "exit create workbook from existing file function");
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "exit create workbook from existing file function");
return retval;
}
@@ -220,7 +236,8 @@ public class Workbook implements Model
*/
public static Workbook createWorkbook()
{
- log.log( DEBUG, "creating new workbook from scratch" );
+ if (log.check( POILogger.DEBUG ))
+ log.log( DEBUG, "creating new workbook from scratch" );
Workbook retval = new Workbook();
ArrayList records = new ArrayList( 30 );
ArrayList formats = new ArrayList( 8 );
@@ -296,7 +313,8 @@ public class Workbook implements Model
records.add( retval.createEOF() );
retval.records.setRecords(records);
- log.log( DEBUG, "exit create new workbook from scratch" );
+ if (log.check( POILogger.DEBUG ))
+ log.log( DEBUG, "exit create new workbook from scratch" );
return retval;
}
@@ -403,8 +421,9 @@ public class Workbook implements Model
*/
public void setSheetBof(int sheetnum, int pos) {
- log.log(DEBUG, "setting bof for sheetnum =", new Integer(sheetnum),
- " at pos=", new Integer(pos));
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "setting bof for sheetnum =", new Integer(sheetnum),
+ " at pos=", new Integer(pos));
checkSheets(sheetnum);
(( BoundSheetRecord ) boundsheets.get(sheetnum))
.setPositionOfBof(pos);
@@ -535,7 +554,8 @@ public class Workbook implements Model
*/
public int getNumSheets() {
- log.log(DEBUG, "getNumSheets=", new Integer(boundsheets.size()));
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "getNumSheets=", new Integer(boundsheets.size()));
return boundsheets.size();
}
@@ -546,7 +566,8 @@ public class Workbook implements Model
*/
public int getNumExFormats() {
- log.log(DEBUG, "getXF=", new Integer(numxfs));
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "getXF=", new Integer(numxfs));
return numxfs;
}
@@ -593,7 +614,8 @@ public class Workbook implements Model
*/
public int addSSTString(String string, boolean use16bits) {
- log.log(DEBUG, "insert to sst string='", string, "' and use16bits= ",
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "insert to sst string='", string, "' and use16bits= ",
new Boolean(use16bits));
if (sst == null) {
insertSST();
@@ -626,8 +648,9 @@ public class Workbook implements Model
}
String retval = sst.getString(str);
- log.log(DEBUG, "Returning SST for index=", new Integer(str),
- " String= ", retval);
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "Returning SST for index=", new Integer(str),
+ " String= ", retval);
return retval;
}
@@ -639,7 +662,8 @@ public class Workbook implements Model
*/
public void insertSST() {
- log.log(DEBUG, "creating new SST via insertSST!");
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "creating new SST via insertSST!");
sst = ( SSTRecord ) createSST();
records.add(records.size() - 1, createExtendedSST());
records.add(records.size() - 2, sst);
@@ -682,7 +706,8 @@ public class Workbook implements Model
public int serialize( int offset, byte[] data )
{
- log.log( DEBUG, "Serializing Workbook with offsets" );
+ if (log.check( POILogger.DEBUG ))
+ log.log( DEBUG, "Serializing Workbook with offsets" );
int pos = 0;
@@ -707,7 +732,8 @@ public class Workbook implements Model
pos += record.serialize( pos + offset, data ); // rec.length;
}
}
- log.log( DEBUG, "Exiting serialize workbook" );
+ if (log.check( POILogger.DEBUG ))
+ log.log( DEBUG, "Exiting serialize workbook" );
return pos;
}
diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ColumnInfoRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/ColumnInfoRecordsAggregate.java
new file mode 100644
index 0000000000..6eb9b111da
--- /dev/null
+++ b/src/java/org/apache/poi/hssf/record/aggregates/ColumnInfoRecordsAggregate.java
@@ -0,0 +1,509 @@
+package org.apache.poi.hssf.record.aggregates;
+
+import org.apache.poi.hssf.record.ColumnInfoRecord;
+import org.apache.poi.hssf.record.Record;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author Glen Stampoultzis
+ * @version $Id$
+ */
+public class ColumnInfoRecordsAggregate
+ extends Record
+{
+ int size = 0;
+ List records = null;
+
+ public ColumnInfoRecordsAggregate()
+ {
+ records = new ArrayList();
+ }
+
+ /** You never fill an aggregate */
+ protected void fillFields(byte [] data, short size, int offset)
+ {
+ }
+
+ /** Not required by an aggregate */
+ protected void validateSid(short id)
+ {
+ }
+
+ /** It's an aggregate... just made something up */
+ public short getSid()
+ {
+ return -1012;
+ }
+
+ public int getRecordSize()
+ {
+ return size;
+ }
+
+ public Iterator getIterator()
+ {
+ return records.iterator();
+ }
+
+ /**
+ * Performs a deep clone of the record
+ */
+ public Object clone()
+ {
+ ColumnInfoRecordsAggregate rec = new ColumnInfoRecordsAggregate();
+ for ( Iterator colIter = getIterator(); colIter.hasNext(); )
+ {
+ //return the cloned Row Record & insert
+ ColumnInfoRecord col = (ColumnInfoRecord) ( (ColumnInfoRecord) colIter.next() ).clone();
+ rec.insertColumn( col );
+ }
+ return rec;
+ }
+
+ /**
+ * Inserts a column into the aggregate (at the end of the list).
+ */
+ public void insertColumn( ColumnInfoRecord col )
+ {
+ size += col.getRecordSize();
+ records.add( col );
+ }
+
+ /**
+ * Inserts a column into the aggregate (at the position specified
+ * by idx
.
+ */
+ public void insertColumn( int idx, ColumnInfoRecord col )
+ {
+ size += col.getRecordSize();
+ records.add( idx, col );
+ }
+
+ public int getNumColumns( )
+ {
+ return records.size();
+ }
+
+ /**
+ * called by the class that is responsible for writing this sucker.
+ * Subclasses should implement this so that their data is passed back in a
+ * byte array.
+ *
+ * @param offset offset to begin writing at
+ * @param data byte array containing instance data
+ * @return number of bytes written
+ */
+ public int serialize(int offset, byte [] data)
+ {
+ Iterator itr = records.iterator();
+ int pos = offset;
+
+ while (itr.hasNext())
+ {
+ pos += (( Record ) itr.next()).serialize(pos, data);
+ }
+ return pos - offset;
+ }
+
+ public int findStartOfColumnOutlineGroup(int idx)
+ {
+ // Find the start of the group.
+ ColumnInfoRecord columnInfo = (ColumnInfoRecord) records.get( idx );
+ int level = columnInfo.getOutlineLevel();
+ while (idx != 0)
+ {
+ ColumnInfoRecord prevColumnInfo = (ColumnInfoRecord) records.get( idx - 1 );
+ if (columnInfo.getFirstColumn() - 1 == prevColumnInfo.getLastColumn())
+ {
+ if (prevColumnInfo.getOutlineLevel() < level)
+ {
+ break;
+ }
+ idx--;
+ columnInfo = prevColumnInfo;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return idx;
+ }
+
+ public int findEndOfColumnOutlineGroup(int idx)
+ {
+ // Find the end of the group.
+ ColumnInfoRecord columnInfo = (ColumnInfoRecord) records.get( idx );
+ int level = columnInfo.getOutlineLevel();
+ while (idx < records.size() - 1)
+ {
+ ColumnInfoRecord nextColumnInfo = (ColumnInfoRecord) records.get( idx + 1 );
+ if (columnInfo.getLastColumn() + 1 == nextColumnInfo.getFirstColumn())
+ {
+ if (nextColumnInfo.getOutlineLevel() < level)
+ {
+ break;
+ }
+ idx++;
+ columnInfo = nextColumnInfo;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return idx;
+ }
+
+ public ColumnInfoRecord getColInfo(int idx)
+ {
+ return (ColumnInfoRecord) records.get( idx );
+ }
+
+ public ColumnInfoRecord writeHidden( ColumnInfoRecord columnInfo, int idx, boolean hidden )
+ {
+ int level = columnInfo.getOutlineLevel();
+ while (idx < records.size())
+ {
+ columnInfo.setHidden( hidden );
+ if (idx + 1 < records.size())
+ {
+ ColumnInfoRecord nextColumnInfo = (ColumnInfoRecord) records.get( idx + 1 );
+ if (columnInfo.getLastColumn() + 1 == nextColumnInfo.getFirstColumn())
+ {
+ if (nextColumnInfo.getOutlineLevel() < level)
+ break;
+ columnInfo = nextColumnInfo;
+ }
+ else
+ {
+ break;
+ }
+ }
+ idx++;
+ }
+ return columnInfo;
+ }
+
+ public boolean isColumnGroupCollapsed( int idx )
+ {
+ int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup( idx );
+ if (endOfOutlineGroupIdx >= records.size())
+ return false;
+ if (getColInfo(endOfOutlineGroupIdx).getLastColumn() + 1 != getColInfo(endOfOutlineGroupIdx + 1).getFirstColumn())
+ return false;
+ else
+ return getColInfo(endOfOutlineGroupIdx+1).getCollapsed();
+ }
+
+
+ public boolean isColumnGroupHiddenByParent( int idx )
+ {
+ // Look out outline details of end
+ int endLevel;
+ boolean endHidden;
+ int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup( idx );
+ if (endOfOutlineGroupIdx >= records.size())
+ {
+ endLevel = 0;
+ endHidden = false;
+ }
+ else if (getColInfo(endOfOutlineGroupIdx).getLastColumn() + 1 != getColInfo(endOfOutlineGroupIdx + 1).getFirstColumn())
+ {
+ endLevel = 0;
+ endHidden = false;
+ }
+ else
+ {
+ endLevel = getColInfo( endOfOutlineGroupIdx + 1).getOutlineLevel();
+ endHidden = getColInfo( endOfOutlineGroupIdx + 1).getHidden();
+ }
+
+ // Look out outline details of start
+ int startLevel;
+ boolean startHidden;
+ int startOfOutlineGroupIdx = findStartOfColumnOutlineGroup( idx );
+ if (startOfOutlineGroupIdx <= 0)
+ {
+ startLevel = 0;
+ startHidden = false;
+ }
+ else if (getColInfo(startOfOutlineGroupIdx).getFirstColumn() - 1 != getColInfo(startOfOutlineGroupIdx - 1).getLastColumn())
+ {
+ startLevel = 0;
+ startHidden = false;
+ }
+ else
+ {
+ startLevel = getColInfo( startOfOutlineGroupIdx - 1).getOutlineLevel();
+ startHidden = getColInfo( startOfOutlineGroupIdx - 1 ).getHidden();
+ }
+
+ if (endLevel > startLevel)
+ {
+ return endHidden;
+ }
+ else
+ {
+ return startHidden;
+ }
+ }
+
+ public void collapseColumn( short columnNumber )
+ {
+ int idx = findColumnIdx( columnNumber, 0 );
+ if (idx == -1)
+ return;
+
+ // Find the start of the group.
+ ColumnInfoRecord columnInfo = (ColumnInfoRecord) records.get( findStartOfColumnOutlineGroup( idx ) );
+
+ // Hide all the columns until the end of the group
+ columnInfo = writeHidden( columnInfo, idx, true );
+
+ // Write collapse field
+ setColumn( (short) ( columnInfo.getLastColumn() + 1 ), null, null, null, Boolean.TRUE);
+ }
+
+ public void expandColumn( short columnNumber )
+ {
+ int idx = findColumnIdx( columnNumber, 0 );
+ if (idx == -1)
+ return;
+
+ // If it is already exapanded do nothing.
+ if (!isColumnGroupCollapsed(idx))
+ return;
+
+ // Find the start of the group.
+ int startIdx = findStartOfColumnOutlineGroup( idx );
+ ColumnInfoRecord columnInfo = getColInfo( startIdx );
+
+ // Find the end of the group.
+ int endIdx = findEndOfColumnOutlineGroup( idx );
+ ColumnInfoRecord endColumnInfo = getColInfo( endIdx );
+
+ // expand:
+ // colapsed bit must be unset
+ // hidden bit gets unset _if_ surrounding groups are expanded you can determine
+ // this by looking at the hidden bit of the enclosing group. You will have
+ // to look at the start and the end of the current group to determine which
+ // is the enclosing group
+ // hidden bit only is altered for this outline level. ie. don't uncollapse contained groups
+ if (!isColumnGroupHiddenByParent( idx ))
+ {
+ for (int i = startIdx; i <= endIdx; i++)
+ {
+ if (columnInfo.getOutlineLevel() == getColInfo(i).getOutlineLevel())
+ getColInfo(i).setHidden( false );
+ }
+ }
+
+ // Write collapse field
+ setColumn( (short) ( columnInfo.getLastColumn() + 1 ), null, null, null, Boolean.FALSE);
+ }
+
+ /**
+ * creates the ColumnInfo Record and sets it to a default column/width
+ * @see org.apache.poi.hssf.record.ColumnInfoRecord
+ * @return record containing a ColumnInfoRecord
+ */
+ public static Record createColInfo()
+ {
+ ColumnInfoRecord retval = new ColumnInfoRecord();
+
+ retval.setColumnWidth(( short ) 2275);
+ // was: retval.setOptions(( short ) 6);
+ retval.setOptions(( short ) 2);
+ retval.setXFIndex(( short ) 0x0f);
+ return retval;
+ }
+
+
+ public void setColumn(short column, Short width, Integer level, Boolean hidden, Boolean collapsed)
+ {
+ ColumnInfoRecord ci = null;
+ int k = 0;
+
+ for (k = 0; k < records.size(); k++)
+ {
+ ci = ( ColumnInfoRecord ) records.get(k);
+ if ((ci.getFirstColumn() <= column)
+ && (column <= ci.getLastColumn()))
+ {
+ break;
+ }
+ ci = null;
+ }
+
+ if (ci != null)
+ {
+ boolean widthChanged = width != null && ci.getColumnWidth() != width.shortValue();
+ boolean levelChanged = level != null && ci.getOutlineLevel() != level.intValue();
+ boolean hiddenChanged = hidden != null && ci.getHidden() != hidden.booleanValue();
+ boolean collapsedChanged = collapsed != null && ci.getCollapsed() != collapsed.booleanValue();
+ boolean columnChanged = widthChanged || levelChanged || hiddenChanged || collapsedChanged;
+ if (!columnChanged)
+ {
+ // do nothing...nothing changed.
+ }
+ else if ((ci.getFirstColumn() == column)
+ && (ci.getLastColumn() == column))
+ { // if its only for this cell then
+ setColumnInfoFields( ci, width, level, hidden, collapsed );
+ }
+ else if ((ci.getFirstColumn() == column)
+ || (ci.getLastColumn() == column))
+ {
+ // okay so the width is different but the first or last column == the column we'return setting
+ // we'll just divide the info and create a new one
+ if (ci.getFirstColumn() == column)
+ {
+ ci.setFirstColumn(( short ) (column + 1));
+ }
+ else
+ {
+ ci.setLastColumn(( short ) (column - 1));
+ }
+ ColumnInfoRecord nci = ( ColumnInfoRecord ) createColInfo();
+
+ nci.setFirstColumn(column);
+ nci.setLastColumn(column);
+ nci.setOptions(ci.getOptions());
+ nci.setXFIndex(ci.getXFIndex());
+ setColumnInfoFields( nci, width, level, hidden, collapsed );
+
+ insertColumn(k, nci);
+ }
+ else
+ {
+ //split to 3 records
+ short lastcolumn = ci.getLastColumn();
+ ci.setLastColumn(( short ) (column - 1));
+
+ ColumnInfoRecord nci = ( ColumnInfoRecord ) createColInfo();
+ nci.setFirstColumn(column);
+ nci.setLastColumn(column);
+ nci.setOptions(ci.getOptions());
+ nci.setXFIndex(ci.getXFIndex());
+ setColumnInfoFields( nci, width, level, hidden, collapsed );
+ insertColumn(++k, nci);
+
+ nci = ( ColumnInfoRecord ) createColInfo();
+ nci.setFirstColumn((short)(column+1));
+ nci.setLastColumn(lastcolumn);
+ nci.setOptions(ci.getOptions());
+ nci.setXFIndex(ci.getXFIndex());
+ nci.setColumnWidth(ci.getColumnWidth());
+ insertColumn(++k, nci);
+ }
+ }
+ else
+ {
+
+ // okay so there ISN'T a column info record that cover's this column so lets create one!
+ ColumnInfoRecord nci = ( ColumnInfoRecord ) createColInfo();
+
+ nci.setFirstColumn(column);
+ nci.setLastColumn(column);
+ setColumnInfoFields( nci, width, level, hidden, collapsed );
+ insertColumn(k, nci);
+ }
+ }
+
+ /**
+ * Sets all non null fields into the ci
parameter.
+ */
+ private void setColumnInfoFields( ColumnInfoRecord ci, Short width, Integer level, Boolean hidden, Boolean collapsed )
+ {
+ if (width != null)
+ ci.setColumnWidth(width.shortValue());
+ if (level != null)
+ ci.setOutlineLevel( level.shortValue() );
+ if (hidden != null)
+ ci.setHidden( hidden.booleanValue() );
+ if (collapsed != null)
+ ci.setCollapsed( collapsed.booleanValue() );
+ }
+
+ public int findColumnIdx(int column, int fromIdx)
+ {
+ if (column < 0)
+ throw new IllegalArgumentException( "column parameter out of range: " + column );
+ if (fromIdx < 0)
+ throw new IllegalArgumentException( "fromIdx parameter out of range: " + fromIdx );
+
+ ColumnInfoRecord ci;
+ for (int k = fromIdx; k < records.size(); k++)
+ {
+ ci = ( ColumnInfoRecord ) records.get(k);
+ if ((ci.getFirstColumn() <= column)
+ && (column <= ci.getLastColumn()))
+ {
+ return k;
+ }
+ ci = null;
+ }
+ return -1;
+ }
+
+ public void collapseColInfoRecords( int columnIdx )
+ {
+ if (columnIdx == 0)
+ return;
+ ColumnInfoRecord previousCol = (ColumnInfoRecord) records.get( columnIdx - 1);
+ ColumnInfoRecord currentCol = (ColumnInfoRecord) records.get( columnIdx );
+ boolean adjacentColumns = previousCol.getLastColumn() == currentCol.getFirstColumn() - 1;
+ if (!adjacentColumns)
+ return;
+
+ boolean columnsMatch =
+ previousCol.getXFIndex() == currentCol.getXFIndex() &&
+ previousCol.getOptions() == currentCol.getOptions() &&
+ previousCol.getColumnWidth() == currentCol.getColumnWidth();
+
+ if (columnsMatch)
+ {
+ previousCol.setLastColumn( currentCol.getLastColumn() );
+ records.remove( columnIdx );
+ }
+ }
+
+ /**
+ * Creates an outline group for the specified columns.
+ * @param fromColumn group from this column (inclusive)
+ * @param toColumn group to this column (inclusive)
+ * @param indent if true the group will be indented by one level,
+ * if false indenting will be removed by one level.
+ */
+ public void groupColumnRange(short fromColumn, short toColumn, boolean indent)
+ {
+
+ // Set the level for each column
+ int fromIdx = 0;
+ for (int i = fromColumn; i <= toColumn; i++)
+ {
+ int level = 1;
+ int columnIdx = findColumnIdx( i, Math.max(0,fromIdx) );
+ if (columnIdx != -1)
+ {
+ level = ((ColumnInfoRecord)records.get( columnIdx )).getOutlineLevel();
+ if (indent) level++; else level--;
+ level = Math.max(0, level);
+ level = Math.min(7, level);
+ fromIdx = columnIdx - 1; // subtract 1 just in case this column is collapsed later.
+ }
+ setColumn((short)i, null, new Integer(level), null, null);
+ columnIdx = findColumnIdx( i, Math.max(0, fromIdx ) );
+ collapseColInfoRecords( columnIdx );
+ }
+
+ }
+
+
+}
diff --git a/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java
index 39e9542ba2..32f25b312d 100644
--- a/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java
+++ b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java
@@ -20,12 +20,10 @@ package org.apache.poi.hssf.record.aggregates;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RowRecord;
-import org.apache.poi.hssf.record.UnknownRecord;
+import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
-import java.util.Iterator;
-import java.util.List;
/**
*
@@ -46,7 +44,6 @@ public class RowRecordsAggregate
public RowRecordsAggregate()
{
records = new TreeMap();
-
}
public void insertRow(RowRecord row)
@@ -121,6 +118,7 @@ public class RowRecordsAggregate
return k;
}
*/
+
/**
* called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a
@@ -186,15 +184,198 @@ public class RowRecordsAggregate
return records.values().iterator();
}
- /** Performs a deep clone of the record*/
- public Object clone() {
- RowRecordsAggregate rec = new RowRecordsAggregate();
- for (Iterator rowIter = getIterator(); rowIter.hasNext();) {
- //return the cloned Row Record & insert
- RowRecord row = (RowRecord)((RowRecord)rowIter.next()).clone();
- rec.insertRow(row);
- }
- return rec;
+ /**
+ * Performs a deep clone of the record
+ */
+ public Object clone()
+ {
+ RowRecordsAggregate rec = new RowRecordsAggregate();
+ for ( Iterator rowIter = getIterator(); rowIter.hasNext(); )
+ {
+ //return the cloned Row Record & insert
+ RowRecord row = (RowRecord) ( (RowRecord) rowIter.next() ).clone();
+ rec.insertRow( row );
+ }
+ return rec;
+ }
+
+
+ public int findStartOfRowOutlineGroup(int row)
+ {
+ // Find the start of the group.
+ RowRecord rowRecord = this.getRow( row );
+ int level = rowRecord.getOutlineLevel();
+ int currentRow = row;
+ while (this.getRow( currentRow ) != null)
+ {
+ rowRecord = this.getRow( currentRow );
+ if (rowRecord.getOutlineLevel() < level)
+ return currentRow + 1;
+ currentRow--;
+ }
+
+ return currentRow + 1;
+ }
+
+ public int findEndOfRowOutlineGroup( int row )
+ {
+ int level = getRow( row ).getOutlineLevel();
+ int currentRow;
+ for (currentRow = row; currentRow < this.getLastRowNum(); currentRow++)
+ {
+ if (getRow(currentRow) == null || getRow(currentRow).getOutlineLevel() < level)
+ {
+ break;
+ }
+ }
+
+ return currentRow-1;
+ }
+
+ public int writeHidden( RowRecord rowRecord, int row, boolean hidden )
+ {
+ int level = rowRecord.getOutlineLevel();
+ while (rowRecord != null && this.getRow(row).getOutlineLevel() >= level)
+ {
+ rowRecord.setZeroHeight( hidden );
+ row++;
+ rowRecord = this.getRow( row );
+ }
+ return row - 1;
+ }
+
+ public void collapseRow( int rowNumber )
+ {
+
+ // Find the start of the group.
+ int startRow = findStartOfRowOutlineGroup( rowNumber );
+ RowRecord rowRecord = (RowRecord) getRow( startRow );
+
+ // Hide all the columns until the end of the group
+ int lastRow = writeHidden( rowRecord, startRow, true );
+
+ // Write collapse field
+ if (getRow(lastRow + 1) != null)
+ {
+ getRow(lastRow + 1).setColapsed( true );
+ }
+ else
+ {
+ RowRecord row = createRow( lastRow + 1);
+ row.setColapsed( true );
+ insertRow( row );
+ }
+ }
+
+ /**
+ * Create a row record.
+ *
+ * @param row number
+ * @return RowRecord created for the passed in row number
+ * @see org.apache.poi.hssf.record.RowRecord
+ */
+ public static RowRecord createRow(int row)
+ {
+ RowRecord rowrec = new RowRecord();
+
+ //rowrec.setRowNumber(( short ) row);
+ rowrec.setRowNumber(row);
+ rowrec.setHeight(( short ) 0xff);
+ rowrec.setOptimize(( short ) 0x0);
+ rowrec.setOptionFlags(( short ) 0x100); // seems necessary for outlining
+ rowrec.setXFIndex(( short ) 0xf);
+ return rowrec;
+ }
+
+ public boolean isRowGroupCollapsed( int row )
+ {
+ int collapseRow = findEndOfRowOutlineGroup( row ) + 1;
+
+ if (getRow(collapseRow) == null)
+ return false;
+ else
+ return getRow( collapseRow ).getColapsed();
+ }
+
+ public void expandRow( int rowNumber )
+ {
+ int idx = rowNumber;
+ if (idx == -1)
+ return;
+
+ // If it is already expanded do nothing.
+ if (!isRowGroupCollapsed(idx))
+ return;
+
+ // Find the start of the group.
+ int startIdx = findStartOfRowOutlineGroup( idx );
+ RowRecord row = getRow( startIdx );
+
+ // Find the end of the group.
+ int endIdx = findEndOfRowOutlineGroup( idx );
+
+ // expand:
+ // colapsed bit must be unset
+ // hidden bit gets unset _if_ surrounding groups are expanded you can determine
+ // this by looking at the hidden bit of the enclosing group. You will have
+ // to look at the start and the end of the current group to determine which
+ // is the enclosing group
+ // hidden bit only is altered for this outline level. ie. don't uncollapse contained groups
+ if ( !isRowGroupHiddenByParent( idx ) )
+ {
+ for ( int i = startIdx; i <= endIdx; i++ )
+ {
+ if ( row.getOutlineLevel() == getRow( i ).getOutlineLevel() )
+ getRow( i ).setZeroHeight( false );
+ else if (!isRowGroupCollapsed(i))
+ getRow( i ).setZeroHeight( false );
+ }
+ }
+
+ // Write collapse field
+ getRow( endIdx + 1 ).setColapsed( false );
+ }
+
+ public boolean isRowGroupHiddenByParent( int row )
+ {
+ // Look out outline details of end
+ int endLevel;
+ boolean endHidden;
+ int endOfOutlineGroupIdx = findEndOfRowOutlineGroup( row );
+ if (getRow( endOfOutlineGroupIdx + 1 ) == null)
+ {
+ endLevel = 0;
+ endHidden = false;
+ }
+ else
+ {
+ endLevel = getRow( endOfOutlineGroupIdx + 1).getOutlineLevel();
+ endHidden = getRow( endOfOutlineGroupIdx + 1).getZeroHeight();
+ }
+
+ // Look out outline details of start
+ int startLevel;
+ boolean startHidden;
+ int startOfOutlineGroupIdx = findStartOfRowOutlineGroup( row );
+ if (startOfOutlineGroupIdx - 1 < 0 || getRow(startOfOutlineGroupIdx - 1) == null)
+ {
+ startLevel = 0;
+ startHidden = false;
+ }
+ else
+ {
+ startLevel = getRow( startOfOutlineGroupIdx - 1).getOutlineLevel();
+ startHidden = getRow( startOfOutlineGroupIdx - 1 ).getZeroHeight();
+ }
+
+ if (endLevel > startLevel)
+ {
+ return endHidden;
+ }
+ else
+ {
+ return startHidden;
+ }
}
}
diff --git a/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java b/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java
index 5469788145..4ddac6a6ad 100644
--- a/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java
+++ b/src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java
@@ -132,12 +132,14 @@ public class EscherGraphics
public void clipRect(int x, int y, int width, int height)
{
- logger.log(POILogger.WARN,"clipRect not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"clipRect not supported");
}
public void copyArea(int x, int y, int width, int height, int dx, int dy)
{
- logger.log(POILogger.WARN,"copyArea not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"copyArea not supported");
}
public Graphics create()
@@ -154,7 +156,8 @@ public class EscherGraphics
public void drawArc(int x, int y, int width, int height,
int startAngle, int arcAngle)
{
- logger.log(POILogger.WARN,"drawArc not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"drawArc not supported");
}
public boolean drawImage(Image img,
@@ -163,7 +166,8 @@ public class EscherGraphics
Color bgcolor,
ImageObserver observer)
{
- logger.log(POILogger.WARN,"drawImage not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"drawImage not supported");
return true;
}
@@ -173,7 +177,8 @@ public class EscherGraphics
int sx1, int sy1, int sx2, int sy2,
ImageObserver observer)
{
- logger.log(POILogger.WARN,"drawImage not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"drawImage not supported");
return true;
}
@@ -240,18 +245,21 @@ public class EscherGraphics
public void drawPolyline(int xPoints[], int yPoints[],
int nPoints)
{
- logger.log(POILogger.WARN,"drawPolyline not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"drawPolyline not supported");
}
public void drawRect(int x, int y, int width, int height)
{
- logger.log(POILogger.WARN,"drawRect not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"drawRect not supported");
}
public void drawRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight)
{
- logger.log(POILogger.WARN,"drawRoundRect not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"drawRoundRect not supported");
}
public void drawString(String str, int x, int y)
@@ -317,13 +325,15 @@ public class EscherGraphics
public void drawString(AttributedCharacterIterator iterator,
int x, int y)
{
- logger.log(POILogger.WARN,"drawString not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"drawString not supported");
}
public void fillArc(int x, int y, int width, int height,
int startAngle, int arcAngle)
{
- logger.log(POILogger.WARN,"fillArc not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"fillArc not supported");
}
public void fillOval(int x, int y, int width, int height)
@@ -383,7 +393,8 @@ public class EscherGraphics
public void fillRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight)
{
- logger.log(POILogger.WARN,"fillRoundRect not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"fillRoundRect not supported");
}
public Shape getClip()
@@ -438,17 +449,20 @@ public class EscherGraphics
public void setPaintMode()
{
- logger.log(POILogger.WARN,"setPaintMode not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"setPaintMode not supported");
}
public void setXORMode(Color color)
{
- logger.log(POILogger.WARN,"setXORMode not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"setXORMode not supported");
}
public void translate(int x, int y)
{
- logger.log(POILogger.WARN,"translate not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"translate not supported");
}
public Color getBackground()
diff --git a/src/java/org/apache/poi/hssf/usermodel/EscherGraphics2d.java b/src/java/org/apache/poi/hssf/usermodel/EscherGraphics2d.java
index 96e0eeace3..50676754bd 100644
--- a/src/java/org/apache/poi/hssf/usermodel/EscherGraphics2d.java
+++ b/src/java/org/apache/poi/hssf/usermodel/EscherGraphics2d.java
@@ -141,7 +141,8 @@ public class EscherGraphics2d extends Graphics2D
public void draw(Shape shape)
{
- logger.log(POILogger.WARN,"copyArea not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"copyArea not supported");
}
public void drawArc(int x, int y, int width, int height,
@@ -158,19 +159,22 @@ public class EscherGraphics2d extends Graphics2D
public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
int sx2, int sy2, Color bgColor, ImageObserver imageobserver)
{
- logger.log(POILogger.WARN,"drawImage() not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"drawImage() not supported");
return true;
}
public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
int sx2, int sy2, ImageObserver imageobserver)
{
- logger.log(POILogger.WARN,"drawImage() not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"drawImage() not supported");
return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, imageobserver);
}
public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, Color bgColor, ImageObserver imageobserver)
{
- logger.log(POILogger.WARN,"drawImage() not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"drawImage() not supported");
return true;
}
@@ -285,7 +289,8 @@ public class EscherGraphics2d extends Graphics2D
public void fill(Shape shape)
{
- logger.log(POILogger.WARN,"fill(Shape) not supported");
+ if (logger.check( POILogger.WARN ))
+ logger.log(POILogger.WARN,"fill(Shape) not supported");
}
public void fillArc(int i, int j, int k, int l, int i1, int j1)
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java
index 4e5655cb62..c84df9032e 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java
@@ -89,6 +89,7 @@ public class HSSFRow
this.book = book;
this.sheet = sheet;
row = new RowRecord();
+ row.setOptionFlags( (short)0x100 ); // seems necessary for outlining to work.
row.setHeight((short) 0xff);
row.setLastCol((short) -1);
row.setFirstCol((short) -1);
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
index 1d6588dc9f..c381e1f1a3 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
@@ -134,7 +134,8 @@ public class HSSFSheet
CellValueRecordInterface cval = sheet.getNextValueRecord();
long timestart = System.currentTimeMillis();
- log.log(DEBUG, "Time at start of cell creating in HSSF sheet = ",
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "Time at start of cell creating in HSSF sheet = ",
new Long(timestart));
HSSFRow lastrow = null;
@@ -150,10 +151,12 @@ public class HSSFSheet
if ( hrow != null )
{
lastrow = hrow;
- log.log( DEBUG, "record id = " + Integer.toHexString( ( (Record) cval ).getSid() ) );
+ if (log.check( POILogger.DEBUG ))
+ log.log( DEBUG, "record id = " + Integer.toHexString( ( (Record) cval ).getSid() ) );
hrow.createCellFromRecord( cval );
cval = sheet.getNextValueRecord();
- log.log( DEBUG, "record took ",
+ if (log.check( POILogger.DEBUG ))
+ log.log( DEBUG, "record took ",
new Long( System.currentTimeMillis() - cellstart ) );
}
else
@@ -161,7 +164,8 @@ public class HSSFSheet
cval = null;
}
}
- log.log(DEBUG, "total sheet cell creation took ",
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "total sheet cell creation took ",
new Long(System.currentTimeMillis() - timestart));
}
@@ -173,8 +177,6 @@ public class HSSFSheet
* @see org.apache.poi.hssf.usermodel.HSSFRow
* @see #removeRow(HSSFRow)
*/
-
- //public HSSFRow createRow(short rownum)
public HSSFRow createRow(int rownum)
{
HSSFRow row = new HSSFRow(book, sheet, rownum);
@@ -1251,6 +1253,47 @@ public class HSSFSheet
return patriarch;
}
+ /**
+ * Expands or collapses a column group.
+ *
+ * @param columnNumber One of the columns in the group.
+ * @param collapsed true = collapse group, false = expand group.
+ */
+ public void setColumnGroupCollapsed( short columnNumber, boolean collapsed )
+ {
+ sheet.setColumnGroupCollapsed( columnNumber, collapsed );
+ }
+
+ /**
+ * Create an outline for the provided column range.
+ *
+ * @param fromColumn beginning of the column range.
+ * @param toColumn end of the column range.
+ */
+ public void groupColumn(short fromColumn, short toColumn)
+ {
+ sheet.groupColumnRange( fromColumn, toColumn, true );
+ }
+
+ public void ungroupColumn( short fromColumn, short toColumn )
+ {
+ sheet.groupColumnRange( fromColumn, toColumn, false );
+ }
+
+ public void groupRow(int fromRow, int toRow)
+ {
+ sheet.groupRowRange( fromRow, toRow, true );
+ }
+
+ public void ungroupRow(int fromRow, int toRow)
+ {
+ sheet.groupRowRange( fromRow, toRow, false );
+ }
+
+ public void setRowGroupCollapsed( int row, boolean collapse )
+ {
+ sheet.setRowGroupCollapsed( row, collapse );
+ }
}
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
index 0700c34fc0..f4f8002d91 100644
--- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
+++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
@@ -46,8 +46,6 @@ import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
-import org.apache.poi.util.HexDump;
-import org.apache.poi.ddf.*;
/**
* High level representation of a workbook. This is the first object most users
@@ -759,7 +757,8 @@ public class HSSFWorkbook
public byte[] getBytes()
{
- log.log(DEBUG, "HSSFWorkbook.getBytes()");
+ if (log.check( POILogger.DEBUG ))
+ log.log(DEBUG, "HSSFWorkbook.getBytes()");
// before getting the workbook size we must tell the sheets that
// serialization is about to occur.
diff --git a/src/java/org/apache/poi/util/POILogger.java b/src/java/org/apache/poi/util/POILogger.java
index 12865927cb..7d485c6f73 100644
--- a/src/java/org/apache/poi/util/POILogger.java
+++ b/src/java/org/apache/poi/util/POILogger.java
@@ -42,7 +42,6 @@ public abstract class POILogger
* package scope so it cannot be instantiated outside of the util
* package. You need a POILogger? Go to the POILogFactory for one
*
- * @param log the object that does the real work of logging
*/
POILogger()
{}
@@ -55,7 +54,6 @@ public abstract class POILogger
* Check if a logger is enabled to log at the specified level
*
* @param level One of DEBUG, INFO, WARN, ERROR, FATAL
- * @param obj1 The logger to check.
*/
abstract public boolean check(final int level);
diff --git a/src/testcases/org/apache/poi/hssf/model/TestSheet.java b/src/testcases/org/apache/poi/hssf/model/TestSheet.java
new file mode 100644
index 0000000000..b11d93f015
--- /dev/null
+++ b/src/testcases/org/apache/poi/hssf/model/TestSheet.java
@@ -0,0 +1,58 @@
+
+/* ====================================================================
+ Copyright 2002-2004 Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+
+package org.apache.poi.hssf.model;
+
+import junit.framework.TestCase;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.record.BOFRecord;
+import org.apache.poi.hssf.record.EOFRecord;
+import org.apache.poi.hssf.record.DimensionsRecord;
+import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
+import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
+import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Unit test for the Sheet class.
+ *
+ * @author Glen Stampoultzis (glens at apache.org)
+ */
+public class TestSheet extends TestCase
+{
+ public void testCreateSheet() throws Exception
+ {
+ // Check we're adding row and cell aggregates
+ List records = new ArrayList();
+ records.add( new BOFRecord() );
+ records.add( new DimensionsRecord() );
+ records.add( new EOFRecord() );
+ Sheet sheet = Sheet.createSheet( records, 0, 0 );
+
+ int pos = 0;
+ assertTrue( sheet.records.get(pos++) instanceof BOFRecord );
+ assertTrue( sheet.records.get(pos++) instanceof ColumnInfoRecordsAggregate );
+ assertTrue( sheet.records.get(pos++) instanceof DimensionsRecord );
+ assertTrue( sheet.records.get(pos++) instanceof RowRecordsAggregate );
+ assertTrue( sheet.records.get(pos++) instanceof ValueRecordsAggregate );
+ assertTrue( sheet.records.get(pos++) instanceof EOFRecord );
+ }
+
+}