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
This commit is contained in:
Glen Stampoultzis 2004-07-28 13:06:33 +00:00
parent 54082fe268
commit 6a753e13ea
13 changed files with 1779 additions and 327 deletions

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (C) 2004 The Apache Software Foundation. All rights reserved. --> <!-- Copyright (C) 2004 The Apache Software Foundation. All rights reserved. -->
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "../dtd/document-v11.dtd"> <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "document-v11.dtd">
<document> <document>
<header> <header>
<title>Busy Developers' Guide to HSSF Features</title> <title>Busy Developers' Guide to HSSF Features</title>
<authors> <authors>
<person email="glens@apache.org" name="Glen Stampoultzis" id="CO"/> <person email="glens@apache.org" name="Glen Stampoultzis" id="GS"/>
</authors> </authors>
</header> </header>
<body> <body>
@ -44,6 +44,7 @@
<li><link href="#DrawingShapes">Drawing Shapes.</link></li> <li><link href="#DrawingShapes">Drawing Shapes.</link></li>
<li><link href="#StylingShapes">Styling Shapes.</link></li> <li><link href="#StylingShapes">Styling Shapes.</link></li>
<li><link href="#Graphics2d">Shapes and Graphics2d.</link></li> <li><link href="#Graphics2d">Shapes and Graphics2d.</link></li>
<li><link href="#Outlining">Outlining.</link></li>
</ul> </ul>
</section> </section>
<section><title>Features</title> <section><title>Features</title>
@ -902,6 +903,42 @@
using the POI logging infrastructure (disabled by default). using the POI logging infrastructure (disabled by default).
</p> </p>
</section> </section>
<anchor id="Outlining"/>
<section>
<title>Outlining</title>
<p>
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:
</p>
<source>
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();
</source>
<p>
To collapse (or expand) an outline use the following calls:
</p>
<source>
sheet1.setRowGroupCollapsed( 7, true );
sheet1.setColumnGroupCollapsed( (short)4, true );
</source>
<p>
The row/column you choose should contain an already
created group. It can be anywhere within the group.
</p>
</section>
</section> </section>
</section> </section>
</body> </body>

View File

@ -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();
}
}

View File

