mirror of https://github.com/apache/poi.git
Fix bug #45126 - Avoid generating multiple NamedRanges with the same name, which Excel dislikes
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@675776 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ae7c94b6cb
commit
21d6638529
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
@ -1919,12 +1921,19 @@ 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)
|
||||
|
@ -1934,8 +1943,20 @@ public class Workbook implements Model
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,11 +17,17 @@
|
|||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue