From 64509ab218d6ef5d856bc4ebbf3af241279e9714 Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Fri, 16 Jan 2009 23:13:11 +0000 Subject: [PATCH] Bug 46548 - fixes for Page Settings Block (patch from Dmitriy Kumshayev + some mods) git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@735179 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/changes.xml | 1 + src/documentation/content/xdocs/status.xml | 1 + src/java/org/apache/poi/hssf/model/Sheet.java | 71 +++++++++++- .../org/apache/poi/hssf/record/BOFRecord.java | 19 +++- .../apache/poi/hssf/record/UnknownRecord.java | 6 +- .../record/aggregates/PageSettingsBlock.java | 107 ++++++++++-------- .../apache/poi/hssf/data/ex46548-23133.xls | Bin 0 -> 22016 bytes .../org/apache/poi/hssf/model/TestSheet.java | 7 +- .../aggregates/AllRecordAggregateTests.java | 83 +++++++------- .../aggregates/TestPageSettingBlock.java | 50 ++++++++ 10 files changed, 244 insertions(+), 101 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/data/ex46548-23133.xls create mode 100644 src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingBlock.java diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 0502ddc4b1..dbac53ad9b 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -37,6 +37,7 @@ + 46548 - Print Settings Block fixes - continued PLS records and PSB in sheet sub-streams 46523 - added implementation for SUMIF function Support for reading HSSF column styles Hook up POIXMLTextExtractor.getMetadataTextExtractor() to the already written POIXMLPropertiesTextExtractor diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index aaab68a12f..93ab10e196 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 46548 - Print Settings Block fixes - continued PLS records and PSB in sheet sub-streams 46523 - added implementation for SUMIF function Support for reading HSSF column styles Hook up POIXMLTextExtractor.getMetadataTextExtractor() to the already written POIXMLPropertiesTextExtractor diff --git a/src/java/org/apache/poi/hssf/model/Sheet.java b/src/java/org/apache/poi/hssf/model/Sheet.java index 834d33d741..472fec9152 100644 --- a/src/java/org/apache/poi/hssf/model/Sheet.java +++ b/src/java/org/apache/poi/hssf/model/Sheet.java @@ -56,6 +56,7 @@ import org.apache.poi.hssf.record.SaveRecalcRecord; import org.apache.poi.hssf.record.ScenarioProtectRecord; import org.apache.poi.hssf.record.SelectionRecord; import org.apache.poi.hssf.record.UncalcedRecord; +import org.apache.poi.hssf.record.UnknownRecord; import org.apache.poi.hssf.record.WSBoolRecord; import org.apache.poi.hssf.record.WindowTwoRecord; import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate; @@ -163,9 +164,18 @@ public final class Sheet implements Model { records = new ArrayList(128); // TODO - take chart streams off into separate java objects - int bofEofNestingLevel = 0; // nesting level can only get to 2 (when charts are present) + int bofEofNestingLevel = 1; // nesting level can only get to 2 (when charts are present) int dimsloc = -1; + if (rs.peekNextSid() == BOFRecord.sid) { + BOFRecord bof = (BOFRecord) rs.getNext(); + if (bof.getType() != BOFRecord.TYPE_WORKSHEET) { + // TODO - fix junit tests throw new RuntimeException("Bad BOF record type"); + } + records.add(bof); + } else { + throw new RuntimeException("BOF record expected"); + } while (rs.hasNext()) { int recSid = rs.peekNextSid(); @@ -200,12 +210,34 @@ public final class Sheet implements Model { if (PageSettingsBlock.isComponentRecord(recSid)) { PageSettingsBlock psb = new PageSettingsBlock(rs); - if (bofEofNestingLevel == 1) { - if (_psBlock == null) { - _psBlock = psb; + if (_psBlock == null) { + _psBlock = psb; + } else { + if (bofEofNestingLevel == 2) { + // It's normal for a chart to have its own PageSettingsBlock + // Fall through and add psb here, because chart records + // are stored loose among the sheet records. + // this latest psb does not clash with _psBlock + } else if (windowTwo != null) { + // probably 'Custom View Settings' sub-stream which is found between + // USERSVIEWBEGIN(01AA) and USERSVIEWEND(01AB) + // This happens three times in test sample file "29982.xls" + if (rs.peekNextSid() != UnknownRecord.USERSVIEWEND_01AB) { + // not quite the expected situation + throw new RuntimeException("two Page Settings Blocks found in the same sheet"); + } } else { - // more than one 'Page Settings Block' at nesting level 1 ? - // apparently this happens in about 15 test sample files + // Some apps write PLS, WSBOOL, but PLS is part of + // This happens in the test sample file "NoGutsRecords.xls" and "WORKBOOK_in_capitals.xls" + // In this case the first PSB is two records back + int prevPsbIx = records.size()-2; + if (_psBlock != records.get(prevPsbIx) || !(records.get(prevPsbIx+1) instanceof WSBoolRecord)) { + // not quite the expected situation + throw new RuntimeException("two Page Settings Blocks found in the same sheet"); + } + records.remove(prevPsbIx); // WSBOOL will drop down one position. + psb = mergePSBs(_psBlock, psb); + _psBlock = psb; } } records.add(psb); @@ -332,7 +364,34 @@ public final class Sheet implements Model { if (log.check( POILogger.DEBUG )) log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited"); } + /** + * Hack to recover from the situation where the page settings block has been split by + * an intervening {@link WSBoolRecord} + */ + private static PageSettingsBlock mergePSBs(PageSettingsBlock a, PageSettingsBlock b) { + List temp = new ArrayList(); + RecordTransferrer rt = new RecordTransferrer(temp); + a.visitContainedRecords(rt); + b.visitContainedRecords(rt); + RecordStream rs = new RecordStream(temp, 0); + PageSettingsBlock result = new PageSettingsBlock(rs); + if (rs.hasNext()) { + throw new RuntimeException("PageSettingsBlocks did not merge properly"); + } + return result; + } + private static final class RecordTransferrer implements RecordVisitor { + + private final List _destList; + + public RecordTransferrer(List destList) { + _destList = destList; + } + public void visitRecord(Record r) { + _destList.add(r); + } + } private static final class RecordCloner implements RecordVisitor { private final List _destList; diff --git a/src/java/org/apache/poi/hssf/record/BOFRecord.java b/src/java/org/apache/poi/hssf/record/BOFRecord.java index f67a67028d..9e661a5531 100644 --- a/src/java/org/apache/poi/hssf/record/BOFRecord.java +++ b/src/java/org/apache/poi/hssf/record/BOFRecord.java @@ -20,6 +20,8 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndianOutput; +import com.sun.java_cup.internal.version; + /** * Title: Beginning Of File (0x0809)

* Description: Somewhat of a misnomer, its used for the beginning of a set of @@ -35,8 +37,8 @@ public final class BOFRecord extends StandardRecord { */ public final static short sid = 0x809; - /** suggested default (0x06 - BIFF8) */ - public final static int VERSION = 0x06; + /** suggested default (0x0600 - BIFF8) */ + public final static int VERSION = 0x0600; /** suggested default 0x10d3 */ public final static int BUILD = 0x10d3; /** suggested default 0x07CC (1996) */ @@ -63,6 +65,19 @@ public final class BOFRecord extends StandardRecord { */ public BOFRecord() { } + + private BOFRecord(int type) { + field_1_version = VERSION; + field_2_type = type; + field_3_build = BUILD; + field_4_year = BUILD_YEAR; + field_5_history = 0x01; + field_6_rversion = VERSION; + } + + public static BOFRecord createSheetBOF() { + return new BOFRecord(TYPE_WORKSHEET); + } public BOFRecord(RecordInputStream in) { field_1_version = in.readShort(); diff --git a/src/java/org/apache/poi/hssf/record/UnknownRecord.java b/src/java/org/apache/poi/hssf/record/UnknownRecord.java index 6ece4782f8..e3cef59d9f 100644 --- a/src/java/org/apache/poi/hssf/record/UnknownRecord.java +++ b/src/java/org/apache/poi/hssf/record/UnknownRecord.java @@ -42,6 +42,8 @@ public final class UnknownRecord extends StandardRecord { public static final int BITMAP_00E9 = 0x00E9; public static final int PHONETICPR_00EF = 0x00EF; public static final int LABELRANGES_015F = 0x015F; + public static final int USERSVIEWBEGIN_01AA = 0x01AA; + public static final int USERSVIEWEND_01AB = 0x01AB; public static final int QUICKTIP_0800 = 0x0800; public static final int SHEETEXT_0862 = 0x0862; // OOO calls this SHEETLAYOUT public static final int SHEETPROTECTION_0867 = 0x0867; @@ -145,8 +147,8 @@ public final class UnknownRecord extends StandardRecord { case LABELRANGES_015F: return "LABELRANGES"; case 0x01BA: return "CODENAME"; case 0x01A9: return "USERBVIEW"; - case 0x01AA: return "USERSVIEWBEGIN"; - case 0x01AB: return "USERSVIEWEND"; + case USERSVIEWBEGIN_01AA: return "USERSVIEWBEGIN"; + case USERSVIEWEND_01AB: return "USERSVIEWEND"; case 0x01AD: return "QSI"; case 0x01C0: return "EXCEL9FILE"; diff --git a/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java b/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java index 68d4559a36..828c0e31f6 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java @@ -19,11 +19,13 @@ package org.apache.poi.hssf.record.aggregates; import java.util.ArrayList; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import org.apache.poi.hssf.model.RecordStream; import org.apache.poi.hssf.model.Sheet; import org.apache.poi.hssf.record.BottomMarginRecord; +import org.apache.poi.hssf.record.ContinueRecord; import org.apache.poi.hssf.record.FooterRecord; import org.apache.poi.hssf.record.HCenterRecord; import org.apache.poi.hssf.record.HeaderRecord; @@ -60,6 +62,13 @@ public final class PageSettingsBlock extends RecordAggregate { private TopMarginRecord _topMargin; private BottomMarginRecord _bottomMargin; private Record _pls; + /** + * holds any continue records found after the PLS record.
+ * This would not be required if PLS was properly interpreted. + * Currently, PLS is an {@link UnknownRecord} and does not automatically + * include any trailing {@link ContinueRecord}s. + */ + private List _plsContinues; private PrintSetupRecord printSetup; private Record _bitmap; @@ -140,13 +149,19 @@ public final class PageSettingsBlock extends RecordAggregate { case BottomMarginRecord.sid: _bottomMargin = (BottomMarginRecord) rs.getNext(); break; - case 0x004D: // PLS + case UnknownRecord.PLS_004D: _pls = rs.getNext(); + while (rs.peekNextSid()==ContinueRecord.sid) { + if (_plsContinues==null) { + _plsContinues = new LinkedList(); + } + _plsContinues.add((ContinueRecord)rs.getNext()); + } break; case PrintSetupRecord.sid: printSetup = (PrintSetupRecord)rs.getNext(); break; - case 0x00E9: // BITMAP + case UnknownRecord.BITMAP_00E9: _bitmap = rs.getNext(); break; default: @@ -202,6 +217,11 @@ public final class PageSettingsBlock extends RecordAggregate { visitIfPresent(_topMargin, rv); visitIfPresent(_bottomMargin, rv); visitIfPresent(_pls, rv); + if (_plsContinues != null) { + for (ContinueRecord cr : _plsContinues) { + visitIfPresent(cr, rv); + } + } visitIfPresent(printSetup, rv); visitIfPresent(_bitmap, rv); } @@ -335,58 +355,51 @@ public final class PageSettingsBlock extends RecordAggregate { * @param margin which margin to get * @return the size of the margin */ - public double getMargin(short margin) { - Margin m = getMarginRec(margin); - if (m != null) { - return m.getMargin(); - } else { - switch ( margin ) - { - case Sheet.LeftMargin: - return .75; - case Sheet.RightMargin: - return .75; - case Sheet.TopMargin: - return 1.0; - case Sheet.BottomMargin: - return 1.0; - } + public double getMargin(short margin) { + Margin m = getMarginRec(margin); + if (m != null) { + return m.getMargin(); + } + switch (margin) { + case Sheet.LeftMargin: return .75; + case Sheet.RightMargin: return .75; + case Sheet.TopMargin: return 1.0; + case Sheet.BottomMargin: return 1.0; + } throw new RuntimeException( "Unknown margin constant: " + margin ); - } - } + } /** * Sets the size of the margin in inches. * @param margin which margin to get * @param size the size of the margin */ - public void setMargin(short margin, double size) { - Margin m = getMarginRec(margin); - if (m == null) { - switch ( margin ) - { - case Sheet.LeftMargin: - _leftMargin = new LeftMarginRecord(); - m = _leftMargin; - break; - case Sheet.RightMargin: - _rightMargin = new RightMarginRecord(); - m = _rightMargin; - break; - case Sheet.TopMargin: - _topMargin = new TopMarginRecord(); - m = _topMargin; - break; - case Sheet.BottomMargin: - _bottomMargin = new BottomMarginRecord(); - m = _bottomMargin; - break; - default : - throw new RuntimeException( "Unknown margin constant: " + margin ); - } - } - m.setMargin( size ); - } + public void setMargin(short margin, double size) { + Margin m = getMarginRec(margin); + if (m == null) { + switch (margin) { + case Sheet.LeftMargin: + _leftMargin = new LeftMarginRecord(); + m = _leftMargin; + break; + case Sheet.RightMargin: + _rightMargin = new RightMarginRecord(); + m = _rightMargin; + break; + case Sheet.TopMargin: + _topMargin = new TopMarginRecord(); + m = _topMargin; + break; + case Sheet.BottomMargin: + _bottomMargin = new BottomMarginRecord(); + m = _bottomMargin; + break; + default : + throw new RuntimeException( "Unknown margin constant: " + margin ); + } + } + m.setMargin( size ); + } /** * Shifts all the page breaks in the range "count" number of rows/columns diff --git a/src/testcases/org/apache/poi/hssf/data/ex46548-23133.xls b/src/testcases/org/apache/poi/hssf/data/ex46548-23133.xls new file mode 100644 index 0000000000000000000000000000000000000000..cc1fe3a2914418f7ad51a56b84ed8b443c1c23b7 GIT binary patch literal 22016 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 records = new ArrayList(); - records.add( new BOFRecord() ); + records.add(BOFRecord.createSheetBOF()); records.add( new DimensionsRecord() ); records.add(createWindow2Record()); records.add(EOFRecord.instance); @@ -187,6 +187,7 @@ public final class TestSheet extends TestCase { new CellRangeAddress(0, 1, 0, 2), }; MergeCellsRecord merged = new MergeCellsRecord(cras, 0, cras.length); + records.add(BOFRecord.createSheetBOF()); records.add(new DimensionsRecord()); records.add(new RowRecord(0)); records.add(new RowRecord(1)); @@ -449,7 +450,7 @@ public final class TestSheet extends TestCase { public void testUncalcSize_bug45066() { List records = new ArrayList(); - records.add(new BOFRecord()); + records.add(BOFRecord.createSheetBOF()); records.add(new UncalcedRecord()); records.add(new DimensionsRecord()); records.add(createWindow2Record()); @@ -600,7 +601,7 @@ public final class TestSheet extends TestCase { nr.setValue(3.0); List inRecs = new ArrayList(); - inRecs.add(new BOFRecord()); + inRecs.add(BOFRecord.createSheetBOF()); inRecs.add(new RowRecord(rowIx)); inRecs.add(nr); inRecs.add(createWindow2Record()); diff --git a/src/testcases/org/apache/poi/hssf/record/aggregates/AllRecordAggregateTests.java b/src/testcases/org/apache/poi/hssf/record/aggregates/AllRecordAggregateTests.java index aafe082582..e19f182f77 100644 --- a/src/testcases/org/apache/poi/hssf/record/aggregates/AllRecordAggregateTests.java +++ b/src/testcases/org/apache/poi/hssf/record/aggregates/AllRecordAggregateTests.java @@ -1,41 +1,42 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hssf.record.aggregates; - -import junit.framework.Test; -import junit.framework.TestSuite; - -/** - * Collects all tests for package org.apache.poi.hssf.record.aggregates. - * - * @author Josh Micich - */ -public final class AllRecordAggregateTests { - - public static Test suite() { - TestSuite result = new TestSuite(AllRecordAggregateTests.class.getName()); - - result.addTestSuite(TestCFRecordsAggregate.class); - result.addTestSuite(TestColumnInfoRecordsAggregate.class); - result.addTestSuite(TestFormulaRecordAggregate.class); - result.addTestSuite(TestRowRecordsAggregate.class); - result.addTestSuite(TestSharedValueManager.class); - result.addTestSuite(TestValueRecordsAggregate.class); - return result; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.record.aggregates; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Collects all tests for package org.apache.poi.hssf.record.aggregates. + * + * @author Josh Micich + */ +public final class AllRecordAggregateTests { + + public static Test suite() { + TestSuite result = new TestSuite(AllRecordAggregateTests.class.getName()); + + result.addTestSuite(TestCFRecordsAggregate.class); + result.addTestSuite(TestColumnInfoRecordsAggregate.class); + result.addTestSuite(TestFormulaRecordAggregate.class); + result.addTestSuite(TestRowRecordsAggregate.class); + result.addTestSuite(TestSharedValueManager.class); + result.addTestSuite(TestValueRecordsAggregate.class); + result.addTestSuite(TestPageSettingBlock.class); + return result; + } +} diff --git a/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingBlock.java b/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingBlock.java new file mode 100644 index 0000000000..518ed5f308 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingBlock.java @@ -0,0 +1,50 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.record.aggregates; + +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; + +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.usermodel.HSSFPrintSetup; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; + +/** + * Tess for {@link PageSettingsBlock} + * + * @author Dmitriy Kumshayev + */ +public final class TestPageSettingBlock extends TestCase { + + public void testPrintSetup_bug46548() { + + // PageSettingBlock in this file contains PLS (sid=x004D) record + // followed by ContinueRecord (sid=x003C) + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ex46548-23133.xls"); + HSSFSheet sheet = wb.getSheetAt(0); + HSSFPrintSetup ps = sheet.getPrintSetup(); + + try { + ps.getCopies(); + } catch (NullPointerException e) { + e.printStackTrace(); + throw new AssertionFailedError("Identified bug 46548: PageSettingBlock missing PrintSetupRecord record"); + } + } +} -- 2.39.5