@ -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.FormulaRecordAggregate;
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate; 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.hssf.record.formula.Ptg;
import org.apache.poi.util.IntList; import org.apache.poi.util.IntList;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
@ -60,6 +61,8 @@ public class Sheet implements Model
public static final short TopMargin = 2; public static final short TopMargin = 2;
public static final short BottomMargin = 3; public static final short BottomMargin = 3;
private static POILogger log = POILogFactory.getLogger(Sheet.class);
protected ArrayList records = null; protected ArrayList records = null;
int preoffset = 0; // offset of the sheet in a new file int preoffset = 0; // offset of the sheet in a new file
int loc = 0; int loc = 0;
@ -75,12 +78,11 @@ public class Sheet implements Model
protected PrintGridlinesRecord printGridlines = null; protected PrintGridlinesRecord printGridlines = null;
protected WindowTwoRecord windowTwo = null; protected WindowTwoRecord windowTwo = null;
protected MergeCellsRecord merged = null; protected MergeCellsRecord merged = null;
protected Margin margins[] = null; protected Margin[] margins = null;
protected List mergedRecords = new ArrayList(); protected List mergedRecords = new ArrayList();
protected int numMergedRegions = 0; protected int numMergedRegions = 0;
protected SelectionRecord selection = null; protected SelectionRecord selection = null;
private static POILogger log = POILogFactory.getLogger(Sheet.class); protected ColumnInfoRecordsAggregate columns = null;
private ArrayList columnSizes = null; // holds column info
protected ValueRecordsAggregate cells = null; protected ValueRecordsAggregate cells = null;
protected RowRecordsAggregate rows = null; protected RowRecordsAggregate rows = null;
private Iterator valueRecIterator = null; private Iterator valueRecIterator = null;
@ -123,6 +125,7 @@ public class Sheet implements Model
*/ */
public static Sheet createSheet(List recs, int sheetnum, int offset) public static Sheet createSheet(List recs, int sheetnum, int offset)
{ {
if (log.check( POILogger.DEBUG ))
log.logFormatted(POILogger.DEBUG, log.logFormatted(POILogger.DEBUG,
"Sheet createSheet (existing file) with %", "Sheet createSheet (existing file) with %",
new Integer(recs.size())); new Integer(recs.size()));
@ -138,17 +141,20 @@ public class Sheet implements Model
if (rec.getSid() == LabelRecord.sid) if (rec.getSid() == LabelRecord.sid)
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Hit label record."); log.log(POILogger.DEBUG, "Hit label record.");
retval.containsLabels = true; retval.containsLabels = true;
} }
else if (rec.getSid() == BOFRecord.sid) else if (rec.getSid() == BOFRecord.sid)
{ {
bofEofNestingLevel++; bofEofNestingLevel++;
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Hit BOF record. Nesting increased to " + bofEofNestingLevel); log.log(POILogger.DEBUG, "Hit BOF record. Nesting increased to " + bofEofNestingLevel);
} }
else if (rec.getSid() == EOFRecord.sid) else if (rec.getSid() == EOFRecord.sid)
{ {
--bofEofNestingLevel; --bofEofNestingLevel;
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Hit EOF record. Nesting decreased to " + bofEofNestingLevel); log.log(POILogger.DEBUG, "Hit EOF record. Nesting decreased to " + bofEofNestingLevel);
if (bofEofNestingLevel == 0) { if (bofEofNestingLevel == 0) {
records.add(rec); records.add(rec);
@ -158,6 +164,13 @@ public class Sheet implements Model
} }
else if (rec.getSid() == DimensionsRecord.sid) 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.dims = ( DimensionsRecord ) rec;
retval.dimsloc = records.size(); retval.dimsloc = records.size();
} }
@ -169,11 +182,16 @@ public class Sheet implements Model
} }
else if (rec.getSid() == ColumnInfoRecord.sid) 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) else if (rec.getSid() == DefaultColWidthRecord.sid)
{ {
@ -283,6 +301,7 @@ public class Sheet implements Model
// { // {
// retval.cells = new ValueRecordsAggregate(); // retval.cells = new ValueRecordsAggregate();
// } // }
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited"); log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited");
return retval; return retval;
} }
@ -342,6 +361,7 @@ public class Sheet implements Model
public static Sheet createSheet(List records, int sheetnum) public static Sheet createSheet(List records, int sheetnum)
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, log.log(POILogger.DEBUG,
"Sheet createSheet (exisiting file) assumed offset 0"); "Sheet createSheet (exisiting file) assumed offset 0");
return createSheet(records, sheetnum, 0); return createSheet(records, sheetnum, 0);
@ -357,6 +377,7 @@ public class Sheet implements Model
public static Sheet createSheet() public static Sheet createSheet()
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Sheet createsheet from scratch called"); log.log(POILogger.DEBUG, "Sheet createsheet from scratch called");
Sheet retval = new Sheet(); Sheet retval = new Sheet();
ArrayList records = new ArrayList(30); ArrayList records = new ArrayList(30);
@ -397,6 +418,9 @@ public class Sheet implements Model
retval.defaultcolwidth = retval.defaultcolwidth =
(DefaultColWidthRecord) retval.createDefaultColWidth(); (DefaultColWidthRecord) retval.createDefaultColWidth();
records.add( retval.defaultcolwidth); records.add( retval.defaultcolwidth);
ColumnInfoRecordsAggregate columns = new ColumnInfoRecordsAggregate();
records.add( columns );
retval.columns = columns;
retval.dims = ( DimensionsRecord ) retval.createDimensions(); retval.dims = ( DimensionsRecord ) retval.createDimensions();
records.add(retval.dims); records.add(retval.dims);
retval.dimsloc = records.size()-1; retval.dimsloc = records.size()-1;
@ -409,7 +433,9 @@ public class Sheet implements Model
records.add(retval.protect); records.add(retval.protect);
records.add(retval.createEOF()); records.add(retval.createEOF());
retval.records = records; retval.records = records;
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Sheet createsheet from scratch exit"); log.log(POILogger.DEBUG, "Sheet createsheet from scratch exit");
return retval; return retval;
} }
@ -549,6 +575,7 @@ public class Sheet implements Model
public void convertLabelRecords(Workbook wb) public void convertLabelRecords(Workbook wb)
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "convertLabelRecords called"); log.log(POILogger.DEBUG, "convertLabelRecords called");
if (containsLabels) if (containsLabels)
{ {
@ -573,6 +600,7 @@ public class Sheet implements Model
} }
} }
} }
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "convertLabelRecords exit"); log.log(POILogger.DEBUG, "convertLabelRecords exit");
} }
@ -587,6 +615,8 @@ public class Sheet implements Model
{ {
checkCells(); checkCells();
checkRows(); checkRows();
if (log.check( POILogger.DEBUG ))
{
log.log(POILogger.DEBUG, "Sheet.getNumRecords"); log.log(POILogger.DEBUG, "Sheet.getNumRecords");
log.logFormatted(POILogger.DEBUG, "returning % + % + % - 2 = %", new int[] log.logFormatted(POILogger.DEBUG, "returning % + % + % - 2 = %", new int[]
{ {
@ -595,6 +625,7 @@ public class Sheet implements Model
records.size() + cells.getPhysicalNumberOfCells() records.size() + cells.getPhysicalNumberOfCells()
+ rows.getPhysicalNumberOfRows() - 2 + rows.getPhysicalNumberOfRows() - 2
}); });
}
return records.size() + cells.getPhysicalNumberOfCells() return records.size() + cells.getPhysicalNumberOfCells()
+ rows.getPhysicalNumberOfRows() - 2; + rows.getPhysicalNumberOfRows() - 2;
} }
@ -610,6 +641,8 @@ public class Sheet implements Model
//public void setDimensions(short firstrow, short firstcol, short lastrow, //public void setDimensions(short firstrow, short firstcol, short lastrow,
public void setDimensions(int firstrow, short firstcol, int lastrow, public void setDimensions(int firstrow, short firstcol, int lastrow,
short lastcol) short lastcol)
{
if (log.check( POILogger.DEBUG ))
{ {
log.log(POILogger.DEBUG, "Sheet.setDimensions"); log.log(POILogger.DEBUG, "Sheet.setDimensions");
log.log(POILogger.DEBUG, log.log(POILogger.DEBUG,
@ -617,10 +650,12 @@ public class Sheet implements Model
.append("firstcol").append(firstcol).append("lastrow") .append("firstcol").append(firstcol).append("lastrow")
.append(lastrow).append("lastcol").append(lastcol) .append(lastrow).append("lastcol").append(lastcol)
.toString()); .toString());
}
dims.setFirstCol(firstcol); dims.setFirstCol(firstcol);
dims.setFirstRow(firstrow); dims.setFirstRow(firstrow);
dims.setLastCol(lastcol); dims.setLastCol(lastcol);
dims.setLastRow(lastrow); dims.setLastRow(lastrow);
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Sheet.setDimensions exiting"); log.log(POILogger.DEBUG, "Sheet.setDimensions exiting");
} }
@ -643,6 +678,7 @@ public class Sheet implements Model
public void setLoc(int loc) public void setLoc(int loc)
{ {
valueRecIterator = null; valueRecIterator = null;
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "sheet.setLoc(): " + loc); log.log(POILogger.DEBUG, "sheet.setLoc(): " + loc);
this.loc = loc; this.loc = loc;
} }
@ -654,6 +690,7 @@ public class Sheet implements Model
public int getLoc() public int getLoc()
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "sheet.getLoc():" + loc); log.log(POILogger.DEBUG, "sheet.getLoc():" + loc);
return loc; return loc;
} }
@ -692,6 +729,7 @@ public class Sheet implements Model
public byte [] serialize() public byte [] serialize()
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Sheet.serialize"); log.log(POILogger.DEBUG, "Sheet.serialize");
// addDBCellRecords(); // addDBCellRecords();
@ -721,6 +759,7 @@ public class Sheet implements Model
pos += (( Record ) records.get(k)).serialize(pos, pos += (( Record ) records.get(k)).serialize(pos,
retval); // rec.length; retval); // rec.length;
} }
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Sheet.serialize returning " + retval); log.log(POILogger.DEBUG, "Sheet.serialize returning " + retval);
return retval; return retval;
} }
@ -736,6 +775,7 @@ public class Sheet implements Model
public int serialize(int offset, byte [] data) public int serialize(int offset, byte [] data)
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Sheet.serialize using offsets"); log.log(POILogger.DEBUG, "Sheet.serialize using offsets");
// addDBCellRecords(); // addDBCellRecords();
@ -775,6 +815,7 @@ public class Sheet implements Model
pos += record.serialize(pos + offset, data ); // rec.length; pos += record.serialize(pos + offset, data ); // rec.length;
} }
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Sheet.serialize returning "); log.log(POILogger.DEBUG, "Sheet.serialize returning ");
return pos; return pos;
} }
@ -789,16 +830,7 @@ public class Sheet implements Model
public RowRecord createRow(int row) public RowRecord createRow(int row)
{ {
log.log(POILogger.DEBUG, "create row number " + row); return RowRecordsAggregate.createRow( 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;
} }
/** /**
@ -1032,6 +1064,7 @@ public class Sheet implements Model
{ {
checkCells(); checkCells();
setLoc(dimsloc); setLoc(dimsloc);
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "replaceValueRecord "); log.log(POILogger.DEBUG, "replaceValueRecord ");
cells.insertCell(newval); cells.insertCell(newval);
@ -1068,6 +1101,7 @@ public class Sheet implements Model
public void addRow(RowRecord row) public void addRow(RowRecord row)
{ {
checkRows(); checkRows();
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "addRow "); log.log(POILogger.DEBUG, "addRow ");
DimensionsRecord d = ( DimensionsRecord ) records.get(getDimsLoc()); DimensionsRecord d = ( DimensionsRecord ) records.get(getDimsLoc());
@ -1122,6 +1156,7 @@ public class Sheet implements Model
* } * }
* } * }
*/ */
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "exit addRow"); log.log(POILogger.DEBUG, "exit addRow");
} }
@ -1182,6 +1217,7 @@ public class Sheet implements Model
public CellValueRecordInterface getNextValueRecord() public CellValueRecordInterface getNextValueRecord()
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "getNextValue loc= " + loc); log.log(POILogger.DEBUG, "getNextValue loc= " + loc);
if (valueRecIterator == null) if (valueRecIterator == null)
{ {
@ -1269,6 +1305,7 @@ public class Sheet implements Model
public RowRecord getNextRow() public RowRecord getNextRow()
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "getNextRow loc= " + loc); log.log(POILogger.DEBUG, "getNextRow loc= " + loc);
if (rowRecIterator == null) if (rowRecIterator == null)
{ {
@ -1315,6 +1352,7 @@ public class Sheet implements Model
//public RowRecord getRow(short rownum) //public RowRecord getRow(short rownum)
public RowRecord getRow(int rownum) public RowRecord getRow(int rownum)
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "getNextRow loc= " + loc); log.log(POILogger.DEBUG, "getNextRow loc= " + loc);
return rows.getRow(rownum); return rows.getRow(rownum);
@ -1787,12 +1825,7 @@ public class Sheet implements Model
protected Record createColInfo() protected Record createColInfo()
{ {
ColumnInfoRecord retval = new ColumnInfoRecord(); return ColumnInfoRecordsAggregate.createColInfo();
retval.setColumnWidth(( short ) 0x8);
retval.setOptions(( short ) 6);
retval.setXFIndex(( short ) 0x0f);
return retval;
} }
/** /**
@ -1867,13 +1900,12 @@ public class Sheet implements Model
{ {
short retval = 0; short retval = 0;
ColumnInfoRecord ci = null; 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) if ((ci.getFirstColumn() <= column)
&& (column <= ci.getLastColumn())) && (column <= ci.getLastColumn()))
{ {
@ -1898,104 +1930,46 @@ public class Sheet implements Model
* @param column - the column number * @param column - the column number
* @param width (in units of 1/20th of a character width) * @param width (in units of 1/20th of a character width)
*/ */
public void setColumnWidth(short column, short width) public void setColumnWidth(short column, short width)
{ {
ColumnInfoRecord ci = null; setColumn( column, new Short(width), null, null, null);
int k = 0; }
if (columnSizes == null) public void setColumn(short column, Short width, Integer level, Boolean hidden, Boolean collapsed)
{ {
columnSizes = new ArrayList(); if (columns == null)
} columns = new ColumnInfoRecordsAggregate();
//int cioffset = getDimsLoc() - columnSizes.size();
for (k = 0; k < columnSizes.size(); k++) columns.setColumn( column, width, level, hidden, collapsed );
{
ci = ( ColumnInfoRecord ) columnSizes.get(k);
if ((ci.getFirstColumn() <= column)
&& (column <= ci.getLastColumn()))
{
break;
} }
ci = null;
} /**
if (ci != null) * Creates an outline group for the specified columns.
{ * @param fromColumn group from this column (inclusive)
if (ci.getColumnWidth() == width) * @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)
{ {
// do nothing...the cell's width is equal to what we're setting it to. // Set the level for each column
} columns.groupColumnRange( fromColumn, toColumn, indent);
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))
{
// okay so the width is different but the first or last column == the column we'return setting // Determine the maximum overall level
// we'll just divide the info and create a new one int maxLevel = 0;
if (ci.getFirstColumn() == column) for ( Iterator iterator = columns.getIterator(); iterator.hasNext(); )
{ {
ci.setFirstColumn(( short ) (column + 1)); 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 else
{ guts.setTopColGutter( (short) ( 29 + (12 * (maxLevel-1)) ) );
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
{
// 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);
nci.setColumnWidth(width);
columnSizes.add(k, nci);
records.add((1 + getDimsLoc() - columnSizes.size()) + k, nci);
dimsloc++;
}
} }
/** /**
@ -2125,7 +2099,6 @@ public class Sheet implements Model
protected Record createMergedCells() protected Record createMergedCells()
{ {
MergeCellsRecord retval = new MergeCellsRecord(); MergeCellsRecord retval = new MergeCellsRecord();
retval.setNumAreas(( short ) 0); retval.setNumAreas(( short ) 0);
return retval; return retval;
} }
@ -2149,6 +2122,7 @@ public class Sheet implements Model
public int getDimsLoc() public int getDimsLoc()
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "getDimsLoc dimsloc= " + dimsloc); log.log(POILogger.DEBUG, "getDimsLoc dimsloc= " + dimsloc);
return dimsloc; return dimsloc;
} }
@ -2433,25 +2407,8 @@ public class Sheet implements Model
windowTwo.setFreezePanesNoSplit(true); windowTwo.setFreezePanesNoSplit(true);
SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid); SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
// SelectionRecord sel2 = (SelectionRecord) sel.clone(); sel.setPane((byte)pane.getActivePane());
// 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);
// 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); windowTwo.setFreezePanesNoSplit(false);
SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid); SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
// SelectionRecord sel2 = (SelectionRecord) sel.clone(); sel.setPane(PANE_LOWER_RIGHT);
// 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);
} }
public SelectionRecord getSelection() public SelectionRecord getSelection()
@ -2512,15 +2452,16 @@ public class Sheet implements Model
{ {
this.selection = selection; this.selection = selection;
} }
/** /**
* creates a Protect record with protect set to false. * creates a Protect record with protect set to false.
* @see org.apache.poi.hssf.record.ProtectRecord * @see org.apache.poi.hssf.record.ProtectRecord
* @see org.apache.poi.hssf.record.Record * @see org.apache.poi.hssf.record.Record
* @return a ProtectRecord * @return a ProtectRecord
*/ */
protected Record createProtect() protected Record createProtect()
{ {
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "create protect record with protection disabled"); log.log(POILogger.DEBUG, "create protect record with protection disabled");
ProtectRecord retval = new ProtectRecord(); ProtectRecord retval = new ProtectRecord();
@ -2705,7 +2646,7 @@ public class Sheet implements Model
/** /**
* Sets a page break at the indicated column * Sets a page break at the indicated column
* @param row *
*/ */
public void setColumnBreak(short column, short fromRow, short toRow) { public void setColumnBreak(short column, short fromRow, short toRow) {
colBreaks.addBreak(column, fromRow, toRow); colBreaks.addBreak(column, fromRow, toRow);
@ -2713,7 +2654,7 @@ public class Sheet implements Model
/** /**
* Removes a page break at the indicated column * Removes a page break at the indicated column
* @param row *
*/ */
public void removeColumnBreak(short column) { public void removeColumnBreak(short column) {
colBreaks.removeBreak(column); colBreaks.removeBreak(column);
@ -2721,7 +2662,7 @@ public class Sheet implements Model
/** /**
* Queries if the specified column has a page break * Queries if the specified column has a page break
* @param row *
* @return true if the specified column has a page break * @return true if the specified column has a page break
*/ */
public boolean isColumnBroken(short column) { public boolean isColumnBroken(short column) {
@ -2779,4 +2720,360 @@ public class Sheet implements Model
public int getNumColumnBreaks(){ public int getNumColumnBreaks(){
return (int)colBreaks.getNumBreaks(); 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;
// }
// }
} }

View File

@ -122,6 +122,7 @@ public class Workbook implements Model
* @return Workbook object * @return Workbook object
*/ */
public static Workbook createWorkbook(List recs) { public static Workbook createWorkbook(List recs) {
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "Workbook (readfile) created with reclen=", log.log(DEBUG, "Workbook (readfile) created with reclen=",
new Integer(recs.size())); new Integer(recs.size()));
Workbook retval = new Workbook(); Workbook retval = new Workbook();
@ -132,71 +133,85 @@ public class Workbook implements Model
if (rec.getSid() == EOFRecord.sid) { if (rec.getSid() == EOFRecord.sid) {
records.add(rec); records.add(rec);
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found workbook eof record at " + k); log.log(DEBUG, "found workbook eof record at " + k);
break; break;
} }
switch (rec.getSid()) { switch (rec.getSid()) {
case BoundSheetRecord.sid : case BoundSheetRecord.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found boundsheet record at " + k); log.log(DEBUG, "found boundsheet record at " + k);
retval.boundsheets.add(rec); retval.boundsheets.add(rec);
retval.records.setBspos( k ); retval.records.setBspos( k );
break; break;
case SSTRecord.sid : case SSTRecord.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found sst record at " + k); log.log(DEBUG, "found sst record at " + k);
retval.sst = ( SSTRecord ) rec; retval.sst = ( SSTRecord ) rec;
break; break;
case FontRecord.sid : case FontRecord.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found font record at " + k); log.log(DEBUG, "found font record at " + k);
retval.records.setFontpos( k ); retval.records.setFontpos( k );
retval.numfonts++; retval.numfonts++;
break; break;
case ExtendedFormatRecord.sid : case ExtendedFormatRecord.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found XF record at " + k); log.log(DEBUG, "found XF record at " + k);
retval.records.setXfpos( k ); retval.records.setXfpos( k );
retval.numxfs++; retval.numxfs++;
break; break;
case TabIdRecord.sid : case TabIdRecord.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found tabid record at " + k); log.log(DEBUG, "found tabid record at " + k);
retval.records.setTabpos( k ); retval.records.setTabpos( k );
break; break;
case ProtectRecord.sid : case ProtectRecord.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found protect record at " + k); log.log(DEBUG, "found protect record at " + k);
retval.records.setProtpos( k ); retval.records.setProtpos( k );
break; break;
case BackupRecord.sid : case BackupRecord.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found backup record at " + k); log.log(DEBUG, "found backup record at " + k);
retval.records.setBackuppos( k ); retval.records.setBackuppos( k );
break; break;
case ExternSheetRecord.sid : case ExternSheetRecord.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found extern sheet record at " + k); log.log(DEBUG, "found extern sheet record at " + k);
retval.externSheet = ( ExternSheetRecord ) rec; retval.externSheet = ( ExternSheetRecord ) rec;
break; break;
case NameRecord.sid : case NameRecord.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found name record at " + k); log.log(DEBUG, "found name record at " + k);
retval.names.add(rec); retval.names.add(rec);
// retval.records.namepos = k; // retval.records.namepos = k;
break; break;
case SupBookRecord.sid : case SupBookRecord.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found SupBook record at " + k); log.log(DEBUG, "found SupBook record at " + k);
// retval.records.supbookpos = k; // retval.records.supbookpos = k;
break; break;
case FormatRecord.sid : case FormatRecord.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found format record at " + k); log.log(DEBUG, "found format record at " + k);
retval.formats.add(rec); retval.formats.add(rec);
retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode(); retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode();
break; break;
case DateWindow1904Record.sid : case DateWindow1904Record.sid :
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found datewindow1904 record at " + k); log.log(DEBUG, "found datewindow1904 record at " + k);
retval.uses1904datewindowing = ((DateWindow1904Record)rec).getWindowing() == 1; retval.uses1904datewindowing = ((DateWindow1904Record)rec).getWindowing() == 1;
break; break;
case PaletteRecord.sid: case PaletteRecord.sid:
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "found palette record at " + k); log.log(DEBUG, "found palette record at " + k);
retval.records.setPalettepos( k ); retval.records.setPalettepos( k );
default : default :
@ -204,12 +219,13 @@ public class Workbook implements Model
records.add(rec); records.add(rec);
} }
//What if we dont have any ranges and supbooks //What if we dont have any ranges and supbooks
// if (retval.records.supbookpos == 0) { // if (retval.records.supbookpos == 0) {
// retval.records.supbookpos = retval.records.bspos + 1; // retval.records.supbookpos = retval.records.bspos + 1;
// retval.records.namepos = retval.records.supbookpos + 1; // retval.records.namepos = retval.records.supbookpos + 1;
// } // }
retval.records.setRecords(records); retval.records.setRecords(records);
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "exit create workbook from existing file function"); log.log(DEBUG, "exit create workbook from existing file function");
return retval; return retval;
} }
@ -220,6 +236,7 @@ public class Workbook implements Model
*/ */
public static Workbook createWorkbook() public static Workbook createWorkbook()
{ {
if (log.check( POILogger.DEBUG ))
log.log( DEBUG, "creating new workbook from scratch" ); log.log( DEBUG, "creating new workbook from scratch" );
Workbook retval = new Workbook(); Workbook retval = new Workbook();
ArrayList records = new ArrayList( 30 ); ArrayList records = new ArrayList( 30 );
@ -296,6 +313,7 @@ public class Workbook implements Model
records.add( retval.createEOF() ); records.add( retval.createEOF() );
retval.records.setRecords(records); retval.records.setRecords(records);
if (log.check( POILogger.DEBUG ))
log.log( DEBUG, "exit create new workbook from scratch" ); log.log( DEBUG, "exit create new workbook from scratch" );
return retval; return retval;
} }
@ -403,6 +421,7 @@ public class Workbook implements Model
*/ */
public void setSheetBof(int sheetnum, int pos) { public void setSheetBof(int sheetnum, int pos) {
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "setting bof for sheetnum =", new Integer(sheetnum), log.log(DEBUG, "setting bof for sheetnum =", new Integer(sheetnum),
" at pos=", new Integer(pos)); " at pos=", new Integer(pos));
checkSheets(sheetnum); checkSheets(sheetnum);
@ -535,6 +554,7 @@ public class Workbook implements Model
*/ */
public int getNumSheets() { public int getNumSheets() {
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "getNumSheets=", new Integer(boundsheets.size())); log.log(DEBUG, "getNumSheets=", new Integer(boundsheets.size()));
return boundsheets.size(); return boundsheets.size();
} }
@ -546,6 +566,7 @@ public class Workbook implements Model
*/ */
public int getNumExFormats() { public int getNumExFormats() {
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "getXF=", new Integer(numxfs)); log.log(DEBUG, "getXF=", new Integer(numxfs));
return numxfs; return numxfs;
} }
@ -593,6 +614,7 @@ public class Workbook implements Model
*/ */
public int addSSTString(String string, boolean use16bits) { public int addSSTString(String string, boolean use16bits) {
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "insert to sst string='", string, "' and use16bits= ", log.log(DEBUG, "insert to sst string='", string, "' and use16bits= ",
new Boolean(use16bits)); new Boolean(use16bits));
if (sst == null) { if (sst == null) {
@ -626,6 +648,7 @@ public class Workbook implements Model
} }
String retval = sst.getString(str); String retval = sst.getString(str);
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "Returning SST for index=", new Integer(str), log.log(DEBUG, "Returning SST for index=", new Integer(str),
" String= ", retval); " String= ", retval);
return retval; return retval;
@ -639,6 +662,7 @@ public class Workbook implements Model
*/ */
public void insertSST() { public void insertSST() {
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "creating new SST via insertSST!"); log.log(DEBUG, "creating new SST via insertSST!");
sst = ( SSTRecord ) createSST(); sst = ( SSTRecord ) createSST();
records.add(records.size() - 1, createExtendedSST()); records.add(records.size() - 1, createExtendedSST());
@ -682,6 +706,7 @@ public class Workbook implements Model
public int serialize( int offset, byte[] data ) public int serialize( int offset, byte[] data )
{ {
if (log.check( POILogger.DEBUG ))
log.log( DEBUG, "Serializing Workbook with offsets" ); log.log( DEBUG, "Serializing Workbook with offsets" );
int pos = 0; int pos = 0;
@ -707,6 +732,7 @@ public class Workbook implements Model
pos += record.serialize( pos + offset, data ); // rec.length; pos += record.serialize( pos + offset, data ); // rec.length;
} }
} }
if (log.check( POILogger.DEBUG ))
log.log( DEBUG, "Exiting serialize workbook" ); log.log( DEBUG, "Exiting serialize workbook" );
return pos; return pos;
} }

View File

@ -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 <code>idx</code>.
*/
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 <code>ci</code> 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 );
}
}
}

