Author: yegor
Date: Tue May 17 10:46:35 2011
New Revision: 1104120

URL: http://svn.apache.org/viewvc?rev=1104120&view=rev
Log:
Bugzilla 51160: Initial version of SXSSF, a low memory foortprint API to 
produce xlsx files

Added:
    poi/trunk/src/examples/src/org/apache/poi/ss/examples/SSPerformanceTest.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java
Modified:
    poi/trunk/src/documentation/content/xdocs/status.xml

Modified: poi/trunk/src/documentation/content/xdocs/status.xml
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/status.xml?rev=1104120&r1=1104119&r2=1104120&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/status.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/status.xml Tue May 17 10:46:35 
2011
@@ -34,7 +34,8 @@
 
     <changes>
         <release version="3.8-beta3" date="2011-??-??">
-           <action dev="poi-developers" type="add">51171 - Improved 
performance of opening large .xls files</action>
+           <action dev="poi-developers" type="add">51160 - Initial version of 
SXSSF, a low memory foortprint API to produce xlsx files</action>
+           <action dev="poi-developers" type="fix">51171 - Improved 
performance of opening large .xls files</action>
            <action dev="poi-developers" type="add">51172 - Add XWPF support 
for GIF pictures</action>
            <action dev="poi-developers" type="add">NPOIFS Mini Streams now 
support extending the underlying big block stream to fit more data</action>
            <action dev="poi-developers" type="fix">51148 - XWPFDocument now 
properly tracks paragraphs and tables when adding/removing them</action>

