diff --git a/src/examples/src/org/apache/poi/xssf/streaming/examples/Outlining.java b/src/examples/src/org/apache/poi/xssf/streaming/examples/Outlining.java new file mode 100644 index 000000000..03af09ddd --- /dev/null +++ b/src/examples/src/org/apache/poi/xssf/streaming/examples/Outlining.java @@ -0,0 +1,51 @@ +/* ==================================================================== + 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.examples; + +import java.io.FileOutputStream; + +import org.apache.poi.xssf.streaming.SXSSFSheet; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; + +public class Outlining { + + public static void main(String[] args) throws Exception { + Outlining o = new Outlining(); + o.collapseRow(); + } + + private void collapseRow() throws Exception { + SXSSFWorkbook wb2 = new SXSSFWorkbook(100); + SXSSFSheet sheet2 = (SXSSFSheet) wb2.createSheet("new sheet"); + + int rowCount = 20; + for (int i = 0; i < rowCount; i++) { + sheet2.createRow(i); + } + + sheet2.groupRow(4, 9); + sheet2.groupRow(11, 19); + + sheet2.setRowGroupCollapsed(4, true); + + FileOutputStream fileOut = new FileOutputStream("outlining_collapsed.xlsx"); + wb2.write(fileOut); + fileOut.close(); + wb2.dispose(); + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java index a762de822..9ace1475a 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java @@ -40,7 +40,10 @@ public class SXSSFRow implements Row short _height=-1; boolean _zHeight = false; int _outlineLevel = 0; // Outlining level of the row, when outlining is on - + // use Boolean to have a tri-state for on/off/undefined + Boolean _hidden; + Boolean _collapsed; + public SXSSFRow(SXSSFSheet sheet, int initialSize) { _sheet=sheet; @@ -61,7 +64,22 @@ public class SXSSFRow implements Row void setOutlineLevel(int level){ _outlineLevel = level; } + + public Boolean getHidden() { + return _hidden; + } + public void setHidden(Boolean hidden) { + this._hidden = hidden; + } + + public Boolean getCollapsed() { + return _collapsed; + } + + public void setCollapsed(Boolean collapsed) { + this._collapsed = collapsed; + } //begin of interface implementation public Iterator iterator() { diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java index b92adddc7..080d31fc3 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java @@ -1143,8 +1143,65 @@ public class SXSSFSheet implements Sheet, Cloneable */ public void setRowGroupCollapsed(int row, boolean collapse) { - //_sh.setRowGroupCollapsed(row, collapse); - throw new RuntimeException("Not Implemented"); + if (collapse) { + collapseRow(row); + } else { + //expandRow(rowIndex); + throw new RuntimeException("Not Implemented"); + } + } + + /** + * @param rowIndex the zero based row index to collapse + */ + private void collapseRow(int rowIndex) { + SXSSFRow row = (SXSSFRow) getRow(rowIndex); + if(row == null) { + throw new IllegalArgumentException("Invalid row number("+ rowIndex + "). Row does not exist."); + } else { + int startRow = findStartOfRowOutlineGroup(rowIndex); + + // Hide all the columns until the end of the group + int lastRow = writeHidden(row, startRow, true); + SXSSFRow lastRowObj = (SXSSFRow) getRow(lastRow); + if (lastRowObj != null) { + lastRowObj.setCollapsed(true); + } else { + SXSSFRow newRow = (SXSSFRow) createRow(lastRow); + newRow.setCollapsed(true); + } + } + } + + /** + * @param rowIndex the zero based row index to find from + */ + private int findStartOfRowOutlineGroup(int rowIndex) { + // Find the start of the group. + Row row = getRow(rowIndex); + int level = ((SXSSFRow) row).getOutlineLevel(); + if(level == 0) { + throw new IllegalArgumentException("Outline level is zero for the row (" + rowIndex + ")."); + } + int currentRow = rowIndex; + while (getRow(currentRow) != null) { + if (((SXSSFRow) getRow(currentRow)).getOutlineLevel() < level) + return currentRow + 1; + currentRow--; + } + return currentRow + 1; + } + + private int writeHidden(SXSSFRow xRow, int rowIndex, boolean hidden) { + int level = xRow.getOutlineLevel(); + SXSSFRow currRow = (SXSSFRow) getRow(rowIndex); + + while (currRow != null && currRow.getOutlineLevel() >= level) { + currRow.setHidden(hidden); + rowIndex++; + currRow = (SXSSFRow) getRow(rowIndex); + } + return rowIndex; } /** diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SheetDataWriter.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SheetDataWriter.java index e20522475..1036c2280 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SheetDataWriter.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SheetDataWriter.java @@ -19,16 +19,19 @@ package org.apache.poi.xssf.streaming; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.util.Iterator; + import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.FormulaError; import org.apache.poi.ss.util.CellReference; -import org.apache.xmlbeans.XmlCursor; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STXstring; - -import javax.xml.namespace.QName; -import java.io.*; -import java.util.Iterator; /** * Initially copied from BigGridDemo "SpreadsheetWriter". @@ -110,6 +113,7 @@ public class SheetDataWriter { return _numberLastFlushedRow; } + @Override protected void finalize() throws Throwable { _fd.delete(); } @@ -148,6 +152,13 @@ public class SheetDataWriter { if (row.getOutlineLevel() != 0) { _out.write(" outlineLevel=\"" + row.getOutlineLevel() + "\""); } + if(row.getHidden() != null) { + _out.write(" hidden=\"" + (row.getHidden() ? "1" : "0") + "\""); + } + if(row.getCollapsed() != null) { + _out.write(" collapsed=\"" + (row.getCollapsed() ? "1" : "0") + "\""); + } + _out.write(">\n"); this._rownum = rownum; _rowContainedNullCells = false; diff --git a/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestOutlining.java b/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestOutlining.java new file mode 100644 index 000000000..e616402af --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestOutlining.java @@ -0,0 +1,102 @@ +/* + * ==================================================================== + * 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 junit.framework.TestCase; + +public final class TestOutlining extends TestCase { + public void testSetRowGroupCollapsed() throws Exception { + + SXSSFWorkbook wb2 = new SXSSFWorkbook(100); + wb2.setCompressTempFiles(true); + SXSSFSheet sheet2 = (SXSSFSheet) wb2.createSheet("new sheet"); + + int rowCount = 20; + for (int i = 0; i < rowCount; i++) { + sheet2.createRow(i); + } + + sheet2.groupRow(4, 9); + sheet2.groupRow(11, 19); + + sheet2.setRowGroupCollapsed(4, true); + + SXSSFRow r = (SXSSFRow) sheet2.getRow(8); + assertTrue(r.getHidden()); + r = (SXSSFRow) sheet2.getRow(10); + assertTrue(r.getCollapsed()); + r = (SXSSFRow) sheet2.getRow(12); + assertNull(r.getHidden()); + wb2.dispose(); + } + + public void testSetRowGroupCollapsedError() throws Exception { + + SXSSFWorkbook wb2 = new SXSSFWorkbook(100); + wb2.setCompressTempFiles(true); + SXSSFSheet sheet2 = (SXSSFSheet) wb2.createSheet("new sheet"); + + int rowCount = 20; + for (int i = 0; i < rowCount; i++) { + sheet2.createRow(i); + } + + sheet2.groupRow(4, 9); + sheet2.groupRow(11, 19); + + try { + sheet2.setRowGroupCollapsed(3, true); + fail("Should fail with an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("row (3)")); + } + + try { + sheet2.setRowGroupCollapsed(10, true); + fail("Should fail with an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("row (10)")); + } + + try { + sheet2.setRowGroupCollapsed(0, true); + fail("Should fail with an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("row (0)")); + } + + try { + sheet2.setRowGroupCollapsed(20, true); + fail("Should fail with an exception"); + } catch (IllegalArgumentException e) { + assertTrue("Had: " + e.getMessage(), + e.getMessage().contains("Row does not exist")); + } + + SXSSFRow r = (SXSSFRow) sheet2.getRow(8); + assertNotNull(r); + assertNull(r.getHidden()); + r = (SXSSFRow) sheet2.getRow(10); + assertNull(r.getCollapsed()); + r = (SXSSFRow) sheet2.getRow(12); + assertNull(r.getHidden()); + wb2.dispose(); + } +}