View File

@ -20,12 +20,10 @@ package org.apache.poi.hssf.record.aggregates;
import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RowRecord; 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.Map;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.Iterator;
import java.util.List;
/** /**
* *
@ -46,7 +44,6 @@ public class RowRecordsAggregate
public RowRecordsAggregate() public RowRecordsAggregate()
{ {
records = new TreeMap(); records = new TreeMap();
} }
public void insertRow(RowRecord row) public void insertRow(RowRecord row)
@ -121,6 +118,7 @@ public class RowRecordsAggregate
return k; return k;
} }
*/ */
/** /**
* called by the class that is responsible for writing this sucker. * called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a * Subclasses should implement this so that their data is passed back in a
@ -186,16 +184,199 @@ public class RowRecordsAggregate
return records.values().iterator(); return records.values().iterator();
} }
/** Performs a deep clone of the record*/ /**
public Object clone() { * Performs a deep clone of the record
*/
public Object clone()
{
RowRecordsAggregate rec = new RowRecordsAggregate(); RowRecordsAggregate rec = new RowRecordsAggregate();
for (Iterator rowIter = getIterator(); rowIter.hasNext();) { for ( Iterator rowIter = getIterator(); rowIter.hasNext(); )
{
//return the cloned Row Record & insert //return the cloned Row Record & insert
RowRecord row = (RowRecord)((RowRecord)rowIter.next()).clone(); RowRecord row = (RowRecord) ( (RowRecord) rowIter.next() ).clone();
rec.insertRow(row); rec.insertRow( row );
} }
return rec; 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;
}
}
} }