Added: 
poi/trunk/src/examples/src/org/apache/poi/ss/examples/SSPerformanceTest.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/examples/src/org/apache/poi/ss/examples/SSPerformanceTest.java?rev=1104120&view=auto
==============================================================================
--- 
poi/trunk/src/examples/src/org/apache/poi/ss/examples/SSPerformanceTest.java 
(added)
+++ 
poi/trunk/src/examples/src/org/apache/poi/ss/examples/SSPerformanceTest.java 
Tue May 17 10:46:35 2011
@@ -0,0 +1,204 @@
+/*
+ *  ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one or more
+ *    contributor license agreements.  See the NOTICE file distributed with
+ *    this work for additional information regarding copyright ownership.
+ *    The ASF licenses this file to You 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.ss.examples;
+
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+public class SSPerformanceTest {
+    public static void main(String[] args) {
+        if (args.length != 4) usage("need four command arguments");
+
+        String type = args[0];
+        long timeStarted = System.currentTimeMillis();
+        Workbook workBook = createWorkbook(type);
+        boolean isHType = workBook instanceof HSSFWorkbook;
+
+        int rows = parseInt(args[1], "Failed to parse rows value as integer");
+        int cols = parseInt(args[2], "Failed to parse cols value as integer");
+        boolean saveFile = parseInt(args[3], "Failed to parse saveFile value 
as integer") != 0;
+
+        Map<String, CellStyle> styles = createStyles(workBook);
+
+        Sheet sheet = workBook.createSheet("Main Sheet");
+
+        Cell headerCell = sheet.createRow(0).createCell(0);
+        headerCell.setCellValue("Header text is spanned across multiple 
cells");
+        headerCell.setCellStyle(styles.get("header"));
+        sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$F$1"));
+
+        int sheetNo = 0;
+        int rowIndexInSheet = 1;
+        double value = 0;
+        Calendar calendar = Calendar.getInstance();
+        for (int rowIndex = 0; rowIndex < rows; rowIndex++) {
+            if (isHType && sheetNo != rowIndex / 0x10000) {
+                sheet = workBook.createSheet("Spillover from sheet " + 
(++sheetNo));
+                headerCell.setCellValue("Header text is spanned across 
multiple cells");
+                headerCell.setCellStyle(styles.get("header"));
+                sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$F$1"));
+                rowIndexInSheet = 1;
+            }
+
+            Row row = sheet.createRow(rowIndexInSheet);
+            for (int colIndex = 0; colIndex < cols; colIndex++) {
+                Cell cell = row.createCell(colIndex);
+                String address = new CellReference(cell).formatAsString();
+                switch (colIndex){
+                    case 0:
+                        // column A: default number format
+                        cell.setCellValue(value++);
+                        break;
+                    case 1:
+                        // column B: #,##0
+                        cell.setCellValue(value++);
+                        cell.setCellStyle(styles.get("#,##0.00"));
+                        break;
+                    case 2:
+                        // column C: $#,##0.00
+                        cell.setCellValue(value++);
+                        cell.setCellStyle(styles.get("$#,##0.00"));
+                        break;
+                    case 3:
+                        // column D: red bold text on yellow background
+                        cell.setCellValue(address);
+                        cell.setCellStyle(styles.get("red-bold"));
+                        break;
+                    case 4:
+                        // column E: boolean
+                        // TODO booleans are shown as 1/0 instead of TRUE/FALSE
+                        cell.setCellValue(rowIndex % 2 == 0);
+                        break;
+                    case 5:
+                        // column F:  date / time
+                        cell.setCellValue(calendar);
+                        cell.setCellStyle(styles.get("m/d/yyyy"));
+                        calendar.roll(Calendar.DAY_OF_YEAR, -1);
+                        break;
+                    case 6:
+                        // column F: formula
+                        // TODO formulas are not yet supported  in SXSSF
+                        //cell.setCellFormula("SUM(A" + (rowIndex+1) + ":E" + 
(rowIndex+1)+ ")");
+                        //break;
+                    default:
+                        cell.setCellValue(value++);
+                        break;
+                }
+            }
+            rowIndexInSheet++;
+        }
+        if (saveFile) {
+            String fileName = type + "_" + rows + "_" + cols + "." + 
getFileSuffix(args[0]);
+            try {
+                FileOutputStream out = new FileOutputStream(fileName);
+                workBook.write(out);
+                out.close();
+            } catch (IOException ioe) {
+                System.err.println("Error: failed to write to file \"" + 
fileName + "\", reason=" + ioe.getMessage());
+            }
+        }
+        long timeFinished = System.currentTimeMillis();
+        System.out.println("Elapsed " + (timeFinished-timeStarted)/1000 + " 
seconds");
+    }
+
+    static Map<String, CellStyle> createStyles(Workbook wb) {
+        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
+        CellStyle style;
+
+        Font headerFont = wb.createFont();
+        headerFont.setFontHeightInPoints((short) 14);
+        headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
+        style = wb.createCellStyle();
+        style.setAlignment(CellStyle.ALIGN_CENTER);
+        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+        style.setFont(headerFont);
+        
style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
+        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
+        styles.put("header", style);
+
+        Font monthFont = wb.createFont();
+        monthFont.setFontHeightInPoints((short)12);
+        monthFont.setColor(IndexedColors.RED.getIndex());
+        monthFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
+        style = wb.createCellStyle();
+        style.setAlignment(CellStyle.ALIGN_CENTER);
+        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+        style.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
+        style.setFillPattern(CellStyle.SOLID_FOREGROUND);
+        style.setFont(monthFont);
+        styles.put("red-bold", style);
+
+        String[] nfmt = {"#,##0.00", "$#,##0.00", "m/d/yyyy"};
+        for(String fmt : nfmt){
+            style = wb.createCellStyle();
+            style.setDataFormat(wb.createDataFormat().getFormat(fmt));
+            styles.put(fmt, style);
+        }
+
+        return styles;
+    }
+
+
+    static void usage(String message) {
+        System.err.println(message);
+        System.err.println("usage: java SSPerformanceTest HSSF|XSSF|SXSSF rows 
cols saveFile (0|1)? ");
+        System.exit(1);
+    }
+
+    static Workbook createWorkbook(String type) {
+        if ("HSSF".equals(type))
+            return new HSSFWorkbook();
+        else if ("XSSF".equals(type))
+            return new XSSFWorkbook();
+        else if ("SXSSF".equals(type))
+            return new SXSSFWorkbook();
+        else
+            usage("Unknown type \"" + type + "\"");
+        return null;
+    }
+
+    static String getFileSuffix(String type) {
+        if ("HSSF".equals(type))
+            return "xls";
+        else if ("XSSF".equals(type))
+            return "xlsx";
+        else if ("SXSSF".equals(type))
+            return "xlsx";
+        return null;
+    }
+
+    static int parseInt(String value, String msg) {
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            usage(msg);
+        }
+        return 0;
+    }
+}

Added: poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java?rev=1104120&view=auto
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java 
(added)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java Tue 
May 17 10:46:35 2011
@@ -0,0 +1,1013 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.xssf.streaming;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.RichTextString;
+import org.apache.poi.ss.usermodel.Comment;
+import org.apache.poi.ss.usermodel.Hyperlink;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.formula.FormulaParseException;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+/**
+ * Streaming version of XSSFRow implementing the "BigGridDemo" strategy.
+ *
+ * @author Alex Geller, Four J's Development Tools
+*/
+public class SXSSFCell implements Cell 
+{
+
+    SXSSFRow _row;
+    Value _value;
+    CellStyle _style;
+    Property _firstProperty;
+
+    public SXSSFCell(SXSSFRow row,int cellType)
+    {
+        _row=row;
+        setType(cellType);
+    }
+
+//start of interface implementation
+
+    /**
+     * Returns column index of this cell
+     *
+     * @return zero-based column index of a column in a sheet.
+     */
+    public int getColumnIndex()
+    {
+        return _row.getCellIndex(this);
+    }
+
+    /**
+     * Returns row index of a row in the sheet that contains this cell
+     *
+     * @return zero-based row index of a row in the sheet that contains this 
cell
+     */
+    public int getRowIndex()
+    {
+        return _row.getRowNum();
+    }
+
+    /**
+     * Returns the sheet this cell belongs to
+     *
+     * @return the sheet this cell belongs to
+     */
+    public Sheet getSheet()
+    {
+        return _row.getSheet();
+    }
+
+    /**
+     * Returns the Row this cell belongs to
+     *
+     * @return the Row that owns this cell
+     */
+     public Row getRow()
+     {
+         return _row;
+     }
+
+    /**
+     * Set the cells type (numeric, formula or string)
+     *
+     * @throws IllegalArgumentException if the specified cell type is invalid
+     * @see #CELL_TYPE_NUMERIC
+     * @see #CELL_TYPE_STRING
+     * @see #CELL_TYPE_FORMULA
+     * @see #CELL_TYPE_BLANK
+     * @see #CELL_TYPE_BOOLEAN
+     * @see #CELL_TYPE_ERROR
+     */
+    public void setCellType(int cellType)
+    {
+        ensureType(cellType);
+    }
+
+    /**
+     * Return the cell type.
+     *
+     * @return the cell type
+     * @see Cell#CELL_TYPE_BLANK
+     * @see Cell#CELL_TYPE_NUMERIC
+     * @see Cell#CELL_TYPE_STRING
+     * @see Cell#CELL_TYPE_FORMULA
+     * @see Cell#CELL_TYPE_BOOLEAN
+     * @see Cell#CELL_TYPE_ERROR
+     */
+    public int getCellType()
+    {
+        return _value.getType();
+    }
+
+    /**
+     * Only valid for formula cells
+     * @return one of ({@link #CELL_TYPE_NUMERIC}, {@link #CELL_TYPE_STRING},
+     *     {@link #CELL_TYPE_BOOLEAN}, {@link #CELL_TYPE_ERROR}) depending
+     * on the cached value of the formula
+     */
+    public int getCachedFormulaResultType()
+    {
+//TODO: Implement this correctly
+        assert false;
+        return CELL_TYPE_NUMERIC;
+    }
+
+    /**
+     * Set a numeric value for the cell
+     *
+     * @param value  the numeric value to set this cell to.  For formulas 
we'll set the
+     *        precalculated value, for numerics we'll set its value. For other 
types we
+     *        will change the cell to a numeric cell and set its value.
+     */
+    public void setCellValue(double value)
+    {
+        ensureTypeOrFormulaType(CELL_TYPE_NUMERIC);
+        if(_value.getType()==CELL_TYPE_FORMULA)
+            ((NumericFormulaValue)_value).setPreEvaluatedValue(value);
+        else
+            ((NumericValue)_value).setValue(value);
+    }
+
+    /**
+     * Converts the supplied date to its equivalent Excel numeric value and 
sets
+     * that into the cell.
+     * <p/>
+     * <b>Note</b> - There is actually no 'DATE' cell type in Excel. In many
+     * cases (when entering date values), Excel automatically adjusts the
+     * <i>cell style</i> to some date format, creating the illusion that the 
cell
+     * data type is now something besides {@link Cell#CELL_TYPE_NUMERIC}.  POI
+     * does not attempt to replicate this behaviour.  To make a numeric cell
+     * display as a date, use {@link #setCellStyle(CellStyle)} etc.
+     *
+     * @param value the numeric value to set this cell to.  For formulas we'll 
set the
+     *        precalculated value, for numerics we'll set its value. For other 
types we
+     *        will change the cell to a numerics cell and set its value.
+     */
+    public void setCellValue(Date value)
+    {
+//TODO: activate this when compiling against 3.7.
+        //boolean date1904 = getSheet().getXSSFWorkbook().isDate1904();
+        boolean date1904 = false;
+        setCellValue(DateUtil.getExcelDate(value, date1904));
+    }
+
+    /**
+     * Set a date value for the cell. Excel treats dates as numeric so you 
will need to format the cell as
+     * a date.
+     * <p>
+     * This will set the cell value based on the Calendar's timezone. As Excel
+     * does not support timezones this means that both 20:00+03:00 and
+     * 20:00-03:00 will be reported as the same value (20:00) even that there
+     * are 6 hours difference between the two times. This difference can be
+     * preserved by using <code>setCellValue(value.getTime())</code> which will
+     * automatically shift the times to the default timezone.
+     * </p>
+     *
+     * @param value  the date value to set this cell to.  For formulas we'll 
set the
+     *        precalculated value, for numerics we'll set its value. For 
othertypes we
+     *        will change the cell to a numeric cell and set its value.
+     */
+    public void setCellValue(Calendar value)
+    {
+//TODO: activate this when compiling against 3.7.
+        //boolean date1904 = getSheet().getXSSFWorkbook().isDate1904();
+        boolean date1904 = false;
+        setCellValue( DateUtil.getExcelDate(value, date1904 ));
+    }
+
+    /**
+     * Set a rich string value for the cell.
+     *
+     * @param value  value to set the cell to.  For formulas we'll set the 
formula
+     * string, for String cells we'll set its value.  For other types we will
+     * change the cell to a string cell and set its value.
+     * If value is null then we will change the cell to a Blank cell.
+     */
+    public void setCellValue(RichTextString value)
+    {
+        ensureRichTextStringType();
+        ((RichTextValue)_value).setValue(value);
+    }
+
+    /**
+     * Set a string value for the cell.
+     *
+     * @param value  value to set the cell to.  For formulas we'll set the 
formula
+     * string, for String cells we'll set its value.  For other types we will
+     * change the cell to a string cell and set its value.
+     * If value is null then we will change the cell to a Blank cell.
+     */
+    public void setCellValue(String value)
+    {
+        ensureTypeOrFormulaType(CELL_TYPE_STRING);
+        if(_value.getType()==CELL_TYPE_FORMULA)
+            ((StringFormulaValue)_value).setPreEvaluatedValue(value);
+        else
+            ((PlainStringValue)_value).setValue(value);
+    }
+
+    /**
+     * Sets formula for this cell.
+     * <p>
+     * Note, this method only sets the formula string and does not calculate 
the formula value.
+     * To set the precalculated value use {@link #setCellValue(double)} or 
{@link #setCellValue(String)}
+     * </p>
+     *
+     * @param formula the formula to set, e.g. <code>"SUM(C4:E4)"</code>.
+     *  If the argument is <code>null</code> then the current formula is 
removed.
+     * @throws FormulaParseException if the formula has incorrect syntax or is 
otherwise invalid
+     */
+    public void setCellFormula(String formula) throws FormulaParseException
+    {
+        ensureFormulaType(computeTypeFromFormula(formula));
+        ((FormulaValue)_value).setValue(formula);
+    }
+    /**
+     * Return a formula for the cell, for example, <code>SUM(C4:E4)</code>
+     *
+     * @return a formula for the cell
+     * @throws IllegalStateException if the cell type returned by {@link 
#getCellType()} is not CELL_TYPE_FORMULA
+     */
+    public String getCellFormula()
+    {
+       if(_value.getType()!=CELL_TYPE_FORMULA)
+           throw typeMismatch(CELL_TYPE_FORMULA,_value.getType(),false);
+        return ((FormulaValue)_value).getValue();
+    }
+
+    /**
+     * Get the value of the cell as a number.
+     * <p>
+     * For strings we throw an exception. For blank cells we return a 0.
+     * For formulas or error cells we return the precalculated value;
+     * </p>
+     * @return the value of the cell as a number
+     * @throws IllegalStateException if the cell type returned by {@link 
#getCellType()} is CELL_TYPE_STRING
+     * @exception NumberFormatException if the cell value isn't a parsable 
<code>double</code>.
+     * @see org.apache.poi.ss.usermodel.DataFormatter for turning this number 
into a string similar to that which Excel would render this number as.
+     */
+    public double getNumericCellValue()
+    {
+        int cellType = getCellType();
+        switch(cellType) 
+        {
+            case CELL_TYPE_BLANK:
+                return 0.0;
+            case CELL_TYPE_FORMULA:
+            {
+                FormulaValue fv=(FormulaValue)_value;
+                if(fv.getFormulaType()!=CELL_TYPE_NUMERIC)
+                      throw typeMismatch(CELL_TYPE_NUMERIC, CELL_TYPE_FORMULA, 
false);
+                return ((NumericFormulaValue)_value).getPreEvaluatedValue();
+            }
+            case CELL_TYPE_NUMERIC:
+                return ((NumericValue)_value).getValue();
+            default:
+                throw typeMismatch(CELL_TYPE_NUMERIC, cellType, false);
+        }
+    }
+
+    /**
+     * Get the value of the cell as a date.
+     * <p>
+     * For strings we throw an exception. For blank cells we return a null.
+     * </p>
+     * @return the value of the cell as a date
+     * @throws IllegalStateException if the cell type returned by {@link 
#getCellType()} is CELL_TYPE_STRING
+     * @exception NumberFormatException if the cell value isn't a parsable 
<code>double</code>.
+     * @see org.apache.poi.ss.usermodel.DataFormatter for formatting  this 
date into a string similar to how excel does.
+     */
+    public Date getDateCellValue()
+    {
+        int cellType = getCellType();
+        if (cellType == CELL_TYPE_BLANK) 
+        {
+            return null;
+        }
+
+        double value = getNumericCellValue();
+//TODO: activate this when compiling against 3.7.
+        //boolean date1904 = getSheet().getXSSFWorkbook().isDate1904();
+        boolean date1904 = false;
+        return DateUtil.getJavaDate(value, date1904);
+    }
+
+    /**
+     * Get the value of the cell as a XSSFRichTextString
+     * <p>
+     * For numeric cells we throw an exception. For blank cells we return an 
empty string.
+     * For formula cells we return the pre-calculated value if a string, 
otherwise an exception.
+     * </p>
+     * @return the value of the cell as a XSSFRichTextString
+     */
+    public RichTextString getRichStringCellValue()
+    {
+        int cellType = getCellType();
+        
if(!(getCellType()==CELL_TYPE_STRING&&((StringValue)_value).isRichText()))
+            throw typeMismatch(CELL_TYPE_STRING, cellType, false);
+        return ((RichTextValue)_value).getValue();
+    }
+
+
+    /**
+     * Get the value of the cell as a string
+     * <p>
+     * For numeric cells we throw an exception. For blank cells we return an 
empty string.
+     * For formulaCells that are not string Formulas, we throw an exception.
+     * </p>
+     * @return the value of the cell as a string
+     */
+    public String getStringCellValue()
+    {
+        int cellType = getCellType();
+        switch(cellType) 
+        {
+            case CELL_TYPE_BLANK:
+                return "";
+            case CELL_TYPE_FORMULA:
+            {
+                FormulaValue fv=(FormulaValue)_value;
+                if(fv.getFormulaType()!=CELL_TYPE_STRING)
+                      throw typeMismatch(CELL_TYPE_STRING, CELL_TYPE_FORMULA, 
false);
+                return ((StringFormulaValue)_value).getPreEvaluatedValue();
+            }
+            case CELL_TYPE_STRING:
+            {
+                if(((StringValue)_value).isRichText())
+                    return ((RichTextValue)_value).getValue().getString();
+                else
+                    return ((PlainStringValue)_value).getValue();
+            }
+            default:
+                throw typeMismatch(CELL_TYPE_STRING, cellType, false);
+        }
+    }
+
+    /**
+     * Set a boolean value for the cell
+     *
+     * @param value the boolean value to set this cell to.  For formulas we'll 
set the
+     *        precalculated value, for booleans we'll set its value. For other 
types we
+     *        will change the cell to a boolean cell and set its value.
+     */
+    public void setCellValue(boolean value)
+    {
+        ensureTypeOrFormulaType(CELL_TYPE_BOOLEAN);
+        if(_value.getType()==CELL_TYPE_FORMULA)
+            ((BooleanFormulaValue)_value).setPreEvaluatedValue(value);
+        else
+            ((BooleanValue)_value).setValue(value);
+    }
+
+    /**
+     * Set a error value for the cell
+     *
+     * @param value the error value to set this cell to.  For formulas we'll 
set the
+     *        precalculated value , for errors we'll set
+     *        its value. For other types we will change the cell to an error
+     *        cell and set its value.
+     * @see org.apache.poi.ss.usermodel.FormulaError
+     */
+    public void setCellErrorValue(byte value)
+    {
+        ensureType(CELL_TYPE_ERROR);
+        if(_value.getType()==CELL_TYPE_FORMULA)
+            ((ErrorFormulaValue)_value).setPreEvaluatedValue(value);
+        else
+            ((ErrorValue)_value).setValue(value);
+    }
+
+    /**
+     * Get the value of the cell as a boolean.
+     * <p>
+     * For strings, numbers, and errors, we throw an exception. For blank 
cells we return a false.
+     * </p>
+     * @return the value of the cell as a boolean
+     * @throws IllegalStateException if the cell type returned by {@link 
#getCellType()}
+     *   is not CELL_TYPE_BOOLEAN, CELL_TYPE_BLANK or CELL_TYPE_FORMULA
+     */
+    public boolean getBooleanCellValue()
+    {
+        int cellType = getCellType();
+        switch(cellType) 
+        {
+            case CELL_TYPE_BLANK:
+                return false;
+            case CELL_TYPE_FORMULA:
+            {
+                FormulaValue fv=(FormulaValue)_value;
+                if(fv.getFormulaType()!=CELL_TYPE_BOOLEAN)
+                      throw typeMismatch(CELL_TYPE_BOOLEAN, CELL_TYPE_FORMULA, 
false);
+                return ((BooleanFormulaValue)_value).getPreEvaluatedValue();
+            }
+            case CELL_TYPE_BOOLEAN:
+            {
+                return ((BooleanValue)_value).getValue();
+            }
+            default:
+                throw typeMismatch(CELL_TYPE_BOOLEAN, cellType, false);
+        }
+    }
+
+    /**
+     * Get the value of the cell as an error code.
+     * <p>
+     * For strings, numbers, and booleans, we throw an exception.
+     * For blank cells we return a 0.
+     * </p>
+     *
+     * @return the value of the cell as an error code
+     * @throws IllegalStateException if the cell type returned by {@link 
#getCellType()} isn't CELL_TYPE_ERROR
+     * @see org.apache.poi.ss.usermodel.FormulaError for error codes
+     */
+    public byte getErrorCellValue()
+    {
+        int cellType = getCellType();
+        switch(cellType) 
+        {
+            case CELL_TYPE_BLANK:
+                return 0;
+            case CELL_TYPE_FORMULA:
+            {
+                FormulaValue fv=(FormulaValue)_value;
+                if(fv.getFormulaType()!=CELL_TYPE_ERROR)
+                      throw typeMismatch(CELL_TYPE_ERROR, CELL_TYPE_FORMULA, 
false);
+                return ((ErrorFormulaValue)_value).getPreEvaluatedValue();
+            }
+            case CELL_TYPE_ERROR:
+            {
+                return ((ErrorValue)_value).getValue();
+            }
+            default:
+                throw typeMismatch(CELL_TYPE_ERROR, cellType, false);
+        }
+    }
+
+    /**
+     * Set the style for the cell.  The style should be an CellStyle 
created/retreived from
+     * the Workbook.
+     *
+     * @param style  reference contained in the workbook.
+     * If the value is null then the style information is removed causing the 
cell to used the default workbook style.
+     * @see org.apache.poi.ss.usermodel.Workbook#createCellStyle()
+     */
+    public void setCellStyle(CellStyle style)
+    {
+        _style=style;
+    }
+
+    /**
+     * Return the cell's style.
+     *
+     * @return the cell's style. Always not-null. Default cell style has zero 
index and can be obtained as
+     * <code>workbook.getCellStyleAt(0)</code>
+     * @see org.apache.poi.ss.usermodel.Workbook#getCellStyleAt(short)
+     */
+    public CellStyle getCellStyle()
+    {
+        return _style;
+    }
+
+    /**
+     * Sets this cell as the active cell for the worksheet
+     */
+    public void setAsActiveCell()
+    {
+//TODO: What needs to be done here? Is there a "the active cell" at the sheet 
or even the workbook level?
+        //getRow().setAsActiveCell(this);
+    }
+
+    /**
+     * Assign a comment to this cell
+     *
+     * @param comment comment associated with this cell
+     */
+    public void setCellComment(Comment comment)
+    {
+        setProperty(Property.COMMENT,comment);
+    }
+
+    /**
+     * Returns comment associated with this cell
+     *
+     * @return comment associated with this cell or <code>null</code> if not 
found
+     */
+    public Comment getCellComment()
+    {
+        return (Comment)getPropertyValue(Property.COMMENT);
+    }
+
+    /**
+     * Removes the comment for this cell, if there is one.
+     */
+    public void removeCellComment()
+    {
+        removeProperty(Property.COMMENT);
+    }
+
+    /**
+     * @return hyperlink associated with this cell or <code>null</code> if not 
found
+     */
+    public Hyperlink getHyperlink()
+    {
+        return (Hyperlink)getPropertyValue(Property.HYPERLINK);
+    }
+
+    /**
+     * Assign a hyperlink to this cell
+     *
+     * @param link hyperlink associated with this cell
+     */
+    public void setHyperlink(Hyperlink link)
+    {
+        setProperty(Property.HYPERLINK,link);
+    }
+
+    /**
+     * Only valid for array formula cells
+     *
+     * @return range of the array formula group that the cell belongs to.
+     */
+//TODO: What is this?
+    public CellRangeAddress getArrayFormulaRange()
+    {
+        return null;
+    }
+
+    /**
+     * @return <code>true</code> if this cell is part of group of cells having 
a common array formula.
+     */
+//TODO: What is this?
+    public boolean isPartOfArrayFormulaGroup()
+    {
+        return false;
+    }
+//end of interface implementation
+
+    void removeProperty(int type)
+    {
+        Property current=_firstProperty;
+        Property previous=null;
+        while(current!=null&&current.getType()!=type)
+        {
+            previous=current;
+            current=current._next;
+        }
+        if(current!=null)
+        {
+            if(previous!=null)
+            {
+                previous._next=current._next;
+            }
+            else
+            {
+                _firstProperty=current._next;
+            }
+        }
+    }
+    void setProperty(int type,Object value)
+    {
+        Property current=_firstProperty;
+        Property previous=null;
+        while(current!=null&&current.getType()!=type)
+        {
+            previous=current;
+            current=current._next;
+        }
+        if(current!=null)
+        {
+            current.setValue(value);
+        }
+        else
+        {
+            switch(type)
+            {
+                case Property.COMMENT:
+                {
+                    current=new CommentProperty(value);
+                    break;
+                }
+                case Property.HYPERLINK:
+                {
+                    current=new HyperlinkProperty(value);
+                    break;
+                }
+            }
+            if(previous!=null)
+            {
+                previous._next=current;
+            }
+            else
+            {
+                _firstProperty=current;
+            }
+        }
+    }
+    Object getPropertyValue(int type)
+    {
+        return getPropertyValue(type,null);
+    }
+    Object getPropertyValue(int type,String defaultValue)
+    {
+        Property current=_firstProperty;
+        while(current!=null&&current.getType()!=type) current=current._next;
+        return current==null?defaultValue:current.getValue();
+    }
+    void ensurePlainStringType()
+    {
+        if(_value.getType()!=CELL_TYPE_STRING
+           ||((StringValue)_value).isRichText())
+            _value=new PlainStringValue();
+    }
+    void ensureRichTextStringType()
+    {
+        if(_value.getType()!=CELL_TYPE_STRING
+           ||!((StringValue)_value).isRichText())
+            _value=new RichTextValue();
+    }
+    void ensureType(int type)
+    {
+        if(_value.getType()!=type)
+            setType(type);
+    }
+    void ensureFormulaType(int type)
+    {
+        if(_value.getType()!=CELL_TYPE_FORMULA
+           ||((FormulaValue)_value).getFormulaType()!=type)
+            setFormulaType(type);
+    }
+    void ensureTypeOrFormulaType(int type)
+    {
+        assert type==CELL_TYPE_NUMERIC||
+               type==CELL_TYPE_STRING||
+               type==CELL_TYPE_BOOLEAN||
+               type==CELL_TYPE_ERROR;
+        if(_value.getType()==type)
+        {
+            if(type==CELL_TYPE_STRING&&((StringValue)_value).isRichText())
+                setType(CELL_TYPE_STRING);
+            return;
+        }
+        if(_value.getType()==CELL_TYPE_FORMULA)
+        {
+            if(((FormulaValue)_value).getFormulaType()==type)
+                return;
+            setFormulaType(type); // once a formula, always a formula
+            return;
+        }
+        setType(type);
+    }
+    void setType(int type)
+    {
+        switch(type)
+        {
+            case CELL_TYPE_NUMERIC:
+            {
+                _value=new NumericValue();
+                break;
+            }
+            case CELL_TYPE_STRING:
+            {
+                _value=new PlainStringValue();
+                break;
+            }
+            case CELL_TYPE_FORMULA:
+            {
+                _value=new NumericFormulaValue();
+                break;
+            }
+            case CELL_TYPE_BLANK:
+            {
+                _value=new BlankValue();
+                break;
+            }
+            case CELL_TYPE_BOOLEAN:
+            {
+                _value=new BooleanValue();
+                break;
+            }
+            case CELL_TYPE_ERROR:
+            {
+                _value=new ErrorValue();
+                break;
+            }
+            default:
+            {
+                throw new IllegalArgumentException("Illegal type " + type);
+            }
+        }
+    }
+    void setFormulaType(int type)
+    {
+        switch(type)
+        {
+            case CELL_TYPE_NUMERIC:
+            {
+                _value=new NumericFormulaValue();
+                break;
+            }
+            case CELL_TYPE_STRING:
+            {
+                _value=new StringFormulaValue();
+                break;
+            }
+            case CELL_TYPE_BOOLEAN:
+            {
+                _value=new BooleanFormulaValue();
+                break;
+            }
+            case CELL_TYPE_ERROR:
+            {
+                _value=new ErrorFormulaValue();
+                break;
+            }
+            default:
+            {
+                throw new IllegalArgumentException("Illegal type " + type);
+            }
+        }
+    }
+//TODO: implement this correctly
+    int computeTypeFromFormula(String formula)
+    {
+        return CELL_TYPE_NUMERIC;
+    }
+//COPIED FROM 
https://svn.apache.org/repos/asf/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
 since the functions are declared private there
+    /**
+     * Used to help format error messages
+     */
+    private static RuntimeException typeMismatch(int expectedTypeCode, int 
actualTypeCode, boolean isFormulaCell) {
+        String msg = "Cannot get a "
+            + getCellTypeName(expectedTypeCode) + " value from a "
+            + getCellTypeName(actualTypeCode) + " " + (isFormulaCell ? 
"formula " : "") + "cell";
+        return new IllegalStateException(msg);
+    }
+/**
+     * Used to help format error messages
+     */
+    private static String getCellTypeName(int cellTypeCode) {
+        switch (cellTypeCode) {
+            case CELL_TYPE_BLANK:   return "blank";
+            case CELL_TYPE_STRING:  return "text";
+            case CELL_TYPE_BOOLEAN: return "boolean";
+            case CELL_TYPE_ERROR:   return "error";
+            case CELL_TYPE_NUMERIC: return "numeric";
+            case CELL_TYPE_FORMULA: return "formula";
+        }
+        return "#unknown cell type (" + cellTypeCode + ")#";
+    }
+//END OF COPIED CODE
+
+    static abstract class Property
+    {
+        final static int COMMENT=1;
+        final static int HYPERLINK=2;
+        Object _value;
+        Property _next;
+        public Property(Object value)
+        {
+            _value=value;
+        }
+        abstract int getType();
+        void setValue(Object value)
+        {
+            _value=value;
+        }
+        Object getValue()
+        {
+            return _value;
+        }
+    }
+    static class CommentProperty extends Property
+    {
+        public CommentProperty(Object value)
+        {
+            super(value);
+        }
+        public int getType()
+        {
+            return COMMENT;
+        }
+    }
+    static class HyperlinkProperty extends Property
+    {
+        public HyperlinkProperty(Object value)
+        {
+            super(value);
+        }
+        public int getType()
+        {
+            return HYPERLINK;
+        }
+    }
+    interface Value
+    {
+        int getType();
+    }
+    static class NumericValue implements Value
+    {
+        double _value;
+        public int getType()
+        {
+            return CELL_TYPE_NUMERIC;
+        }
+        void setValue(double value)
+        {
+            _value=value;
+        }
+        double getValue()
+        {
+            return _value;
+        }
+    }
+    static abstract class StringValue implements Value
+    {
+        public int getType()
+        {
+            return CELL_TYPE_STRING;
+        }
+//We cannot introduce a new type CELL_TYPE_RICH_TEXT because the types are 
public so we have to make rich text as a type of string
+        abstract boolean isRichText(); // using the POI style which seems to 
avoid "instanceof".
+    }
+    static class PlainStringValue extends StringValue
+    {
+        String _value;
+        void setValue(String value)
+        {
+            _value=value;
+        }
+        String getValue()
+        {
+            return _value;
+        }
+        boolean isRichText()
+        {
+            return false;
+        }
+    }
+    static class RichTextValue implements Value
+    {
+        RichTextString _value;
+        public int getType()
+        {
+            return CELL_TYPE_STRING;
+        }
+        void setValue(RichTextString value)
+        {
+            _value=value;
+        }
+        RichTextString getValue()
+        {
+            return _value;
+        }
+        boolean isRichText()
+        {
+            return true;
+        }
+    }
+    static abstract class FormulaValue implements Value
+    {
+        String _value;
+        public int getType()
+        {
+            return CELL_TYPE_FORMULA;
+        }
+        void setValue(String value)
+        {
+            _value=value;
+        }
+        String getValue()
+        {
+            return _value;
+        }
+        abstract int getFormulaType();
+    }
+    static class NumericFormulaValue extends FormulaValue
+    {
+        double _preEvaluatedValue;
+        int getFormulaType()
+        {
+            return CELL_TYPE_NUMERIC;
+        }
+        void setPreEvaluatedValue(double value)
+        {
+            _preEvaluatedValue=value;
+        }
+        double getPreEvaluatedValue()
+        {
+            return _preEvaluatedValue;
+        }
+    }
+    static class StringFormulaValue extends FormulaValue
+    {
+        String _preEvaluatedValue;
+        int getFormulaType()
+        {
+            return CELL_TYPE_STRING;
+        }
+        void setPreEvaluatedValue(String value)
+        {
+            _preEvaluatedValue=value;
+        }
+        String getPreEvaluatedValue()
+        {
+            return _preEvaluatedValue;
+        }
+    }
+    static class BooleanFormulaValue extends FormulaValue
+    {
+        boolean _preEvaluatedValue;
+        int getFormulaType()
+        {
+            return CELL_TYPE_BOOLEAN;
+        }
+        void setPreEvaluatedValue(boolean value)
+        {
+            _preEvaluatedValue=value;
+        }
+        boolean getPreEvaluatedValue()
+        {
+            return _preEvaluatedValue;
+        }
+    }
+    static class ErrorFormulaValue extends FormulaValue
+    {
+        byte _preEvaluatedValue;
+        int getFormulaType()
+        {
+            return CELL_TYPE_ERROR;
+        }
+        void setPreEvaluatedValue(byte value)
+        {
+            _preEvaluatedValue=value;
+        }
+        byte getPreEvaluatedValue()
+        {
+            return _preEvaluatedValue;
+        }
+    }
+    static class BlankValue implements Value
+    {
+        public int getType()
+        {
+            return CELL_TYPE_BLANK;
+        }
+    }
+    static class BooleanValue implements Value
+    {
+        boolean _value;
+        public int getType()
+        {
+            return CELL_TYPE_BOOLEAN;
+        }
+        void setValue(boolean value)
+        {
+            _value=value;
+        }
+        boolean getValue()
+        {
+            return _value;
+        }
+    }
+    static class ErrorValue implements Value
+    {
+        byte _value;
+        public int getType()
+        {
+            return CELL_TYPE_ERROR;
+        }
+        void setValue(byte value)
+        {
+            _value=value;
+        }
+        byte getValue()
+        {
+            return _value;
+        }
+    }
+}

