]> source.dussan.org Git - poi.git/commitdiff
Bugzilla 53500 - Getter for repeating rows and columns
authorYegor Kozlov <yegor@apache.org>
Sat, 21 Jul 2012 10:33:00 +0000 (10:33 +0000)
committerYegor Kozlov <yegor@apache.org>
Sat, 21 Jul 2012 10:33:00 +0000 (10:33 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1364061 13f79535-47bb-0310-9956-ffa450edef68

12 files changed:
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
src/java/org/apache/poi/ss/usermodel/Sheet.java
src/java/org/apache/poi/ss/util/CellRangeAddress.java
src/java/org/apache/poi/ss/util/CellRangeAddressBase.java
src/java/org/apache/poi/ss/util/CellReference.java
src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
src/testcases/org/apache/poi/ss/usermodel/BaseTestWorkbook.java
test-data/spreadsheet/RepeatingRowsCols.xls [new file with mode: 0644]
test-data/spreadsheet/RepeatingRowsCols.xlsx [new file with mode: 0644]

index 092abdbfc6948a93d9ce6aa1f91230f1267c2c99..4d84732c4d2df8583e1c026d09859b55d9dc90b1 100644 (file)
@@ -34,6 +34,7 @@
 
     <changes>
         <release version="3.9-beta1" date="2012-??-??">
+          <action dev="poi-developers" type="add">53500 - Getter for repeating rows and columns</action>
           <action dev="poi-developers" type="fix">53369 - Fixed tests failing on JDK 1.7</action>
           <action dev="poi-developers" type="fix">53360 - Fixed SXSSF to correctly write text before escaped Unicode control character</action>
           <action dev="poi-developers" type="add">Change HSMF Types to have full data on ID, Name and Length, rather than just being a simple ID</action>
index fe332eb83e5b0766f3caf14e710d7be0884423ec..9ca6a9552a6d02cd2ff394055ae3e42c725adfd5 100644 (file)
@@ -2003,4 +2003,71 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
         return new HSSFAutoFilter(this);
     }
 
+
+  @Override
+  public CellRangeAddress getRepeatingRows() {
+    return getRepeatingRowsOrColums(true);
+  }
+
+
+  @Override
+  public CellRangeAddress getRepeatingColumns() {
+    return getRepeatingRowsOrColums(false);
+  }
+
+  
+  private CellRangeAddress getRepeatingRowsOrColums(boolean rows) {
+    NameRecord rec = getBuiltinNameRecord(NameRecord.BUILTIN_PRINT_TITLE);
+    if (rec == null) {
+      return null;
+    }
+    
+    Ptg[] nameDefinition = rec.getNameDefinition();
+    if (rec.getNameDefinition() == null) {
+      return null;
+    }
+    
+    int maxRowIndex = SpreadsheetVersion.EXCEL97.getLastRowIndex();
+    int maxColIndex = SpreadsheetVersion.EXCEL97.getLastColumnIndex();
+    
+    for (Ptg ptg :nameDefinition) {
+      
+      if (ptg instanceof Area3DPtg) {
+        Area3DPtg areaPtg = (Area3DPtg) ptg;
+        
+        if (areaPtg.getFirstColumn() == 0 
+            && areaPtg.getLastColumn() == maxColIndex) {
+          if (rows) {
+            CellRangeAddress rowRange = new CellRangeAddress(
+                areaPtg.getFirstRow(), areaPtg.getLastRow(), -1, -1);
+            return rowRange;
+          }
+        } else if (areaPtg.getFirstRow() == 0 
+            && areaPtg.getLastRow() == maxRowIndex) {
+          if (!rows) {
+            CellRangeAddress columnRange = new CellRangeAddress(-1, -1, 
+                areaPtg.getFirstColumn(), areaPtg.getLastColumn());
+            return columnRange;
+          }
+        }
+        
+      }
+      
+    }
+    
+    return null;
+  }
+
+
+  private NameRecord getBuiltinNameRecord(byte builtinCode) {
+    int sheetIndex = _workbook.getSheetIndex(this);
+    int recIndex = 
+      _workbook.findExistingBuiltinNameRecordIdx(sheetIndex, builtinCode);
+    if (recIndex == -1) {
+      return null;
+    }
+    return _workbook.getNameRecord(recIndex);
+  }
+
+  
 }
