mirror of https://github.com/apache/poi.git
Fix for bug 46840 - PageSettingsBlock should include HEADERFOOTER record
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@757520 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2af8300e50
commit
a5bff38b97
|
@ -37,7 +37,8 @@
|
||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.5-beta6" date="2009-??-??">
|
<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">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="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>
|
<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! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.5-beta6" date="2009-??-??">
|
<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">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="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>
|
<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) {
|
} else if (windowTwo != null) {
|
||||||
// probably 'Custom View Settings' sub-stream which is found between
|
// probably 'Custom View Settings' sub-stream which is found between
|
||||||
// USERSVIEWBEGIN(01AA) and USERSVIEWEND(01AB)
|
// 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"
|
// 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
|
// not quite the expected situation
|
||||||
throw new RuntimeException("two Page Settings Blocks found in the same sheet");
|
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 SHEETEXT_0862 = 0x0862; // OOO calls this SHEETLAYOUT
|
||||||
public static final int SHEETPROTECTION_0867 = 0x0867;
|
public static final int SHEETPROTECTION_0867 = 0x0867;
|
||||||
public static final int RANGEPROTECTION_0868 = 0x0868;
|
public static final int RANGEPROTECTION_0868 = 0x0868;
|
||||||
|
public static final int HEADER_FOOTER_089C = 0x089C;
|
||||||
|
|
||||||
private int _sid;
|
private int _sid;
|
||||||
private byte[] _rawData;
|
private byte[] _rawData;
|
||||||
|
@ -181,7 +182,7 @@ public final class UnknownRecord extends StandardRecord {
|
||||||
case 0x0897: return "GUIDTYPELIB";
|
case 0x0897: return "GUIDTYPELIB";
|
||||||
case 0x089A: return "MTRSETTINGS";
|
case 0x089A: return "MTRSETTINGS";
|
||||||
case 0x089B: return "COMPRESSPICTURES";
|
case 0x089B: return "COMPRESSPICTURES";
|
||||||
case 0x089C: return "HEADERFOOTER";
|
case HEADER_FOOTER_089C: return "HEADERFOOTER";
|
||||||
case 0x08A1: return "SHAPEPROPSSTREAM";
|
case 0x08A1: return "SHAPEPROPSSTREAM";
|
||||||
case 0x08A3: return "FORCEFULLCALCULATION";
|
case 0x08A3: return "FORCEFULLCALCULATION";
|
||||||
case 0x08A4: return "SHAPEPROPSSTREAM";
|
case 0x08A4: return "SHAPEPROPSSTREAM";
|
||||||
|
|
|
@ -71,6 +71,7 @@ public final class PageSettingsBlock extends RecordAggregate {
|
||||||
private List<ContinueRecord> _plsContinues;
|
private List<ContinueRecord> _plsContinues;
|
||||||
private PrintSetupRecord printSetup;
|
private PrintSetupRecord printSetup;
|
||||||
private Record _bitmap;
|
private Record _bitmap;
|
||||||
|
private Record _headerFooter;
|
||||||
|
|
||||||
public PageSettingsBlock(RecordStream rs) {
|
public PageSettingsBlock(RecordStream rs) {
|
||||||
while(true) {
|
while(true) {
|
||||||
|
@ -112,6 +113,7 @@ public final class PageSettingsBlock extends RecordAggregate {
|
||||||
case UnknownRecord.PLS_004D:
|
case UnknownRecord.PLS_004D:
|
||||||
case PrintSetupRecord.sid:
|
case PrintSetupRecord.sid:
|
||||||
case UnknownRecord.BITMAP_00E9:
|
case UnknownRecord.BITMAP_00E9:
|
||||||
|
case UnknownRecord.HEADER_FOOTER_089C: // extra header/footer settings supported by Excel 2007
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -164,6 +166,9 @@ public final class PageSettingsBlock extends RecordAggregate {
|
||||||
case UnknownRecord.BITMAP_00E9:
|
case UnknownRecord.BITMAP_00E9:
|
||||||
_bitmap = rs.getNext();
|
_bitmap = rs.getNext();
|
||||||
break;
|
break;
|
||||||
|
case UnknownRecord.HEADER_FOOTER_089C:
|
||||||
|
_headerFooter = rs.getNext();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// all other record types are not part of the PageSettingsBlock
|
// all other record types are not part of the PageSettingsBlock
|
||||||
return false;
|
return false;
|
||||||
|
@ -224,6 +229,7 @@ public final class PageSettingsBlock extends RecordAggregate {
|
||||||
}
|
}
|
||||||
visitIfPresent(printSetup, rv);
|
visitIfPresent(printSetup, rv);
|
||||||
visitIfPresent(_bitmap, rv);
|
visitIfPresent(_bitmap, rv);
|
||||||
|
visitIfPresent(_headerFooter, rv);
|
||||||
}
|
}
|
||||||
private static void visitIfPresent(Record r, RecordVisitor rv) {
|
private static void visitIfPresent(Record r, RecordVisitor rv) {
|
||||||
if (r != null) {
|
if (r != null) {
|
||||||
|
@ -523,4 +529,16 @@ public final class PageSettingsBlock extends RecordAggregate {
|
||||||
public HCenterRecord getHCenter() {
|
public HCenterRecord getHCenter() {
|
||||||
return _hCenter;
|
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;
|
package org.apache.poi.hssf.record.aggregates;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
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.HSSFPrintSetup;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
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}
|
* Tess for {@link PageSettingsBlock}
|
||||||
|
@ -47,4 +62,54 @@ public final class TestPageSettingBlock extends TestCase {
|
||||||
throw new AssertionFailedError("Identified bug 46548: PageSettingBlock missing PrintSetupRecord record");
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue