]> source.dussan.org Git - poi.git/commitdiff
applied patch #46003 by Gisella Bronzetti
authorYegor Kozlov <yegor@apache.org>
Fri, 17 Oct 2008 18:43:37 +0000 (18:43 +0000)
committerYegor Kozlov <yegor@apache.org>
Fri, 17 Oct 2008 18:43:37 +0000 (18:43 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@705701 13f79535-47bb-0310-9956-ffa450edef68

src/examples/src/org/apache/poi/xssf/usermodel/examples/SetPrintArea.java [new file with mode: 0755]
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java

diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/SetPrintArea.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/SetPrintArea.java
new file mode 100755 (executable)
index 0000000..4de66e3
--- /dev/null
@@ -0,0 +1,42 @@
+/* ====================================================================
+   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.usermodel.examples;
+
+import java.io.FileOutputStream;
+
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+public class SetPrintArea {
+
+
+    public static void main(String[]args) throws Exception {
+        Workbook wb = new XSSFWorkbook();
+        Sheet sheet = wb.createSheet("Sheet1");
+        //wb.setPrintArea(0, "$A$1:$C$2");
+        //sets the print area for the first sheet
+        //Alternatively:
+        wb.setPrintArea(0, 1, 2, 0, 3); //is equivalent to using the name reference (See the JavaDocs for more details)
+
+        // Create various cells and rows for spreadsheet.
+
+        FileOutputStream fileOut = new FileOutputStream("printArea.xlsx");
+        wb.write(fileOut);
+        fileOut.close();
+    }
+}
index 0e9e573b456623eb4ddd42cf246b418843a305de..7b4494661d13e0aee89d8da1a672c9b9d0d2bcf4 100644 (file)
@@ -23,66 +23,165 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName;
  * XSSF Implementation of a Named Range
  */
 public class XSSFName implements Name {
-       private XSSFWorkbook workbook;
-       private CTDefinedName ctName;
-       
-       protected XSSFName(XSSFWorkbook workbook) {
-               this.workbook = workbook;
-               this.ctName = CTDefinedName.Factory.newInstance();
-       }
-       protected XSSFName(CTDefinedName name, XSSFWorkbook workbook) {
-               this.workbook = workbook;
-               this.ctName = name;
-       }
-       
-       public boolean isFunctionName() {
-               // TODO Figure out how HSSF does this, and do the same!
-               return ctName.getFunction(); // maybe this works - verify
-       }
-       /**
-        * Returns the underlying named range object
-        */
-       protected CTDefinedName getCTName() {
-               return ctName;
-       }
-       
-       public String getNameName() {
-               return ctName.getName();
-       }
-       public void setNameName(String nameName) {
-               ctName.setName(nameName);
-       }
+    /**
+     * The following built-in names are defined in this SpreadsheetML
+     * specification:
+     * Built-in names reserved by SpreadsheetML begin with "_xlnm.". End users shall not use
+     * this string for custom names in the user interface.
+     */
 
-       public String getReference() {
-               return ctName.getStringValue();
-       }
-       public void setReference(String ref) {
-               ctName.setStringValue(ref);
-       }
-       
-       public String getSheetName() {
-               if(ctName.isSetLocalSheetId()) {
-                       // Given as explicit sheet id
-                       long sheetId = ctName.getLocalSheetId();
-                       if(sheetId >= 0) {
-                               return workbook.getSheetName((int)sheetId);
-                       }
-               } else {
-                       // Is it embeded in the reference itself?
-                       int excl = getReference().indexOf('!');
-                       if(excl > -1) {
-                               return getReference().substring(0, excl);
-                       }
-               }
-               
-               // Not given at all
-               return null;
-       }
+    /**
+     * this defined name specifies the workbook's print area
+     */
+    public final static String  BUILTIN_PRINT_AREA            = "_xlnm.Print_Area";
 
-       public String getComment() {
-               return ctName.getComment();
-       }
-       public void setComment(String comment) {
-               ctName.setComment(comment);
+    /**
+     * this defined name specifies the row(s) or column(s) to repeat
+     * at the top of each printed page.
+     */
+    public final static String  BUILTIN_PRINT_TITLE           = "_xlnm.Print_Titles";
+
+    //Filter & Advanced Filter
+
+    /**
+     * this defined name refers to a range containing the criteria values
+     * to be used in applying an advanced filter to a range of data
+     */
+    public final static String  BUILTIN_CRITERIA              = "_xlnm.Criteria:";
+
+
+    /**
+     * this defined name refers to the range containing the filtered
+     * output values resulting from applying an advanced filter criteria to a source
+     * range
+     */
+    public final static String  BUILTIN_EXTRACT              = "_xlnm.Extract:";
+
+    /**
+     * can be one of the following
+     * a. this defined name refers to a range to which an advanced filter has been
+     * applied. This represents the source data range, unfiltered.
+     * b. This defined name refers to a range to which an AutoFilter has been
+     * applied
+     */
+    public final static String  BUILTIN_FILTER_DB             = "_xlnm._FilterDatabase:";
+
+
+    //Miscellaneous
+
+    /**
+     * the defined name refers to a consolidation area
+     */
+    public final static String  BUILTIN_CONSOLIDATE_AREA      = "_xlnm.Consolidate_Area";
+
+    /**
+     * the range specified in the defined name is from a database data source
+     */
+    public final static String  BUILTIN_DATABASE              = "_xlnm.Database";
+
+    /**
+     * the defined name refers to a sheet title.
+     */
+    public final static String  BUILTIN_SHEET_TITLE           = "_xlnm.Sheet_Title";
+
+    private XSSFWorkbook workbook;
+    private CTDefinedName ctName;
+
+    protected XSSFName(XSSFWorkbook workbook) {
+       this.workbook = workbook;
+       this.ctName = CTDefinedName.Factory.newInstance();
+    }
+    protected XSSFName(CTDefinedName name, XSSFWorkbook workbook) {
+       this.workbook = workbook;
+       this.ctName = name;
+    }
+
+    public boolean isFunctionName() {
+       // TODO Figure out how HSSF does this, and do the same!
+       return ctName.getFunction(); // maybe this works - verify
+    }
+    /**
+     * Returns the underlying named range object
+     */
+    protected CTDefinedName getCTName() {
+       return ctName;
+    }
+
+    public String getNameName() {
+       return ctName.getName();
+    }
+    public void setNameName(String nameName) {
+       ctName.setName(nameName);
+    }
+
+    public String getReference() {
+       return ctName.getStringValue();
+    }
+    public void setReference(String ref) {
+       ctName.setStringValue(ref);
+    }
+
+    public void setLocalSheetId(int sheetId) {
+       ctName.setLocalSheetId(sheetId);
+    }
+
+    public int getLocalSheetId() {
+       return (int)ctName.getLocalSheetId();
+    }
+
+
+    public void setFunction(boolean value) {
+       ctName.setFunction(value);
+    }
+
+    public boolean getFunction() {
+       return ctName.getFunction();
+    }
+
+    public void setFunctionGroupId(int functionGroupId) {
+       ctName.setFunctionGroupId(functionGroupId);
+    }
+
+    public int getFunctionGroupId() {
+       return (int)ctName.getFunctionGroupId();
+    }
+
+    public String getSheetName() {
+       if(ctName.isSetLocalSheetId()) {
+           // Given as explicit sheet id
+           long sheetId = ctName.getLocalSheetId();
+           if(sheetId >= 0) {
+               return workbook.getSheetName((int)sheetId);
+           }
+       } else {
+           // Is it embeded in the reference itself?
+           int excl = getReference().indexOf('!');
+           if(excl > -1) {
+               return getReference().substring(0, excl);
+           }
        }
+
+       // Not given at all
+       return null;
+    }
+
+    public String getComment() {
+       return ctName.getComment();
+    }
+    public void setComment(String comment) {
+       ctName.setComment(comment);
+    }
+
+
+    public int hashCode(){
+       return ctName.toString().hashCode();
+    }
+
+    public boolean equals(Object o){
+       if(!(o instanceof XSSFName)) return false;
+       XSSFName cf = (XSSFName)o;
+       return ctName.toString().equals(cf.getCTName().toString());
+    }
+
+
 }
index c12c7ab7797782166be9b7220eab858ff0a9fe97..5bed8939906ccdc98f5b81081db8829161551ef3 100644 (file)
@@ -28,6 +28,7 @@ import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
+import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 import org.apache.poi.util.PackageHelper;
@@ -604,9 +605,16 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
         return this.sheets.size();
     }
 
-    public String getPrintArea(int sheetIndex) {
-        // TODO Auto-generated method stub
-        return null;
+    /**
+     * Retrieves the reference for the printarea of the specified sheet, the sheet name is appended to the reference even if it was not specified.
+     * @param sheetIndex Zero-based sheet index (0 Represents the first sheet to keep consistent with java)
+     * @return String Null if no print area has been defined
+     */
+    public String getPrintArea(int sheetIndex) {       
+        XSSFName name = getSpecificBuiltinRecord(XSSFName.BUILTIN_PRINT_AREA, sheetIndex);
+        if (name == null) return null;
+        //adding one here because 0 indicates a global named region; doesnt make sense for print areas
+        return name.getReference();
     }
 
     /**
@@ -826,21 +834,119 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
         bookView.setActiveTab(index);
     }
 
+    /**
+     * Sets the printarea for the sheet provided
+     * <p>
+     * i.e. Reference = $A$1:$B$2
+     * @param sheetIndex Zero-based sheet index (0 Represents the first sheet to keep consistent with java)
+     * @param reference Valid name Reference for the Print Area
+     */
     public void setPrintArea(int sheetIndex, String reference) {
-        // TODO Auto-generated method stub
-
+        XSSFName name = getSpecificBuiltinRecord(XSSFName.BUILTIN_PRINT_AREA, sheetIndex);
+        if (name == null) {
+            name = createBuiltInName(XSSFName.BUILTIN_PRINT_AREA, sheetIndex);
+            namedRanges.add(name);
+        }
+        name.setReference(reference);
     }
 
+    /**
+     * For the Convenience of Java Programmers maintaining pointers.
+     * @see #setPrintArea(int, String)
+     * @param sheetIndex Zero-based sheet index (0 = First Sheet)
+     * @param startColumn Column to begin printarea
+     * @param endColumn Column to end the printarea
+     * @param startRow Row to begin the printarea
+     * @param endRow Row to end the printarea
+     */
     public void setPrintArea(int sheetIndex, int startColumn, int endColumn, int startRow, int endRow) {
-        // TODO Auto-generated method stub
+        String reference=getReferencePrintArea(getSheetName(sheetIndex), startColumn, endColumn, startRow, endRow);
+        setPrintArea(sheetIndex, reference);
+    }
 
+    /**
+     * Sets the repeating rows and columns for a sheet.
+     *   This is function is included in the workbook
+     * because it creates/modifies name records which are stored at the
+     * workbook level.
+     * <p>
+     * To set just repeating columns:
+     * <pre>
+     *  workbook.setRepeatingRowsAndColumns(0,0,1,-1,-1);
+     * </pre>
+     * To set just repeating rows:
+     * <pre>
+     *  workbook.setRepeatingRowsAndColumns(0,-1,-1,0,4);
+     * </pre>
+     * To remove all repeating rows and columns for a sheet.
+     * <pre>
+     *  workbook.setRepeatingRowsAndColumns(0,-1,-1,-1,-1);
+     * </pre>
+     *
+     * @param sheetIndex    0 based index to sheet.
+     * @param startColumn   0 based start of repeating columns.
+     * @param endColumn     0 based end of repeating columns.
+     * @param startRow      0 based start of repeating rows.
+     * @param endRow        0 based end of repeating rows.
+     */
+    public void setRepeatingRowsAndColumns(int sheetIndex,
+                                           int startColumn, int endColumn,
+                                           int startRow, int endRow) {
+        //TODO
     }
 
-    public void setRepeatingRowsAndColumns(int sheetIndex, int startColumn, int endColumn, int startRow, int endRow) {
-        // TODO Auto-generated method stub
 
+    private String getReferencePrintArea(String sheetName, int startC, int endC, int startR, int endR) {
+        //windows excel example: Sheet1!$C$3:$E$4
+        CellReference colRef = new CellReference(sheetName, startR, startC, true, true);
+        CellReference colRef2 = new CellReference(sheetName, endR, endC, true, true);
+
+        String c = "'" + sheetName + "'!$" + colRef.getCellRefParts()[2] + "$" + colRef.getCellRefParts()[1] + ":$" + colRef2.getCellRefParts()[2] + "$" + colRef2.getCellRefParts()[1];
+        return c;
+    }
+
+    //****************** NAME RANGE *************************
+
+    private CTDefinedNames getDefinedNames() {
+        return workbook.getDefinedNames() == null ? workbook.addNewDefinedNames() : workbook.getDefinedNames();
     }
 
+
+    public XSSFName getSpecificBuiltinRecord(String builtInCode, int sheetNumber) {
+        for (XSSFName name : namedRanges) {
+            if (name.getNameName().equalsIgnoreCase(builtInCode) && name.getLocalSheetId() == sheetNumber) {
+                return name;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Generates a NameRecord to represent a built-in region
+     * @return a new NameRecord
+     */
+    public XSSFName createBuiltInName(String builtInName, int sheetNumber) {
+        if (sheetNumber < 0 || sheetNumber+1 > Short.MAX_VALUE) {
+            throw new IllegalArgumentException("Sheet number ["+sheetNumber+"]is not valid ");
+        }
+        
+        CTDefinedName nameRecord=getDefinedNames().addNewDefinedName();
+        nameRecord.setName(builtInName);
+        nameRecord.setLocalSheetId(sheetNumber);
+   
+        XSSFName name=new XSSFName(nameRecord,this);        
+        //while(namedRanges.contains(name)) {
+        for(XSSFName nr :  namedRanges){
+            if(nr.equals(name))
+            throw new RuntimeException("Builtin (" + builtInName 
+                    + ") already exists for sheet (" + sheetNumber + ")");
+        }     
+
+        return name;
+    }
+    
+    //*******************************************
+    
     /**
      * We only set one sheet as selected for compatibility with HSSF.
      */
index 49e47c937d9db321c1b80e988b65a1988e76c99e..e4157c7d08b799c30cd1dcd8240eccc102802f60 100644 (file)
@@ -31,6 +31,7 @@ import org.apache.poi.ss.usermodel.Name;
 import org.apache.poi.ss.usermodel.RichTextString;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.StylesSource;
+import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.xssf.XSSFTestDataSamples;
 import org.apache.poi.xssf.model.StylesTable;
 import org.openxml4j.opc.ContentTypes;
@@ -150,6 +151,73 @@ public final class TestXSSFWorkbook extends TestCase {
                workbook.removeSheetAt(0);
                assertEquals(0, workbook.getNumberOfSheets());
        }
+
+       public void testPrintArea(){
+        Workbook workbook = new XSSFWorkbook();
+        Sheet sheet = workbook.createSheet("Test Print Area");
+        String sheetName = workbook.getSheetName(0);
+        
+       // String reference = sheetName+"!$A$1:$B$1";
+       // workbook.setPrintArea(0, reference);
+        workbook.setPrintArea(0,1,5,4,9);
+        
+        String retrievedPrintArea = workbook.getPrintArea(0);
+
+        //assertNotNull("Print Area not defined for first sheet", retrievedPrintArea);
+        assertEquals("'"+sheetName+"'!$B$5:$F$10", retrievedPrintArea);
+}
+       
+       public void _testRepeatingRowsAndColums() {
+               // First test that setting RR&C for same sheet more than once only creates a 
+               // single  Print_Titles built-in record
+               XSSFWorkbook wb = new XSSFWorkbook();
+               XSSFSheet sheet = wb.createSheet("FirstSheet");
+               
+               // set repeating rows and columns twice for the first sheet
+               for (int i = 0; i < 2; i++) {
+                       wb.setRepeatingRowsAndColumns(0, 0, 0, 0, 3);
+                       //sheet.createFreezePane(0, 3);
+               }
+               assertEquals(1, wb.getNumberOfNames());
+               XSSFName nr1 = wb.getNameAt(0);
+               
+               assertEquals(XSSFName.BUILTIN_PRINT_TITLE, nr1.getNameName());
+               assertEquals("'FirstSheet'!$A:$A,'FirstSheet'!$1:$4", nr1.getReference());
+               
+               // Save and re-open
+               XSSFWorkbook nwb = XSSFTestDataSamples.writeOutAndReadBack(wb);
+
+               assertEquals(1, nwb.getNumberOfNames());
+               nr1 = nwb.getNameAt(0);
+               
+               assertEquals(XSSFName.BUILTIN_PRINT_TITLE, nr1.getNameName());
+               assertEquals("'FirstSheet'!$A:$A,'FirstSheet'!$1:$4", nr1.getReference());
+               
+               // check that setting RR&C on a second sheet causes a new Print_Titles built-in
+               // name to be created
+               sheet = nwb.createSheet("SecondSheet");
+               nwb.setRepeatingRowsAndColumns(1, 1, 2, 0, 0);
+
+               assertEquals(2, nwb.getNumberOfNames());
+               XSSFName nr2 = nwb.getNameAt(1);
+               
+               assertEquals(XSSFName.BUILTIN_PRINT_TITLE, nr2.getNameName());
+               assertEquals("'SecondSheet'!$B:$C,'SecondSheet'!$1:$1", nr2.getReference());
+               
+               if (false) {
+                       // In case you fancy checking in excel, to ensure it
+                       //  won't complain about the file now
+                       try {
+                               File tempFile = File.createTempFile("POI-45126-", ".xlsx");
+                               FileOutputStream fout = new FileOutputStream(tempFile);
+                               nwb.write(fout);
+                               fout.close();
+                               System.out.println("check out " + tempFile.getAbsolutePath());
+                       } catch (IOException e) {
+                               throw new RuntimeException(e);
+                       }
+               }
+       }
        
        /**
         * Tests that we can save a new document