index afd0bce10fba20367e99f296c50ced545e62d994..a92f4bbff6f49ac2182c3758e60a86220d934345 100644 (file)
@@ -76,7 +76,7 @@ import org.apache.commons.codec.digest.DigestUtils;
 public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook {
     private static final Pattern COMMA_PATTERN = Pattern.compile(",");
     private static final int MAX_ROW = 0xFFFF;
-    private static final short MAX_COLUMN = (short)0x00FF;
+    private static final int MAX_COLUMN = (short)0x00FF;
 
     /**
      * The maximum number of cell styles in a .xls workbook.
@@ -1034,7 +1034,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
     }
 
 
-    private int findExistingBuiltinNameRecordIdx(int sheetIndex, byte builtinCode) {
+    int findExistingBuiltinNameRecordIdx(int sheetIndex, byte builtinCode) {
         for(int defNameIndex =0; defNameIndex<names.size(); defNameIndex++) {
             NameRecord r = workbook.getNameRecord(defNameIndex);
             if (r == null) {
index 5be4f1f5e63915be1a6fe245e5343949ae5470eb..4ef8842609aa60534872ae5c7bbc2bae52e49420 100644 (file)
@@ -927,4 +927,48 @@ public interface Sheet extends Iterable<Row> {
      */
     SheetConditionalFormatting getSheetConditionalFormatting();
 
+
+    /**
+     * Gets the repeating rows used when printing the sheet, as found in 
+     * File->PageSetup->Sheet.
+     * <p/>
+     * Repeating rows cover a range of contiguous rows, e.g.:
+     * <pre>
+     * Sheet1!$1:$1
+     * Sheet2!$5:$8
+     * </pre>
+     * The {@link CellRangeAddress} returned contains a column part which spans 
+     * all columns, and a row part which specifies the contiguous range of 
+     * repeating rows.
+     * <p/>
+     * If the Sheet does not have any repeating rows defined, null is returned.
+     * 
+     * @return an {@link CellRangeAddress} containing the repeating rows for the 
+     *         Sheet, or null.
+     */
+    CellRangeAddress getRepeatingRows();
+
+
+    /**
+     * Gets the repeating columns used when printing the sheet, as found in 
+     * File->PageSetup->Sheet.
+     * <p/>
+     * Repeating columns cover a range of contiguous columns, e.g.:
+     * <pre>
+     * Sheet1!$A:$A
+     * Sheet2!$C:$F
+     * </pre>
+     * The {@link CellRangeAddress} returned contains a row part which spans all 
+     * rows, and a column part which specifies the contiguous range of 
+     * repeating columns.
+     * <p/>
+     * If the Sheet does not have any repeating columns defined, null is 
+     * returned.
+     * 
+     * @return an {@link CellRangeAddress} containing the repeating columns for the 
+     *         Sheet, or null.
+     */
+    CellRangeAddress getRepeatingColumns();
+
+
 }