View File

@ -132,11 +132,13 @@ public class EscherGraphics
public void clipRect(int x, int y, int width, int height) public void clipRect(int x, int y, int width, int height)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"clipRect not supported"); logger.log(POILogger.WARN,"clipRect not supported");
} }
public void copyArea(int x, int y, int width, int height, int dx, int dy) public void copyArea(int x, int y, int width, int height, int dx, int dy)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"copyArea not supported"); logger.log(POILogger.WARN,"copyArea not supported");
} }
@ -154,6 +156,7 @@ public class EscherGraphics
public void drawArc(int x, int y, int width, int height, public void drawArc(int x, int y, int width, int height,
int startAngle, int arcAngle) int startAngle, int arcAngle)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"drawArc not supported"); logger.log(POILogger.WARN,"drawArc not supported");
} }
@ -163,6 +166,7 @@ public class EscherGraphics
Color bgcolor, Color bgcolor,
ImageObserver observer) ImageObserver observer)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"drawImage not supported"); logger.log(POILogger.WARN,"drawImage not supported");
return true; return true;
@ -173,6 +177,7 @@ public class EscherGraphics
int sx1, int sy1, int sx2, int sy2, int sx1, int sy1, int sx2, int sy2,
ImageObserver observer) ImageObserver observer)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"drawImage not supported"); logger.log(POILogger.WARN,"drawImage not supported");
return true; return true;
} }
@ -240,17 +245,20 @@ public class EscherGraphics
public void drawPolyline(int xPoints[], int yPoints[], public void drawPolyline(int xPoints[], int yPoints[],
int nPoints) int nPoints)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"drawPolyline not supported"); logger.log(POILogger.WARN,"drawPolyline not supported");
} }
public void drawRect(int x, int y, int width, int height) public void drawRect(int x, int y, int width, int height)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"drawRect not supported"); logger.log(POILogger.WARN,"drawRect not supported");
} }
public void drawRoundRect(int x, int y, int width, int height, public void drawRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight) int arcWidth, int arcHeight)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"drawRoundRect not supported"); logger.log(POILogger.WARN,"drawRoundRect not supported");
} }
@ -317,12 +325,14 @@ public class EscherGraphics
public void drawString(AttributedCharacterIterator iterator, public void drawString(AttributedCharacterIterator iterator,
int x, int y) int x, int y)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"drawString not supported"); logger.log(POILogger.WARN,"drawString not supported");
} }
public void fillArc(int x, int y, int width, int height, public void fillArc(int x, int y, int width, int height,
int startAngle, int arcAngle) int startAngle, int arcAngle)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"fillArc not supported"); logger.log(POILogger.WARN,"fillArc not supported");
} }
@ -383,6 +393,7 @@ public class EscherGraphics
public void fillRoundRect(int x, int y, int width, int height, public void fillRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight) int arcWidth, int arcHeight)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"fillRoundRect not supported"); logger.log(POILogger.WARN,"fillRoundRect not supported");
} }
@ -438,16 +449,19 @@ public class EscherGraphics
public void setPaintMode() public void setPaintMode()
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"setPaintMode not supported"); logger.log(POILogger.WARN,"setPaintMode not supported");
} }
public void setXORMode(Color color) public void setXORMode(Color color)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"setXORMode not supported"); logger.log(POILogger.WARN,"setXORMode not supported");
} }
public void translate(int x, int y) public void translate(int x, int y)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"translate not supported"); logger.log(POILogger.WARN,"translate not supported");
} }

