]> source.dussan.org Git - poi.git/commitdiff
Fix bug #45126 - Avoid generating multiple NamedRanges with the same name, which...
authorNick Burch <nick@apache.org>
Thu, 10 Jul 2008 21:49:37 +0000 (21:49 +0000)
committerNick Burch <nick@apache.org>
Thu, 10 Jul 2008 21:49:37 +0000 (21:49 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@675776 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/model/LinkTable.java
src/java/org/apache/poi/hssf/model/Workbook.java
src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java

index f6f0bce1a12f2d12677d955da1a86d23a2779541..e484ebbf1a6835c37d1a78d393855492d2d45504 100644 (file)
@@ -37,6 +37,7 @@
 
                <!-- Don't forget to update status.xml too! -->
         <release version="3.1.1-alpha1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">45126 - Avoid generating multiple NamedRanges with the same name, which Excel dislikes</action>
            <action dev="POI-DEVELOPERS" type="fix">Fix cell.getRichStringCellValue() for formula cells with string results</action>
            <action dev="POI-DEVELOPERS" type="fix">45365 - Handle more excel number formatting rules in FormatTrackingHSSFListener / XLS2CSVmra</action>
            <action dev="POI-DEVELOPERS" type="fix">45373 - Improve the performance of HSSFSheet.shiftRows</action>
index 4e95db32308a1cd371f45b47105176d2e130efa7..767b33521b64562f4b79d1bab62b20f2605c9b71 100644 (file)
@@ -34,6 +34,7 @@
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.1.1-alpha1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">45126 - Avoid generating multiple NamedRanges with the same name, which Excel dislikes</action>
            <action dev="POI-DEVELOPERS" type="fix">Fix cell.getRichStringCellValue() for formula cells with string results</action>
            <action dev="POI-DEVELOPERS" type="fix">45365 - Handle more excel number formatting rules in FormatTrackingHSSFListener / XLS2CSVmra</action>
            <action dev="POI-DEVELOPERS" type="fix">45373 - Improve the performance of HSSFSheet.shiftRows</action>
index a19971b7d59bc72cad9d56ea81562f18abb673b6..1d8781d9713dc1e91939a031aa24b4ea88d574d3 100755 (executable)
@@ -63,6 +63,8 @@ import org.apache.poi.hssf.record.SupBookRecord;
  * @author Josh Micich
  */
 final class LinkTable {
+       
+       
        // TODO make this class into a record aggregate
 
        private static final class CRNBlock {
@@ -233,13 +235,39 @@ final class LinkTable {
                if (idx == -1) idx = findFirstRecordLocBySid(CountryRecord.sid);
                int countNames = _definedNames.size();
                _workbookRecordList.add(idx+countNames, name);
-
        }
 
        public void removeName(int namenum) {
                _definedNames.remove(namenum);
        }
 
+    /**
+     * checks if the given name is already included in the linkTable
+     */
+    public boolean nameAlreadyExists(NameRecord name)
+    {
+       // Check to ensure no other names have the same case-insensitive name
+       for ( int i = getNumNames()-1; i >=0; i-- ) {
+               NameRecord rec = getNameRecord(i);
+               if (rec != name) {
+                       if (isDuplicatedNames(name, rec))
+                               return true;
+               }
+       }
+       return false;
+    }
+    
+    private boolean isDuplicatedNames(NameRecord firstName, NameRecord lastName)
+    {
+       return lastName.getNameText().equalsIgnoreCase(firstName.getNameText()) 
+               && isSameSheetNames(firstName, lastName);
+    }
+    private boolean isSameSheetNames(NameRecord firstName, NameRecord lastName)
+    {
+       return lastName.getEqualsToIndexToSheet() == firstName.getEqualsToIndexToSheet();
+    }
+
+    
        public short getIndexToSheet(short num) {
                return _externSheetRecord.getREFRecordAt(num).getIndexToFirstSupBook();
        }
index fa22cfb6889161f94b5d25ff75caf828d251bf1a..329e217a81158488e5390ce77facdb5bd6d7b6ac 100644 (file)
@@ -105,6 +105,8 @@ public class Workbook implements Model
 
     private static POILogger   log = POILogFactory.getLogger(Workbook.class);
 
+    protected static final String EXCEL_REPEATING_NAME_PREFIX_ = "Excel_Name_Record_Titles_";
+
     /**
      * Creates new Workbook with no intitialization --useless right now
      * @see #createWorkbook(List)
@@ -1918,13 +1920,20 @@ public class Workbook implements Model
      */
     public NameRecord addName(NameRecord name)
     {
-        
-        getOrCreateLinkTable().addName(name);
+       
+        LinkTable linkTable = getOrCreateLinkTable();
+        if(linkTable.nameAlreadyExists(name)) {
+               throw new IllegalArgumentException(
+                "You are trying to assign a duplicated name record: "
+                + name.getNameText());
+        }
+        linkTable.addName(name);
 
         return name;
     }
-
-    /**Generates a NameRecord to represent a built-in region
+    
+    /**
+     * Generates a NameRecord to represent a built-in region
      * @return a new NameRecord unless the index is invalid
      */
     public NameRecord createBuiltInName(byte builtInName, int index)
@@ -1933,9 +1942,21 @@ public class Workbook implements Model
             throw new IllegalArgumentException("Index is not valid ["+index+"]");
         
         NameRecord name = new NameRecord(builtInName, (short)(index));
-                
-        addName(name);
         
+        String prefix = EXCEL_REPEATING_NAME_PREFIX_ + index + "_";
+        int cont = 0;
+        while(linkTable.nameAlreadyExists(name)) {
+               cont++;
+               String altNameName = prefix + cont;
+               
+               // It would be better to set a different builtInName here.
+               // It does not seem possible, so we create it as a 
+               //  non built-in name from this point on
+               name = new NameRecord();
+               name.setNameText(altNameName);
+            name.setNameTextLength((byte)altNameName.length());
+        }
+        addName(name);
         return name;
     }
 
index 591a7ba24fe86d28ed9a26c243fde47f5062c11e..0a508805db1e94f578817437a3bdfec37753cf29 100644 (file)
 
 package org.apache.poi.hssf.usermodel;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+
 import junit.framework.TestCase;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
 import org.apache.poi.hssf.util.AreaReference;
 import org.apache.poi.hssf.util.CellReference;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 
 /**
  * 
@@ -485,4 +491,57 @@ public final class TestNamedRange extends TestCase {
                        // expected during successful test
                }
    }
+       
+       public void testRepeatingRowsAndColumsNames() throws Exception {
+               HSSFWorkbook wb = new HSSFWorkbook();
+               HSSFSheet sheet = wb.createSheet();
+               
+               for (int rowItem = 0; rowItem < 10; rowItem++) {
+                       HSSFRow r = sheet.createRow(rowItem);
+                       for (int column = 0; column < 2; column++) {
+                               HSSFCell cellItem = r.createCell((short) column);
+                               cellItem.setCellType(HSSFCell.CELL_TYPE_STRING);
+                               cellItem.setCellValue(new HSSFRichTextString("Some value here"));
+                               if (rowItem == 2) {
+                                       wb.setRepeatingRowsAndColumns(0, 0, 0, 0, 3 - 1);
+                                       sheet.createFreezePane(0, 3);
+                               } 
+                       }
+               }
+
+               assertEquals(2, wb.getNumberOfNames());
+               HSSFName nr1 = wb.getNameAt(0);
+               HSSFName nr2 = wb.getNameAt(1);
+               
+               assertEquals("Print_Titles", nr1.getNameName());
+               assertEquals("Sheet0!$A$1:$A$0,Sheet0!$A$1:$IV$3", nr1.getReference());
+               
+               assertEquals("Excel_Name_Record_Titles_1_1", nr2.getNameName());
+               assertEquals("Sheet0!$A$1:$A$0,Sheet0!$A$1:$IV$3", nr2.getReference());
+               
+               // Save and re-open
+               ByteArrayOutputStream baos = new ByteArrayOutputStream();
+               wb.write(baos);
+               ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+               HSSFWorkbook nwb = new HSSFWorkbook(new POIFSFileSystem(bais));
+
+               assertEquals(2, nwb.getNumberOfNames());
+               nr1 = nwb.getNameAt(0);
+               nr2 = nwb.getNameAt(1);
+               
+               // TODO -
+               //  should these references really have been corrected?
+               //  and if so, why not also above?
+               assertEquals("Print_Titles", nr1.getNameName());
+               assertEquals("Sheet0!A:A,Sheet0!$A$1:$IV$3", nr1.getReference());
+               
+               assertEquals("Excel_Name_Record_Titles_1_1", nr2.getNameName());
+               assertEquals("Sheet0!A:A,Sheet0!$A$1:$IV$3", nr2.getReference());
+               
+               // In case you fancy checking in excel, to ensure it
+               //  won't complain about the file now
+               FileOutputStream fout = new FileOutputStream(File.createTempFile("POI-45126-", ".xls"));
+               wb.write(fout);
+               fout.close();
+       }
 }