index 4a44a6c8a5c771b4898ad9967bfab372acd8957c..418161d752d3d743d467193d04a246a10e784789 100644 (file)
@@ -100,7 +100,10 @@ public class CellRangeAddress extends CellRangeAddressBase {
         sb.append(cellRefFrom.formatAsString());
 
         //for a single-cell reference return A1 instead of A1:A1
-        if(!cellRefFrom.equals(cellRefTo)){
+        //for full-column ranges or full-row ranges return A:A instead of A,
+        //and 1:1 instead of 1         
+        if(!cellRefFrom.equals(cellRefTo)
+            || isFullColumnRange() || isFullRowRange()){
             sb.append(':');
             sb.append(cellRefTo.formatAsString());
         }
index e8d9c9100a216e1aee53edd7ef19418e4e65164b..12aaa6f6292743e119e18015278a991bb49c389b 100644 (file)
@@ -76,11 +76,13 @@ public abstract class CellRangeAddressBase {
 
        //TODO use the correct SpreadsheetVersion
        public final boolean isFullColumnRange() {
-               return _firstRow == 0 && _lastRow == SpreadsheetVersion.EXCEL97.getLastRowIndex();
+               return (_firstRow == 0 && _lastRow == SpreadsheetVersion.EXCEL97.getLastRowIndex())
+                 || (_firstRow == -1 && _lastRow == -1);
        }
        //TODO use the correct SpreadsheetVersion
        public final boolean isFullRowRange() {
-               return _firstCol == 0 && _lastCol == SpreadsheetVersion.EXCEL97.getLastColumnIndex();
+               return (_firstCol == 0 && _lastCol == SpreadsheetVersion.EXCEL97.getLastColumnIndex())
+                 || (_firstCol == -1 && _lastCol == -1);
        }
 
        /**
index 12120b748987a96fb33b74d552704b20d2531fd4..f7c37e30052f072d32f2d19793b1938b517be937 100644 (file)
@@ -91,25 +91,28 @@ public class CellReference {
 
                String[] parts = separateRefParts(cellRef);
                _sheetName = parts[0];
+
                String colRef = parts[1];
-               if (colRef.length() < 1) {
-                       throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
-               }
-               _isColAbs = colRef.charAt(0) == '$';
+               _isColAbs = (colRef.length() > 0) && colRef.charAt(0) == '$';
                if (_isColAbs) {
-                       colRef=colRef.substring(1);
+                 colRef = colRef.substring(1);
+               }
+               if (colRef.length() == 0) {
+                 _colIndex = -1;
+               } else {
+                 _colIndex = convertColStringToIndex(colRef);
                }
-               _colIndex = convertColStringToIndex(colRef);
 
                String rowRef=parts[2];
-               if (rowRef.length() < 1) {
-                       throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
-               }
-               _isRowAbs = rowRef.charAt(0) == '$';
+    _isRowAbs = (rowRef.length() > 0) && rowRef.charAt(0) == '$';
                if (_isRowAbs) {
-                       rowRef=rowRef.substring(1);
+                 rowRef = rowRef.substring(1);
+               }
+               if (rowRef.length() == 0) {
+                 _rowIndex = -1;
+               } else {
+                 _rowIndex = Integer.parseInt(rowRef)-1; // -1 to convert 1-based to zero-based
                }
-               _rowIndex = Integer.parseInt(rowRef)-1; // -1 to convert 1-based to zero-based
        }
 
        public CellReference(int pRow, int pCol) {
@@ -482,14 +485,18 @@ public class CellReference {
         * Sheet name is not included.
         */
        /* package */ void appendCellReference(StringBuffer sb) {
-               if(_isColAbs) {
-                       sb.append(ABSOLUTE_REFERENCE_MARKER);
-               }
-               sb.append( convertNumToColString(_colIndex));
-               if(_isRowAbs) {
-                       sb.append(ABSOLUTE_REFERENCE_MARKER);
+    if (_colIndex != -1) {
+      if(_isColAbs) {
+        sb.append(ABSOLUTE_REFERENCE_MARKER);
+      }
+      sb.append( convertNumToColString(_colIndex));
+    }
+               if (_rowIndex != -1) {
+                 if(_isRowAbs) {
+                   sb.append(ABSOLUTE_REFERENCE_MARKER);
+                 }
+                 sb.append(_rowIndex+1);
                }
-               sb.append(_rowIndex+1);
        }
 
        /**
index 5eb3338afb4ec2bb6a2858f54e7590b154fb35c6..9c6890f18469238ec0bf16324e1a3fc10e249304 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Map;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.ss.usermodel.*;
 
+import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.SheetUtil;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 
@@ -1263,7 +1264,20 @@ public class SXSSFSheet implements Sheet, Cloneable
     public SheetConditionalFormatting getSheetConditionalFormatting(){
         return _sh.getSheetConditionalFormatting();
     }
-
+    
+    
+    @Override
+    public CellRangeAddress getRepeatingRows() {
+      return _sh.getRepeatingRows();
+    }
+    
+    
+    @Override
+    public CellRangeAddress getRepeatingColumns() {
+      return _sh.getRepeatingColumns();
+    }
+    
+    
 //end of interface implementation
     /**
      * Specifies how many rows can be accessed at most via getRow().
index fbed5b06ddfba3beb167a3e62be1760c16cb0989..1da83b22d7b0d012a56bab55eb869674421d6b3d 100644 (file)
@@ -3185,4 +3185,54 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
         color.setIndexed(colorIndex);
         pr.setTabColor(color);
     }
+    
+    
+    @Override
+    public CellRangeAddress getRepeatingRows() {
+      return getRepeatingRowsOrColums(true);
+    }
+
+
+    @Override
+    public CellRangeAddress getRepeatingColumns() {
+      return getRepeatingRowsOrColums(false);
+    }
+
+
+    private CellRangeAddress getRepeatingRowsOrColums(boolean rows) {
+      int sheetIndex = getWorkbook().getSheetIndex(this);
+      XSSFName name = getWorkbook().getBuiltInName(
+          XSSFName.BUILTIN_PRINT_TITLE, sheetIndex);
+      if (name == null ) {
+        return null;
+      }
+      String refStr = name.getRefersToFormula();
+      if (refStr == null) {
+        return null;
+      }
+      String[] parts = refStr.split(",");
+      int maxRowIndex = SpreadsheetVersion.EXCEL2007.getLastRowIndex();
+      int maxColIndex = SpreadsheetVersion.EXCEL2007.getLastColumnIndex();
+      for (String part : parts) {
+        CellRangeAddress range = CellRangeAddress.valueOf(part);
+        if ((range.getFirstColumn() == 0 
+            && range.getLastColumn() == maxColIndex)
+            || (range.getFirstColumn() == -1 
+                && range.getLastColumn() == -1)) {
+          if (rows) {
+            return range;
+          }
+        } else if (range.getFirstRow() == 0 
+            && range.getLastRow() == maxRowIndex
+            || (range.getFirstRow() == -1 
+                && range.getLastRow() == -1)) {
+          if (!rows) {
+            return range;
+          }
+        }
+      }
+      return null;
+    }
+
+
 }
index 347eded97354229fc6c7c3c5c8f60f32a5b5ae18..fca31de5f78faf92569c0bfedc092d82da8e41a2 100644 (file)
@@ -359,14 +359,40 @@ public abstract class BaseTestWorkbook extends TestCase {
         assertSame(row, cell.getRow());
     }
 
+
+    public void testGetRepeatingRowsAnsColumns(){
+        Workbook wb = _testDataProvider.openSampleWorkbook(
+            "RepeatingRowsCols." 
+            + _testDataProvider.getStandardFileNameExtension());
+        
+        Sheet sheet0 = wb.getSheetAt(0);
+        assertNull(sheet0.getRepeatingRows());
+        assertNull(sheet0.getRepeatingColumns());
+
+        Sheet sheet1 = wb.getSheetAt(1);
+        assertEquals("1:1", sheet1.getRepeatingRows().formatAsString());
+        assertNull(sheet1.getRepeatingColumns());
+        
+        Sheet sheet2 = wb.getSheetAt(2);
+        assertNull(sheet2.getRepeatingRows());
+        assertEquals("A:A", sheet2.getRepeatingColumns().formatAsString());
+        
+        Sheet sheet3 = wb.getSheetAt(3);
+        assertEquals("2:3", sheet3.getRepeatingRows().formatAsString());
+        assertEquals("A:B", sheet3.getRepeatingColumns().formatAsString());
+    }
+
+
     public void testSetRepeatingRowsAnsColumns(){
         Workbook wb = _testDataProvider.createWorkbook();
         Sheet sheet1 = wb.createSheet();
         wb.setRepeatingRowsAndColumns(wb.getSheetIndex(sheet1), 0, 0, 0, 3);
+        assertEquals("1:4", sheet1.getRepeatingRows().formatAsString());
 
         //must handle sheets with quotas, see Bugzilla #47294
         Sheet sheet2 = wb.createSheet("My' Sheet");
         wb.setRepeatingRowsAndColumns(wb.getSheetIndex(sheet2), 0, 0, 0, 3);
+        assertEquals("1:4", sheet2.getRepeatingRows().formatAsString());
     }
 
     /**
diff --git a/test-data/spreadsheet/RepeatingRowsCols.xls b/test-data/spreadsheet/RepeatingRowsCols.xls
new file mode 100644 (file)
index 0000000..95f4e50
Binary files /dev/null and b/test-data/spreadsheet/RepeatingRowsCols.xls differ
diff --git a/test-data/spreadsheet/RepeatingRowsCols.xlsx b/test-data/spreadsheet/RepeatingRowsCols.xlsx
new file mode 100644 (file)
index 0000000..a8a5edf
Binary files /dev/null and b/test-data/spreadsheet/RepeatingRowsCols.xlsx differ