View File

@ -141,6 +141,7 @@ public class EscherGraphics2d extends Graphics2D
public void draw(Shape shape) public void draw(Shape shape)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"copyArea not supported"); logger.log(POILogger.WARN,"copyArea not supported");
} }
@ -158,6 +159,7 @@ public class EscherGraphics2d extends Graphics2D
public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, 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) int sx2, int sy2, Color bgColor, ImageObserver imageobserver)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"drawImage() not supported"); logger.log(POILogger.WARN,"drawImage() not supported");
return true; return true;
} }
@ -165,11 +167,13 @@ public class EscherGraphics2d extends Graphics2D
public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
int sx2, int sy2, ImageObserver imageobserver) int sx2, int sy2, ImageObserver imageobserver)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"drawImage() not supported"); logger.log(POILogger.WARN,"drawImage() not supported");
return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, imageobserver); 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) public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, Color bgColor, ImageObserver imageobserver)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"drawImage() not supported"); logger.log(POILogger.WARN,"drawImage() not supported");
return true; return true;
} }
@ -285,6 +289,7 @@ public class EscherGraphics2d extends Graphics2D
public void fill(Shape shape) public void fill(Shape shape)
{ {
if (logger.check( POILogger.WARN ))
logger.log(POILogger.WARN,"fill(Shape) not supported"); logger.log(POILogger.WARN,"fill(Shape) not supported");
} }

