]> source.dussan.org Git - poi.git/commitdiff
Support for outlining. Enjoy.
authorGlen Stampoultzis <glens@apache.org>
Wed, 28 Jul 2004 13:06:33 +0000 (13:06 +0000)
committerGlen Stampoultzis <glens@apache.org>
Wed, 28 Jul 2004 13:06:33 +0000 (13:06 +0000)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/branches/REL_2_BRANCH@353574 13f79535-47bb-0310-9956-ffa450edef68

13 files changed:
src/documentation/content/xdocs/hssf/quick-guide.xml
src/examples/src/org/apache/poi/hssf/usermodel/examples/Outlines.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/model/Sheet.java
src/java/org/apache/poi/hssf/model/Workbook.java
src/java/org/apache/poi/hssf/record/aggregates/ColumnInfoRecordsAggregate.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java
src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java
src/java/org/apache/poi/hssf/usermodel/EscherGraphics2d.java
src/java/org/apache/poi/hssf/usermodel/HSSFRow.java
src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
src/java/org/apache/poi/util/POILogger.java
src/testcases/org/apache/poi/hssf/model/TestSheet.java [new file with mode: 0644]

index ea5830e8d7a72cdeceb1c22b3988af8730dae023..5dfbe81092858bc7375be42cc94ee5e825442a97 100644 (file)
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- 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>
     <header>
         <title>Busy Developers' Guide to HSSF Features</title>
         <authors>
-            <person email="glens@apache.org" name="Glen Stampoultzis" id="CO"/>
+            <person email="glens@apache.org" name="Glen Stampoultzis" id="GS"/>
         </authors>
     </header>
     <body>
@@ -44,6 +44,7 @@
                     <li><link href="#DrawingShapes">Drawing Shapes.</link></li>
                     <li><link href="#StylingShapes">Styling Shapes.</link></li>
                     <li><link href="#Graphics2d">Shapes and Graphics2d.</link></li>
+                    <li><link href="#Outlining">Outlining.</link></li>
                 </ul>
             </section>
             <section><title>Features</title>
                         using the POI logging infrastructure (disabled by default).
                     </p>
                 </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>
     </body>
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 (file)
index 0000000..de6195d
--- /dev/null
@@ -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();
+    }
+
+
+}
index 90909662bc67ef320055d1b55affd3b0e330265e..1a44d6e57f5bf90d45a5ca501318cb11ce3634fd 100644 (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.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;
+//        }
+//    }
+
 }
index 8ce327270a05e95384f07468dbacfe2b67b9bc0a..9b0a18f362aea7ba9d2e6364ee368ce5fc360a2c 100644 (file)
@@ -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 (file)
index 0000000..6eb9b11
--- /dev/null
@@ -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 );
+        }
+
+    }
+
+
+}
index 39e9542ba268f5b9bb50dec24300e38ff94d9054..32f25b312d3a82b14156dba575c290881aac457d 100644 (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.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;
+        }
     }
 
 }
index 54697881455414590235438808e0db950126c94a..4ddac6a6ad46bfb12b6b54185eeb91ca8d20324a 100644 (file)
@@ -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()
index 96e0eeace3d6d76c0a22151105030325c02bd590..50676754bd169d99547bbac980fd4e99c06e9387 100644 (file)
@@ -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)
index 4e5655cb6225f0252dd9abfa2845de4f0172a8cd..c84df9032e1a640fc2214e19d2269a5b828f0220 100644 (file)
@@ -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);
index 1d6588dc9f5f4105d397188e9c40c566647dcb77..c381e1f1a35794f4916123aeb0247a18dffc3d31 100644 (file)
@@ -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 );
+    }
 
 
 }
index 0700c34fc07698cf3f8b04979b8c3ad5af0b4ad2..f4f8002d91587fe3abc98d61c7be05edf378ed32 100644 (file)
@@ -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.
index 12865927cb2003f5a37bc644ec0a965d81bcd4d5..7d485c6f73d258253e7f0327647a7e7dc9b2a73a 100644 (file)
@@ -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 (file)
index 0000000..b11d93f
--- /dev/null
@@ -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 );
+    }
+
+}