Merged revisions 638786-638802,638805-638811,638813-638814,638816-639230,639233-639241,639243-639253,639255-639486,639488-639601,639603-639835,639837-639917,639919-640056,640058-640710,640712-641156,641158-641184,641186-641795,641797-641798,641800-641933,641935-641963,641965-641966,641968-641995,641997-642230,642232-642562,642564-642565,642568-642570,642572-642573,642576-642736,642739-642877,642879,642881-642890,642892-642903,642905-642945,642947-643624,643626-643653,643655-643669,643671,643673-643830,643832-643833,643835-644342,644344-644472,644474-644508,644510-645347,645349-645351,645353-645559,645561-645565,645568-645951,645953-646193,646195-646311,646313-646404,646406-646665,646667-646853,646855-646869,646871-647151,647153-647185,647187-647277,647279-647566,647568-647573,647575,647578-647711,647714-647737,647739-647823,647825-648155,648157-648202,648204-648273,648275,648277-648302,648304-648333,648335-648588,648590-648622,648625-648673,648675-649141,649144,649146-649556,649558-649795,649799,649801-649910,649912-649913,649915-650128,650131-650132,650134-650137,650140-650914,650916-651991,651993-652284,652286-652287,652289,652291,652293-652297,652299-652328,652330-652425,652427-652445,652447-652560,652562-652933,652935,652937-652993,652995-653116,653118-653124,653126-653483,653487-653519,653522-653550,653552-653607,653609-653667,653669-653674,653676-653814,653817-653830,653832-653891,653893-653944,653946-654055,654057-654355,654357-654365,654367-654648,654651-655215,655217-655277,655279-655281,655283-655911,655913-656212,656214,656216-656251,656253-656698,656700-656756,656758-656892,656894-657135,657137-657165,657168-657179,657181-657354,657356-657357,657359-657701,657703-657874,657876-658032,658034-658284,658286,658288-658301,658303-658307,658309-658321,658323-658335,658337-658348,658351,658353-658832,658834-658983,658985,658987-659066,659068-659402,659404-659428,659430-659451,659453-659454,659456-659461,659463-659477,659479-659524,659526-659571,659574,659576-660255,660257-660262,660264-660279,660281-660343,660345-660473,660475-660827,660829-660833,660835-660888,660890-663321,663323-663435,663437-663764,663766-663854,663856-664219,664221-664489,664494-664514,664516-668013,668015-668142,668144-668152,668154,668156-668256,668258,668260-669139,669141-669455,669457-669657,669659-669808,669810-670189,670191-671321,671323-672229,672231-672549,672551-672552,672554-672561,672563-672566,672568,672571-673049,673051-673852,673854-673862,673864-673986,673988-673996,673998-674347,674349-674890,674892-674910,674912-674936,674938-674952,674954-675078,675080-675085,675087-675217,675219-675660,675662-675670,675672-675716,675718-675776 via svnmerge from

https://svn.apache.org:443/repos/asf/poi/trunk

........
  r675727 | nick | 2008-07-10 21:54:42 +0100 (Thu, 10 Jul 2008) | 1 line
  
  Fix cell.getRichStringCellValue() for formula cells with string results
........
  r675734 | nick | 2008-07-10 22:03:52 +0100 (Thu, 10 Jul 2008) | 1 line
  
  Add test for bug #43623, currently disabled as it makes FormulaParser unhappy
........
  r675776 | nick | 2008-07-10 22:49:37 +0100 (Thu, 10 Jul 2008) | 1 line
  
  Fix bug #45126 - Avoid generating multiple NamedRanges with the same name, which Excel dislikes
........


git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@675787 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2008-07-10 22:27:38 +00:00
parent 82f6d9f991
commit 03c8608066
8 changed files with 204 additions and 20 deletions

View File

@ -50,6 +50,8 @@
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
</release>
<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>
<action dev="POI-DEVELOPERS" type="fix">45367 - Fixed bug when last row removed from sheet is row zero</action>

View File

@ -47,6 +47,8 @@
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
</release>
<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>
<action dev="POI-DEVELOPERS" type="fix">45367 - Fixed bug when last row removed from sheet is row zero</action>

View File

@ -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();
}

View 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)
@ -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;
}

View File

@ -610,13 +610,28 @@ public class HSSFCell implements Cell
// Set the 'pre-evaluated result' for the formula
// note - formulas do not preserve text formatting.
FormulaRecordAggregate fr = (FormulaRecordAggregate) record;
// must make new sr because fr.getStringRecord() may be null
StringRecord sr = new StringRecord();
sr.setString(hvalue.getString()); // looses format
// Save the string into a String Record, creating
// one if required
StringRecord sr = fr.getStringRecord();
if(sr == null) {
// Wasn't a string before, need a new one
sr = new StringRecord();
fr.setStringRecord(sr);
}
// Save, loosing the formatting
sr.setString(hvalue.getString());
// Update our local cache to the un-formatted version
stringValue = new HSSFRichTextString(sr.getString());
// All done
return;
}
// If we get here, we're not dealing with a formula,
// so handle things as a normal rich text cell
if (cellType != CELL_TYPE_STRING) {
setCellType(CELL_TYPE_STRING, false, row, col, styleIndex);
}

Binary file not shown.

View File