Added: poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java?rev=1104120&view=auto
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java (added)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java Tue 
May 17 10:46:35 2011
@@ -0,0 +1,388 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.xssf.streaming;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Streaming version of XSSFRow implementing the "BigGridDemo" strategy.
+ *
+ * @author Alex Geller, Four J's Development Tools
+*/
+public class SXSSFRow implements Row
+{
+    SXSSFSheet _sheet;
+    SXSSFCell[] _cells;
+    int _maxColumn=-1;
+    short _height=-1;
+//TODO: Need to set the correct default value for _zHeight
+    boolean _zHeight;
+
+    public SXSSFRow(SXSSFSheet sheet, int initialSize)
+    {
+        _sheet=sheet;
+        _cells=new SXSSFCell[initialSize];
+    }
+    public Iterator<Cell> allCellsIterator()
+    {
+        return new CellIterator();
+    }
+    public boolean hasCustomHeight()
+    {
+        return _height!=-1;
+    }
+//begin of interface implementation
+    public Iterator<Cell> iterator()
+    {
+        return new FilledCellIterator();
+    }
+
+    /**
+     * Use this to create new cells within the row and return it.
+     * <p>
+     * The cell that is returned is a {@link Cell#CELL_TYPE_BLANK}. The type 
can be changed
+     * either through calling <code>setCellValue</code> or 
<code>setCellType</code>.
+     *
+     * @param column - the column number this cell represents
+     * @return Cell a high level representation of the created cell.
+     * @throws IllegalArgumentException if columnIndex < 0 or greater than the 
maximum number of supported columns
+     * (255 for *.xls, 1048576 for *.xlsx)
+     */
+    public Cell createCell(int column)
+    {
+        return createCell(column,Cell.CELL_TYPE_BLANK);
+    }
+
+    /**
+     * Use this to create new cells within the row and return it.
+     * <p>
+     * The cell that is returned is a {@link Cell#CELL_TYPE_BLANK}. The type 
can be changed
+     * either through calling setCellValue or setCellType.
+     *
+     * @param column - the column number this cell represents
+     * @return Cell a high level representation of the created cell.
+     * @throws IllegalArgumentException if columnIndex < 0 or greate than a 
maximum number of supported columns
+     * (255 for *.xls, 1048576 for *.xlsx)
+     */
+    public Cell createCell(int column, int type)
+    {
+        if(column>=_cells.length)
+        {
+            SXSSFCell[] newCells=new 
SXSSFCell[Math.max(column+1,_cells.length*2)];
+            System.arraycopy(_cells,0,newCells,0,_cells.length);
+            _cells=newCells;
+        }
+        _cells[column]=new SXSSFCell(this,type);
+        if(column>_maxColumn) _maxColumn=column;
+        return _cells[column];
+    }
+
+    /**
+     * Remove the Cell from this row.
+     *
+     * @param cell the cell to remove
+     */
+    public void removeCell(Cell cell)
+    {
+        int index=getCellIndex(cell);
+        if(index>=0)
+        {
+            _cells[index]=null;
+            while(_maxColumn>=0&&_cells[_maxColumn]==null) _maxColumn--;
+        }
+    }
+
+    int getCellIndex(Cell cell)
+    {
+        for(int i=0;i<=_maxColumn;i++)
+        {
+            if(_cells[i]==cell) return i;
+        }
+        return -1;
+    }
+
+    /**
+     * Set the row number of this row.
+     *
+     * @param rowNum  the row number (0-based)
+     * @throws IllegalArgumentException if rowNum < 0
+     */
+    public void setRowNum(int rowNum)
+    {
+        _sheet.changeRowNum(this,rowNum);
+    }
+
+    /**
+     * Get row number this row represents
+     *
+     * @return the row number (0 based)
+     */
+    public int getRowNum()
+    {
+        return _sheet.getRowNum(this);
+    }
+
+    /**
+     * Get the cell representing a given column (logical cell) 0-based.  If you
+     * ask for a cell that is not defined....you get a null.
+     *
+     * @param cellnum  0 based column number
+     * @return Cell representing that column or null if undefined.
+     * @see #getCell(int, org.apache.poi.ss.usermodel.Row.MissingCellPolicy)
+     */
+    public Cell getCell(int cellnum)
+    {
+        return cellnum>_maxColumn?null:_cells[cellnum];
+    }
+
+    /**
+     * Returns the cell at the given (0 based) index, with the specified 
{@link org.apache.poi.ss.usermodel.Row.MissingCellPolicy}
+     *
+     * @return the cell at the given (0 based) index
+     * @throws IllegalArgumentException if cellnum < 0 or the specified 
MissingCellPolicy is invalid
+     * @see Row#RETURN_NULL_AND_BLANK
+     * @see Row#RETURN_BLANK_AS_NULL
+     * @see Row#CREATE_NULL_AS_BLANK
+     */
+    public Cell getCell(int cellnum, MissingCellPolicy policy)
+    {
+        assert false;
+        Cell cell = getCell(cellnum);
+        if(policy == RETURN_NULL_AND_BLANK)
+        {
+            return cell;
+        }
+        if(policy == RETURN_BLANK_AS_NULL)
+        {
+            if(cell == null) return cell;
+            if(cell.getCellType() == Cell.CELL_TYPE_BLANK)
+            {
+                return null;
+            }
+            return cell;
+        }
+        if(policy == CREATE_NULL_AS_BLANK)
+        {
+            if(cell == null)
+            {
+                return createCell(cellnum, Cell.CELL_TYPE_BLANK);
+            }
+            return cell;
+        }
+        throw new IllegalArgumentException("Illegal policy " + policy + " (" + 
policy.id + ")");
+    }
+
+    /**
+     * Get the number of the first cell contained in this row.
+     *
+     * @return short representing the first logical cell in the row,
+     *  or -1 if the row does not contain any cells.
+     */
+    public short getFirstCellNum()
+    {
+        for(int i=0;i<=_maxColumn;i++)
+            if(_cells[i]!=null) return (short)i;
+        return -1;
+    }
+
+    /**
+     * Gets the index of the last cell contained in this row <b>PLUS ONE</b>. 
The result also
+     * happens to be the 1-based column number of the last cell.  This value 
can be used as a
+     * standard upper bound when iterating over cells:
+     * <pre>
+     * short minColIx = row.getFirstCellNum();
+     * short maxColIx = row.getLastCellNum();
+     * for(short colIx=minColIx; colIx&lt;maxColIx; colIx++) {
+     *   Cell cell = row.getCell(colIx);
+     *   if(cell == null) {
+     *     continue;
+     *   }
+     *   //... do something with cell
+     * }
+     * </pre>
+     *
+     * @return short representing the last logical cell in the row <b>PLUS 
ONE</b>,
+     *   or -1 if the row does not contain any cells.
+     */
+    public short getLastCellNum()
+    {
+        return (short)(_maxColumn+1);
+    }
+
+    /**
+     * Gets the number of defined cells (NOT number of cells in the actual 
row!).
+     * That is to say if only columns 0,4,5 have values then there would be 3.
+     *
+     * @return int representing the number of defined cells in the row.
+     */
+    public int getPhysicalNumberOfCells()
+    {
+        int count=0;
+        for(int i=0;i<=_maxColumn;i++)
+        {
+            if(_cells[i]!=null) count++;
+        }
+        return count;
+    }
+
+    /**
+     * Set the row's height or set to ff (-1) for undefined/default-height.  
Set the height in "twips" or
+     * 1/20th of a point.
+     *
+     * @param height  rowheight or 0xff for undefined (use sheet default)
+     */
+    public void setHeight(short height)
+    {
+        _height=height;
+    }
+
+    /**
+     * Set whether or not to display this row with 0 height
+     *
+     * @param zHeight  height is zero or not.
+     */
+    public void setZeroHeight(boolean zHeight)
+    {
+        _zHeight=zHeight;
+    }
+
+    /**
+     * Get whether or not to display this row with 0 height
+     *
+     * @return - zHeight height is zero or not.
+     */
+    public boolean getZeroHeight()
+    {
+        return _zHeight;
+    }
+
+    /**
+     * Set the row's height in points.
+     *
+     * @param height the height in points. <code>-1</code>  resets to the 
default height
+     */
+    public void setHeightInPoints(float height)
+    {
+        if(height==-1)
+            _height=-1;
+        else
+            _height=(short)(height*20);
+    }
+
+    /**
+     * Get the row's height measured in twips (1/20th of a point). If the 
height is not set, the default worksheet value is returned,
+     * See {@link Sheet#getDefaultRowHeightInPoints()}
+     *
+     * @return row height measured in twips (1/20th of a point)
+     */
+    public short getHeight()
+    {
+        return 
(short)(_height==-1?getSheet().getDefaultRowHeightInPoints()*20:_height);
+    }
+
+    /**
+     * Returns row height measured in point size. If the height is not set, 
the default worksheet value is returned,
+     * See {@link Sheet#getDefaultRowHeightInPoints()}
+     *
+     * @return row height measured in point size
+     * @see Sheet#getDefaultRowHeightInPoints()
+     */
+    public float getHeightInPoints()
+    {
+        return 
(float)(_height==-1?getSheet().getDefaultRowHeightInPoints():(float)_height/20.0);
+    }
+
+    /**
+     * @return Cell iterator of the physically defined cells.  Note element 4 
may
+     * actually be row cell depending on how many are defined!
+     */
+    public Iterator<Cell> cellIterator()
+    {
+        return iterator();
+    }
+
+    /**
+     * Returns the Sheet this row belongs to
+     *
+     * @return the Sheet that owns this row
+     */
+    public Sheet getSheet()
+    {
+        return _sheet;
+    }
+//end of interface implementation
+
+
+/** returns all filled cells (created via Row.createCell())*/
+    public class FilledCellIterator implements Iterator<Cell>
+    {
+        int pos=0;
+        public boolean hasNext()
+        {
+            return pos <= _maxColumn;
+        }
+        void advanceToNext()
+        {
+            pos++;
+            while(pos<=_maxColumn&&_cells[pos]==null) pos++;
+        }
+        public Cell next() throws NoSuchElementException
+        {
+            if (hasNext())
+            {
+                Cell retval=_cells[pos];
+                advanceToNext();
+                return retval;
+            }
+            else
+            {
+                throw new NoSuchElementException();
+            }
+        }
+        public void remove()
+        {
+            throw new UnsupportedOperationException();
+        }
+    }
+/** returns all cells including empty cells in which case "null" is returned*/
+    public class CellIterator implements Iterator<Cell>
+    {
+        int pos=0;
+        public boolean hasNext()
+        {
+            return pos <= _maxColumn;
+        }
+        public Cell next() throws NoSuchElementException
+        {
+            if (hasNext())
+                return _cells[pos++];
+            else
+                throw new NoSuchElementException();
+        }
+        public void remove()
+        {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
+



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to