git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@757520 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_5_BETA6
@@ -37,7 +37,8 @@ | |||
<!-- Don't forget to update status.xml too! --> | |||
<release version="3.5-beta6" date="2009-??-??"> | |||
<action dev="POI-DEVELOPERS" type="fix">update cell type when setting cached formula result in XSSFCell</action> | |||
<action dev="POI-DEVELOPERS" type="fix">46840 - PageSettingsBlock should include HEADERFOOTER record</action> | |||
<action dev="POI-DEVELOPERS" type="fix">46885 - update cell type when setting cached formula result in XSSFCell</action> | |||
<action dev="POI-DEVELOPERS" type="add">added modifiers for anchor type to XSSFClientAnchor</action> | |||
<action dev="POI-DEVELOPERS" type="add">46772 - support built-in data formats in XSSFDataFormat</action> | |||
<action dev="POI-DEVELOPERS" type="fix">46719 - fixed XSSFSheet.shiftRows to correctly preserve row heights</action> |
@@ -34,7 +34,8 @@ | |||
<!-- Don't forget to update changes.xml too! --> | |||
<changes> | |||
<release version="3.5-beta6" date="2009-??-??"> | |||
<action dev="POI-DEVELOPERS" type="fix">update cell type when setting cached formula result in XSSFCell</action> | |||
<action dev="POI-DEVELOPERS" type="fix">46840 - PageSettingsBlock should include HEADERFOOTER record</action> | |||
<action dev="POI-DEVELOPERS" type="fix">46885 - update cell type when setting cached formula result in XSSFCell</action> | |||
<action dev="POI-DEVELOPERS" type="add">added modifiers for anchor type to XSSFClientAnchor</action> | |||
<action dev="POI-DEVELOPERS" type="add">46772 - support built-in data formats in XSSFDataFormat</action> | |||
<action dev="POI-DEVELOPERS" type="fix">46719 - fixed XSSFSheet.shiftRows to correctly preserve row heights</action> |
@@ -222,8 +222,12 @@ public final class Sheet implements Model { | |||
} else if (windowTwo != null) { | |||
// probably 'Custom View Settings' sub-stream which is found between | |||
// USERSVIEWBEGIN(01AA) and USERSVIEWEND(01AB) | |||
// TODO - create UsersViewAggregate to hold these sub-streams, and simplify this code a bit | |||
// This happens three times in test sample file "29982.xls" | |||
if (rs.peekNextSid() != UnknownRecord.USERSVIEWEND_01AB) { | |||
// Also several times in bugzilla samples 46840-23373 and 46840-23374 | |||
if (recSid == UnknownRecord.HEADER_FOOTER_089C) { | |||
_psBlock.addLateHeaderFooter(rs.getNext()); | |||
} else if (rs.peekNextSid() != UnknownRecord.USERSVIEWEND_01AB) { | |||
// not quite the expected situation | |||
throw new RuntimeException("two Page Settings Blocks found in the same sheet"); | |||
} |
@@ -48,6 +48,7 @@ public final class UnknownRecord extends StandardRecord { | |||
public static final int SHEETEXT_0862 = 0x0862; // OOO calls this SHEETLAYOUT | |||
public static final int SHEETPROTECTION_0867 = 0x0867; | |||
public static final int RANGEPROTECTION_0868 = 0x0868; | |||
public static final int HEADER_FOOTER_089C = 0x089C; | |||
private int _sid; | |||
private byte[] _rawData; | |||
@@ -181,7 +182,7 @@ public final class UnknownRecord extends StandardRecord { | |||
case 0x0897: return "GUIDTYPELIB"; | |||
case 0x089A: return "MTRSETTINGS"; | |||
case 0x089B: return "COMPRESSPICTURES"; | |||
case 0x089C: return "HEADERFOOTER"; | |||
case HEADER_FOOTER_089C: return "HEADERFOOTER"; | |||
case 0x08A1: return "SHAPEPROPSSTREAM"; | |||
case 0x08A3: return "FORCEFULLCALCULATION"; | |||
case 0x08A4: return "SHAPEPROPSSTREAM"; |
@@ -71,6 +71,7 @@ public final class PageSettingsBlock extends RecordAggregate { | |||
private List<ContinueRecord> _plsContinues; | |||
private PrintSetupRecord printSetup; | |||
private Record _bitmap; | |||
private Record _headerFooter; | |||
public PageSettingsBlock(RecordStream rs) { | |||
while(true) { | |||
@@ -112,6 +113,7 @@ public final class PageSettingsBlock extends RecordAggregate { | |||
case UnknownRecord.PLS_004D: | |||
case PrintSetupRecord.sid: | |||
case UnknownRecord.BITMAP_00E9: | |||
case UnknownRecord.HEADER_FOOTER_089C: // extra header/footer settings supported by Excel 2007 | |||
return true; | |||
} | |||
return false; | |||
@@ -164,6 +166,9 @@ public final class PageSettingsBlock extends RecordAggregate { | |||
case UnknownRecord.BITMAP_00E9: | |||
_bitmap = rs.getNext(); | |||
break; | |||
case UnknownRecord.HEADER_FOOTER_089C: | |||
_headerFooter = rs.getNext(); | |||
break; | |||
default: | |||
// all other record types are not part of the PageSettingsBlock | |||
return false; | |||
@@ -224,6 +229,7 @@ public final class PageSettingsBlock extends RecordAggregate { | |||
} | |||
visitIfPresent(printSetup, rv); | |||
visitIfPresent(_bitmap, rv); | |||
visitIfPresent(_headerFooter, rv); | |||
} | |||
private static void visitIfPresent(Record r, RecordVisitor rv) { | |||
if (r != null) { | |||
@@ -523,4 +529,16 @@ public final class PageSettingsBlock extends RecordAggregate { | |||
public HCenterRecord getHCenter() { | |||
return _hCenter; | |||
} | |||
/** | |||
* HEADERFOOTER is new in 2007. Some apps seem to have scattered this record long after | |||
* the {@link PageSettingsBlock} where it belongs. | |||
* | |||
*/ | |||
public void addLateHeaderFooter(Record rec) { | |||
if (_headerFooter != null) { | |||
throw new IllegalStateException("This page settings block already has a header/footer record"); | |||
} | |||
_headerFooter = rec; | |||
} | |||
} |
@@ -17,13 +17,28 @@ | |||
package org.apache.poi.hssf.record.aggregates; | |||
import java.util.Arrays; | |||
import junit.framework.AssertionFailedError; | |||
import junit.framework.TestCase; | |||
import org.apache.poi.hssf.HSSFTestDataSamples; | |||
import org.apache.poi.hssf.model.RecordStream; | |||
import org.apache.poi.hssf.model.Sheet; | |||
import org.apache.poi.hssf.record.BOFRecord; | |||
import org.apache.poi.hssf.record.DimensionsRecord; | |||
import org.apache.poi.hssf.record.EOFRecord; | |||
import org.apache.poi.hssf.record.FooterRecord; | |||
import org.apache.poi.hssf.record.HeaderRecord; | |||
import org.apache.poi.hssf.record.NumberRecord; | |||
import org.apache.poi.hssf.record.Record; | |||
import org.apache.poi.hssf.record.UnknownRecord; | |||
import org.apache.poi.hssf.record.WindowTwoRecord; | |||
import org.apache.poi.hssf.usermodel.HSSFPrintSetup; | |||
import org.apache.poi.hssf.usermodel.HSSFSheet; | |||
import org.apache.poi.hssf.usermodel.HSSFWorkbook; | |||
import org.apache.poi.hssf.usermodel.RecordInspector.RecordCollector; | |||
import org.apache.poi.util.HexRead; | |||
/** | |||
* Tess for {@link PageSettingsBlock} | |||
@@ -47,4 +62,54 @@ public final class TestPageSettingBlock extends TestCase { | |||
throw new AssertionFailedError("Identified bug 46548: PageSettingBlock missing PrintSetupRecord record"); | |||
} | |||
} | |||
/** | |||
* Bug 46840 occurred because POI failed to recognise HEADERFOOTER as part of the | |||
* {@link PageSettingsBlock}. | |||
* | |||
*/ | |||
public void testHeaderFooter_bug46840() { | |||
int rowIx = 5; | |||
int colIx = 6; | |||
NumberRecord nr = new NumberRecord(); | |||
nr.setRow(rowIx); | |||
nr.setColumn((short) colIx); | |||
nr.setValue(3.0); | |||
Record[] recs = { | |||
BOFRecord.createSheetBOF(), | |||
new HeaderRecord("&LSales Figures"), | |||
new FooterRecord("&LJanuary"), | |||
ur(UnknownRecord.HEADER_FOOTER_089C, "9C 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C4 60 00 00 00 00 00 00 00 00"), | |||
new DimensionsRecord(), | |||
new WindowTwoRecord(), | |||
ur(UnknownRecord.USERSVIEWBEGIN_01AA, "ED 77 3B 86 BC 3F 37 4C A9 58 60 23 43 68 54 4B 01 00 00 00 64 00 00 00 40 00 00 00 02 00 00 00 3D 80 04 00 00 00 00 00 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 3F FF FF 01 00"), | |||
new HeaderRecord("&LSales Figures"), | |||
new FooterRecord("&LJanuary"), | |||
ur(UnknownRecord.HEADER_FOOTER_089C, "9C 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C4 60 00 00 00 00 00 00 00 00"), | |||
ur(UnknownRecord.USERSVIEWEND_01AB, "01, 00"), | |||
EOFRecord.instance, | |||
}; | |||
RecordStream rs = new RecordStream(Arrays.asList(recs), 0); | |||
Sheet sheet; | |||
try { | |||
sheet = Sheet.createSheet(rs); | |||
} catch (RuntimeException e) { | |||
if (e.getMessage().equals("two Page Settings Blocks found in the same sheet")) { | |||
throw new AssertionFailedError("Identified bug 46480"); | |||
} | |||
throw e; | |||
} | |||
RecordCollector rv = new RecordCollector(); | |||
sheet.visitContainedRecords(rv, rowIx); | |||
Record[] outRecs = rv.getRecords(); | |||
assertEquals(13, outRecs.length); | |||
} | |||
private static UnknownRecord ur(int sid, String hexData) { | |||
return new UnknownRecord(sid, HexRead.readFromString(hexData)); | |||
} | |||
} |