@ -33,9 +33,7 @@ import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.formula.DeletedArea3DPtg;
import org.apache.poi.util.TempFile;
@ -1152,10 +1150,12 @@ public final class TestBugs extends TestCase {
s.createRow(0);
HSSFCell c1 = s.getRow(0).createCell((short)0);
HSSFCell c2 = s.getRow(0).createCell((short)1);
HSSFCell c3 = s.getRow(0).createCell((short)2);
// As number and string
c1.setCellFormula("70164");
c2.setCellFormula("\"70164\"");
c3.setCellFormula("\"90210\"");
// Check the formulas
assertEquals("70164.0", c1.getCellFormula());
@ -1166,20 +1166,31 @@ public final class TestBugs extends TestCase {
assertEquals("", c1.getRichStringCellValue().getString());
assertEquals(0.0, c2.getNumericCellValue(), 0.00001);
assertEquals("", c2.getRichStringCellValue().getString());
assertEquals(0.0, c3.getNumericCellValue(), 0.00001);
assertEquals("", c3.getRichStringCellValue().getString());
// Now evaluate
// Try changing the cached value on one of the string
// formula cells, so we can see it updates properly
c3.setCellValue(new HSSFRichTextString("test"));
assertEquals(0.0, c3.getNumericCellValue(), 0.00001);
assertEquals("test", c3.getRichStringCellValue().getString());
// Now evaluate, they should all be changed
HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(s, wb);
eval.setCurrentRow(s.getRow(0));
eval.evaluateFormulaCell(c1);
eval.evaluateFormulaCell(c2);
eval.evaluateFormulaCell(c3);
// Check
// Check that the cells now contain
// the correct values
assertEquals(70164.0, c1.getNumericCellValue(), 0.00001);
assertEquals("", c1.getRichStringCellValue().getString());
assertEquals(0.0, c2.getNumericCellValue(), 0.00001);
// TODO - why isn't this working?
// assertEquals("70164", c2.getRichStringCellValue().getString());
assertEquals("70164", c2.getRichStringCellValue().getString());
assertEquals(0.0, c3.getNumericCellValue(), 0.00001);
assertEquals("90210", c3.getRichStringCellValue().getString());
// Write and read
@ -1187,12 +1198,15 @@ public final class TestBugs extends TestCase {
HSSFSheet ns = nwb.getSheetAt(0);
HSSFCell nc1 = ns.getRow(0).getCell((short)0);
HSSFCell nc2 = ns.getRow(0).getCell((short)1);
HSSFCell nc3 = ns.getRow(0).getCell((short)2);
// Re-check
assertEquals(70164.0, nc1.getNumericCellValue(), 0.00001);
assertEquals("", nc1.getRichStringCellValue().getString());
assertEquals(0.0, nc2.getNumericCellValue(), 0.00001);
assertEquals("70164", nc2.getRichStringCellValue().getString());
assertEquals(0.0, nc3.getNumericCellValue(), 0.00001);
assertEquals("90210", nc3.getRichStringCellValue().getString());
// Now check record level stuff too
ns.getSheet().setLoc(0);
@ -1205,15 +1219,58 @@ public final class TestBugs extends TestCase {
if(fn == 0) {
assertEquals(70164.0, fr.getFormulaRecord().getValue(), 0.0001);
assertNull(fr.getStringRecord());
} else {
} else if (fn == 1) {
assertEquals(0.0, fr.getFormulaRecord().getValue(), 0.0001);
assertNotNull(fr.getStringRecord());
assertEquals("70164", fr.getStringRecord().getString());
} else {
assertEquals(0.0, fr.getFormulaRecord().getValue(), 0.0001);
assertNotNull(fr.getStringRecord());
assertEquals("90210", fr.getStringRecord().getString());
}
fn++;
}
}
assertEquals(2, fn);
assertEquals(3, fn);
}
/**
* Problem with "Vector Rows", eg a whole
* column which is set to the result of
* {=sin(B1:B9)}(9,1), so that each cell is
* shown to have the contents
* {=sin(B1:B9){9,1)[rownum][0]
* In this sample file, the vector column
* is C, and the data column is B.
*
* For now, blows up with an exception from ExtPtg
* Expected ExpPtg to be converted from Shared to Non-Shared...
*/
public void DISABLEDtest43623() throws Exception {
HSSFWorkbook wb = openSample("43623.xls");
assertEquals(1, wb.getNumberOfSheets());
HSSFSheet s1 = wb.getSheetAt(0);
HSSFCell c1 = s1.getRow(0).getCell(2);
HSSFCell c2 = s1.getRow(1).getCell(2);
HSSFCell c3 = s1.getRow(2).getCell(2);
// These formula contents are a guess...
assertEquals("{=sin(B1:B9){9,1)[0][0]", c1.getCellFormula());
assertEquals("{=sin(B1:B9){9,1)[1][0]", c2.getCellFormula());
assertEquals("{=sin(B1:B9){9,1)[2][0]", c3.getCellFormula());
// Save and re-open, ensure it still works
HSSFWorkbook nwb = writeOutAndReadBack(wb);
HSSFSheet ns1 = nwb.getSheetAt(0);
HSSFCell nc1 = ns1.getRow(0).getCell(2);
HSSFCell nc2 = ns1.getRow(1).getCell(2);
HSSFCell nc3 = ns1.getRow(2).getCell(2);
assertEquals("{=sin(B1:B9){9,1)[0][0]", nc1.getCellFormula());
assertEquals("{=sin(B1:B9){9,1)[1][0]", nc2.getCellFormula());
assertEquals("{=sin(B1:B9){9,1)[2][0]", nc3.getCellFormula());
}
}

View File

@ -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();
}
}