View File

@ -89,6 +89,7 @@ public class HSSFRow
this.book = book; this.book = book;
this.sheet = sheet; this.sheet = sheet;
row = new RowRecord(); row = new RowRecord();
row.setOptionFlags( (short)0x100 ); // seems necessary for outlining to work.
row.setHeight((short) 0xff); row.setHeight((short) 0xff);
row.setLastCol((short) -1); row.setLastCol((short) -1);
row.setFirstCol((short) -1); row.setFirstCol((short) -1);

View File

@ -134,6 +134,7 @@ public class HSSFSheet
CellValueRecordInterface cval = sheet.getNextValueRecord(); CellValueRecordInterface cval = sheet.getNextValueRecord();
long timestart = System.currentTimeMillis(); long timestart = System.currentTimeMillis();
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "Time at start of cell creating in HSSF sheet = ", log.log(DEBUG, "Time at start of cell creating in HSSF sheet = ",
new Long(timestart)); new Long(timestart));
HSSFRow lastrow = null; HSSFRow lastrow = null;
@ -150,9 +151,11 @@ public class HSSFSheet
if ( hrow != null ) if ( hrow != null )
{ {
lastrow = hrow; lastrow = hrow;
if (log.check( POILogger.DEBUG ))
log.log( DEBUG, "record id = " + Integer.toHexString( ( (Record) cval ).getSid() ) ); log.log( DEBUG, "record id = " + Integer.toHexString( ( (Record) cval ).getSid() ) );
hrow.createCellFromRecord( cval ); hrow.createCellFromRecord( cval );
cval = sheet.getNextValueRecord(); cval = sheet.getNextValueRecord();
if (log.check( POILogger.DEBUG ))
log.log( DEBUG, "record took ", log.log( DEBUG, "record took ",
new Long( System.currentTimeMillis() - cellstart ) ); new Long( System.currentTimeMillis() - cellstart ) );
} }
@ -161,6 +164,7 @@ public class HSSFSheet
cval = null; cval = null;
} }
} }
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "total sheet cell creation took ", log.log(DEBUG, "total sheet cell creation took ",
new Long(System.currentTimeMillis() - timestart)); new Long(System.currentTimeMillis() - timestart));
} }
@ -173,8 +177,6 @@ public class HSSFSheet
* @see org.apache.poi.hssf.usermodel.HSSFRow * @see org.apache.poi.hssf.usermodel.HSSFRow
* @see #removeRow(HSSFRow) * @see #removeRow(HSSFRow)
*/ */
//public HSSFRow createRow(short rownum)
public HSSFRow createRow(int rownum) public HSSFRow createRow(int rownum)
{ {
HSSFRow row = new HSSFRow(book, sheet, rownum); HSSFRow row = new HSSFRow(book, sheet, rownum);
@ -1251,6 +1253,47 @@ public class HSSFSheet
return patriarch; 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 );
}
} }

View File

@ -46,8 +46,6 @@ import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; 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 * High level representation of a workbook. This is the first object most users
@ -759,6 +757,7 @@ public class HSSFWorkbook
public byte[] getBytes() public byte[] getBytes()
{ {
if (log.check( POILogger.DEBUG ))
log.log(DEBUG, "HSSFWorkbook.getBytes()"); log.log(DEBUG, "HSSFWorkbook.getBytes()");
// before getting the workbook size we must tell the sheets that // before getting the workbook size we must tell the sheets that

View File

@ -42,7 +42,6 @@ public abstract class POILogger
* package scope so it cannot be instantiated outside of the util * package scope so it cannot be instantiated outside of the util
* package. You need a POILogger? Go to the POILogFactory for one * package. You need a POILogger? Go to the POILogFactory for one
* *
* @param log the object that does the real work of logging
*/ */
POILogger() POILogger()
{} {}
@ -55,7 +54,6 @@ public abstract class POILogger
* Check if a logger is enabled to log at the specified level * Check if a logger is enabled to log at the specified level
* *
* @param level One of DEBUG, INFO, WARN, ERROR, FATAL * @param level One of DEBUG, INFO, WARN, ERROR, FATAL
* @param obj1 The logger to check.
*/ */
abstract public boolean check(final int level); abstract public boolean check(final int level);

View File

@ -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 );
}
}