From ad181534cf8f07dd3b8057a5b1689deeca1d72b0 Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Fri, 8 Aug 2008 06:27:06 +0000 Subject: [PATCH] Extracting PageSettingsBlock from Sheet git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@683871 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/model/RecordOrderer.java | 30 +- .../apache/poi/hssf/model/RecordStream.java | 7 + src/java/org/apache/poi/hssf/model/Sheet.java | 330 +++-------- .../poi/hssf/record/PrintSetupRecord.java | 15 +- .../record/aggregates/PageSettingsBlock.java | 526 ++++++++++++++++++ .../apache/poi/hssf/usermodel/HSSFSheet.java | 19 +- .../poi/hssf/usermodel/SanityChecker.java | 16 +- .../poi/hssf/usermodel/TestHSSFSheet.java | 6 +- 8 files changed, 620 insertions(+), 329 deletions(-) create mode 100644 src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java diff --git a/src/java/org/apache/poi/hssf/model/RecordOrderer.java b/src/java/org/apache/poi/hssf/model/RecordOrderer.java index ae445597d1..887497a911 100644 --- a/src/java/org/apache/poi/hssf/model/RecordOrderer.java +++ b/src/java/org/apache/poi/hssf/model/RecordOrderer.java @@ -29,7 +29,6 @@ import org.apache.poi.hssf.record.DimensionsRecord; import org.apache.poi.hssf.record.EOFRecord; import org.apache.poi.hssf.record.GridsetRecord; import org.apache.poi.hssf.record.GutsRecord; -import org.apache.poi.hssf.record.HorizontalPageBreakRecord; import org.apache.poi.hssf.record.HyperlinkRecord; import org.apache.poi.hssf.record.IndexRecord; import org.apache.poi.hssf.record.IterationRecord; @@ -44,11 +43,11 @@ import org.apache.poi.hssf.record.SCLRecord; import org.apache.poi.hssf.record.SaveRecalcRecord; import org.apache.poi.hssf.record.SelectionRecord; import org.apache.poi.hssf.record.UncalcedRecord; -import org.apache.poi.hssf.record.VerticalPageBreakRecord; import org.apache.poi.hssf.record.WindowTwoRecord; import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable; import org.apache.poi.hssf.record.aggregates.DataValidityTable; import org.apache.poi.hssf.record.aggregates.MergedCellsTable; +import org.apache.poi.hssf.record.aggregates.PageSettingsBlock; /** * Finds correct insert positions for records in workbook streams

@@ -88,28 +87,25 @@ final class RecordOrderer { if (recClass == GutsRecord.class) { return getGutsRecordInsertPos(records); } - if (recClass == HorizontalPageBreakRecord.class) { - return getPageBreakRecordInsertPos(records, true); - } - if (recClass == VerticalPageBreakRecord.class) { - return getPageBreakRecordInsertPos(records, false); + if (recClass == PageSettingsBlock.class) { + return getPageBreakRecordInsertPos(records); } throw new RuntimeException("Unexpected record class (" + recClass.getName() + ")"); } - private static int getPageBreakRecordInsertPos(List records, boolean isHorizonal) { + private static int getPageBreakRecordInsertPos(List records) { int dimensionsIndex = getDimensionsIndex(records); int i = dimensionsIndex-1; while (i > 0) { i--; Object rb = records.get(i); - if (isPageBreakPriorRecord(rb, isHorizonal)) { + if (isPageBreakPriorRecord(rb)) { return i+1; } } throw new RuntimeException("Did not find insert point for GUTS"); } - private static boolean isPageBreakPriorRecord(Object rb, boolean newRecIsHorizontal) { + private static boolean isPageBreakPriorRecord(Object rb) { if (rb instanceof Record) { Record record = (Record) rb; switch (record.getSid()) { @@ -132,19 +128,7 @@ final class RecordOrderer { case DefaultRowHeightRecord.sid: case 0x0081: // SHEETPR return true; - } - switch (record.getSid()) { - // page settings block - case HorizontalPageBreakRecord.sid: - if (!newRecIsHorizontal) { - return true; - } - return false; - case VerticalPageBreakRecord.sid: - return false; - // next is case HeaderRecord.sid: case FooterRecord.sid: - // then more records in page settings block - + // next is the 'Worksheet Protection Block' } } return false; diff --git a/src/java/org/apache/poi/hssf/model/RecordStream.java b/src/java/org/apache/poi/hssf/model/RecordStream.java index bec1c40e6a..1a06873954 100755 --- a/src/java/org/apache/poi/hssf/model/RecordStream.java +++ b/src/java/org/apache/poi/hssf/model/RecordStream.java @@ -59,6 +59,13 @@ public final class RecordStream { return _list.get(_nextIndex).getClass(); } + public int peekNextSid() { + if(_nextIndex >= _list.size()) { + return -1; + } + return ((Record)_list.get(_nextIndex)).getSid(); + } + public int getCountRead() { return _countRead; } diff --git a/src/java/org/apache/poi/hssf/model/Sheet.java b/src/java/org/apache/poi/hssf/model/Sheet.java index 11ee42b6a9..d49c0f72d9 100644 --- a/src/java/org/apache/poi/hssf/model/Sheet.java +++ b/src/java/org/apache/poi/hssf/model/Sheet.java @@ -22,7 +22,6 @@ import java.util.Iterator; import java.util.List; import org.apache.poi.hssf.record.BOFRecord; -import org.apache.poi.hssf.record.BottomMarginRecord; import org.apache.poi.hssf.record.CFHeaderRecord; import org.apache.poi.hssf.record.CalcCountRecord; import org.apache.poi.hssf.record.CalcModeRecord; @@ -40,17 +39,12 @@ import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.FooterRecord; import org.apache.poi.hssf.record.GridsetRecord; import org.apache.poi.hssf.record.GutsRecord; -import org.apache.poi.hssf.record.HCenterRecord; import org.apache.poi.hssf.record.HeaderRecord; -import org.apache.poi.hssf.record.HorizontalPageBreakRecord; import org.apache.poi.hssf.record.IndexRecord; import org.apache.poi.hssf.record.IterationRecord; -import org.apache.poi.hssf.record.LeftMarginRecord; -import org.apache.poi.hssf.record.Margin; import org.apache.poi.hssf.record.MergeCellsRecord; import org.apache.poi.hssf.record.ObjRecord; import org.apache.poi.hssf.record.ObjectProtectRecord; -import org.apache.poi.hssf.record.PageBreakRecord; import org.apache.poi.hssf.record.PaneRecord; import org.apache.poi.hssf.record.PasswordRecord; import org.apache.poi.hssf.record.PrintGridlinesRecord; @@ -60,17 +54,13 @@ import org.apache.poi.hssf.record.ProtectRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.RecordBase; import org.apache.poi.hssf.record.RefModeRecord; -import org.apache.poi.hssf.record.RightMarginRecord; import org.apache.poi.hssf.record.RowRecord; import org.apache.poi.hssf.record.SCLRecord; 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.StringRecord; -import org.apache.poi.hssf.record.TopMarginRecord; import org.apache.poi.hssf.record.UncalcedRecord; -import org.apache.poi.hssf.record.VCenterRecord; -import org.apache.poi.hssf.record.VerticalPageBreakRecord; import org.apache.poi.hssf.record.WSBoolRecord; import org.apache.poi.hssf.record.WindowTwoRecord; import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate; @@ -78,6 +68,7 @@ import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate; import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable; import org.apache.poi.hssf.record.aggregates.DataValidityTable; import org.apache.poi.hssf.record.aggregates.MergedCellsTable; +import org.apache.poi.hssf.record.aggregates.PageSettingsBlock; import org.apache.poi.hssf.record.aggregates.RecordAggregate; import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor; @@ -119,33 +110,32 @@ public final class Sheet implements Model { protected ArrayList records = null; int preoffset = 0; // offset of the sheet in a new file protected int dimsloc = -1; // TODO - is it legal for dims record to be missing? - protected DimensionsRecord dims; - protected DefaultColWidthRecord defaultcolwidth = null; - protected DefaultRowHeightRecord defaultrowheight = null; + protected PrintGridlinesRecord printGridlines = null; protected GridsetRecord gridset = null; private GutsRecord _gutsRecord; - protected PrintSetupRecord printSetup = null; - protected HeaderRecord header = null; - protected FooterRecord footer = null; - protected PrintGridlinesRecord printGridlines = null; - protected WindowTwoRecord windowTwo = null; - protected Margin[] margins = null; - private MergedCellsTable _mergedCellsTable; - protected SelectionRecord selection = null; - /** always present in this POI object, not always written to Excel file */ - /*package*/ColumnInfoRecordsAggregate _columnInfos; - protected RowRecordsAggregate _rowsAggregate = null; - private Iterator rowRecIterator = null; - protected int eofLoc = 0; + protected DefaultColWidthRecord defaultcolwidth = null; + protected DefaultRowHeightRecord defaultrowheight = null; + private PageSettingsBlock _psBlock; + + // 'Worksheet Protection Block' protected ProtectRecord protect = null; - protected PageBreakRecord _rowBreaksRecord; - protected PageBreakRecord _columnBreaksRecord; - private DataValidityTable _dataValidityTable= null; protected ObjectProtectRecord objprotect = null; protected ScenarioProtectRecord scenprotect = null; protected PasswordRecord password = null; + + protected WindowTwoRecord windowTwo = null; + protected SelectionRecord selection = null; + private MergedCellsTable _mergedCellsTable; + /** always present in this POI object, not always written to Excel file */ + /*package*/ColumnInfoRecordsAggregate _columnInfos; + protected DimensionsRecord dims; + protected RowRecordsAggregate _rowsAggregate = null; + private DataValidityTable _dataValidityTable= null; private ConditionalFormattingTable condFormatting; + protected int eofLoc = 0; + private Iterator rowRecIterator = null; + /** Add an UncalcedRecord if not true indicating formulas have not been calculated */ protected boolean _isUncalced = false; @@ -247,13 +237,28 @@ public final class Sheet implements Model { } continue; } - + + if (PageSettingsBlock.isComponentRecord(rec.getSid())) { + RecordStream rs = new RecordStream(recs, k); + PageSettingsBlock psb = new PageSettingsBlock(rs); + if (bofEofNestingLevel == 1) { + if (retval._psBlock == null) { + retval._psBlock = psb; + } else { + // more than one 'Page Settings Block' at nesting level 1 ? + // apparently this happens in about 15 test sample files + } + } + records.add(psb); + k += rs.getCountRead()-1; + continue; + } if (rec.getSid() == MergeCellsRecord.sid) { RecordStream rs = new RecordStream(recs, k); retval._mergedCellsTable = new MergedCellsTable(rs); records.add(retval._mergedCellsTable); - continue; // TODO + continue; } if (rec.getSid() == BOFRecord.sid) @@ -304,34 +309,6 @@ public final class Sheet implements Model { { retval.gridset = (GridsetRecord) rec; } - else if ( rec.getSid() == HeaderRecord.sid && bofEofNestingLevel == 1) - { - retval.header = (HeaderRecord) rec; - } - else if ( rec.getSid() == FooterRecord.sid && bofEofNestingLevel == 1) - { - retval.footer = (FooterRecord) rec; - } - else if ( rec.getSid() == PrintSetupRecord.sid && bofEofNestingLevel == 1) - { - retval.printSetup = (PrintSetupRecord) rec; - } - else if ( rec.getSid() == LeftMarginRecord.sid) - { - retval.getMargins()[LeftMargin] = (LeftMarginRecord) rec; - } - else if ( rec.getSid() == RightMarginRecord.sid) - { - retval.getMargins()[RightMargin] = (RightMarginRecord) rec; - } - else if ( rec.getSid() == TopMarginRecord.sid) - { - retval.getMargins()[TopMargin] = (TopMarginRecord) rec; - } - else if ( rec.getSid() == BottomMarginRecord.sid) - { - retval.getMargins()[BottomMargin] = (BottomMarginRecord) rec; - } else if ( rec.getSid() == SelectionRecord.sid ) { retval.selection = (SelectionRecord) rec; @@ -356,14 +333,6 @@ public final class Sheet implements Model { { retval.password = (PasswordRecord) rec; } - else if (rec.getSid() == HorizontalPageBreakRecord.sid) - { - retval._rowBreaksRecord = (HorizontalPageBreakRecord)rec; - } - else if (rec.getSid() == VerticalPageBreakRecord.sid) - { - retval._columnBreaksRecord = (VerticalPageBreakRecord)rec; - } records.add(rec); } @@ -463,20 +432,9 @@ public final class Sheet implements Model { records.add( retval.createWSBool() ); // 'Page Settings Block' - retval._rowBreaksRecord = new HorizontalPageBreakRecord(); - records.add(retval._rowBreaksRecord); - retval._columnBreaksRecord = new VerticalPageBreakRecord(); - records.add(retval._columnBreaksRecord); - - retval.header = createHeader(); - records.add( retval.header ); - retval.footer = createFooter(); - records.add( retval.footer ); - records.add(createHCenter() ); - records.add(createVCenter() ); - retval.printSetup = createPrintSetup(); - records.add( retval.printSetup ); - + retval._psBlock = new PageSettingsBlock(); + records.add(retval._psBlock); + // 'Worksheet Protection Block' (after 'Page Settings Block' and before DEFCOLWIDTH) // PROTECT record normally goes here, don't add yet since the flag is initially false @@ -1061,70 +1019,6 @@ public final class Sheet implements Model { return retval; } - /** - * creates the Header Record and sets it to nothing/0 length - */ - private static HeaderRecord createHeader() { - HeaderRecord retval = new HeaderRecord(); - - retval.setHeaderLength(( byte ) 0); - retval.setHeader(null); - return retval; - } - - /** - * creates the Footer Record and sets it to nothing/0 length - */ - private static FooterRecord createFooter() { - FooterRecord retval = new FooterRecord(); - - retval.setFooterLength(( byte ) 0); - retval.setFooter(null); - return retval; - } - - /** - * creates the HCenter Record and sets it to false (don't horizontally center) - */ - private static HCenterRecord createHCenter() { - HCenterRecord retval = new HCenterRecord(); - - retval.setHCenter(false); - return retval; - } - - /** - * creates the VCenter Record and sets it to false (don't horizontally center) - */ - private static VCenterRecord createVCenter() { - VCenterRecord retval = new VCenterRecord(); - - retval.setVCenter(false); - return retval; - } - - /** - * creates the PrintSetup Record and sets it to defaults and marks it invalid - * @see org.apache.poi.hssf.record.PrintSetupRecord - * @see org.apache.poi.hssf.record.Record - * @return record containing a PrintSetupRecord - */ - private static PrintSetupRecord createPrintSetup() { - PrintSetupRecord retval = new PrintSetupRecord(); - - retval.setPaperSize(( short ) 1); - retval.setScale(( short ) 100); - retval.setPageStart(( short ) 1); - retval.setFitWidth(( short ) 1); - retval.setFitHeight(( short ) 1); - retval.setOptions(( short ) 2); - retval.setHResolution(( short ) 300); - retval.setVResolution(( short ) 300); - retval.setHeaderMargin( 0.5); - retval.setFooterMargin( 0.5); - retval.setCopies(( short ) 0); - return retval; - } /** * creates the DefaultColWidth Record and sets it to 8 @@ -1563,7 +1457,7 @@ public final class Sheet implements Model { */ public HeaderRecord getHeader () { - return header; + return getPageSettings().getHeader(); } public WindowTwoRecord getWindowTwo() { @@ -1575,7 +1469,7 @@ public final class Sheet implements Model { */ public void setHeader (HeaderRecord newHeader) { - header = newHeader; + getPageSettings().setHeader(newHeader); } /** @@ -1584,7 +1478,7 @@ public final class Sheet implements Model { */ public FooterRecord getFooter () { - return footer; + return getPageSettings().getFooter(); } /** @@ -1593,7 +1487,7 @@ public final class Sheet implements Model { */ public void setFooter (FooterRecord newFooter) { - footer = newFooter; + getPageSettings().setFooter(newFooter); } /** @@ -1602,7 +1496,7 @@ public final class Sheet implements Model { */ public PrintSetupRecord getPrintSetup () { - return printSetup; + return getPageSettings().getPrintSetup(); } /** @@ -1611,7 +1505,7 @@ public final class Sheet implements Model { */ public void setPrintSetup (PrintSetupRecord newPrintSetup) { - printSetup = newPrintSetup; + getPageSettings().setPrintSetup(newPrintSetup); } /** @@ -1646,23 +1540,7 @@ public final class Sheet implements Model { * @return the size of the margin */ public double getMargin(short margin) { - if (getMargins()[margin] != null) - return margins[margin].getMargin(); - else { - switch ( margin ) - { - case LeftMargin: - return .75; - case RightMargin: - return .75; - case TopMargin: - return 1.0; - case BottomMargin: - return 1.0; - default : - throw new RuntimeException( "Unknown margin constant: " + margin ); - } - } + return getPageSettings().getMargin(margin); } /** @@ -1671,32 +1549,7 @@ public final class Sheet implements Model { * @param size the size of the margin */ public void setMargin(short margin, double size) { - Margin m = getMargins()[margin]; - if (m == null) { - switch ( margin ) - { - case LeftMargin: - m = new LeftMarginRecord(); - records.add( getDimsLoc() + 1, m ); - break; - case RightMargin: - m = new RightMarginRecord(); - records.add( getDimsLoc() + 1, m ); - break; - case TopMargin: - m = new TopMarginRecord(); - records.add( getDimsLoc() + 1, m ); - break; - case BottomMargin: - m = new BottomMarginRecord(); - records.add( getDimsLoc() + 1, m ); - break; - default : - throw new RuntimeException( "Unknown margin constant: " + margin ); - } - margins[margin] = m; - } - m.setMargin( size ); + getPageSettings().setMargin(margin, size); } public int getEofLoc() @@ -1947,17 +1800,6 @@ public final class Sheet implements Model { this._isUncalced = uncalced; } - /** - * Returns the array of margins. If not created, will create. - * - * @return the array of marings. - */ - protected Margin[] getMargins() { - if (margins == null) - margins = new Margin[4]; - return margins; - } - /** * Finds the DrawingRecord for our sheet, and * attaches it to the DrawingManager (which knows about @@ -2026,60 +1868,22 @@ public final class Sheet implements Model { } } - /** - * Shifts all the page breaks in the range "count" number of rows/columns - * @param breaks The page record to be shifted - * @param start Starting "main" value to shift breaks - * @param stop Ending "main" value to shift breaks - * @param count number of units (rows/columns) to shift by - */ - private static void shiftBreaks(PageBreakRecord breaks, int start, int stop, int count) { - - Iterator iterator = breaks.getBreaksIterator(); - List shiftedBreak = new ArrayList(); - while(iterator.hasNext()) - { - PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next(); - int breakLocation = breakItem.main; - boolean inStart = (breakLocation >= start); - boolean inEnd = (breakLocation <= stop); - if(inStart && inEnd) - shiftedBreak.add(breakItem); - } - - iterator = shiftedBreak.iterator(); - while (iterator.hasNext()) { - PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next(); - breaks.removeBreak(breakItem.main); - breaks.addBreak((short)(breakItem.main+count), breakItem.subFrom, breakItem.subTo); - } - } - - private PageBreakRecord getRowBreaksRecord() { - if (_rowBreaksRecord == null) { - _rowBreaksRecord = new HorizontalPageBreakRecord(); - RecordOrderer.addNewSheetRecord(records, _rowBreaksRecord); + + public PageSettingsBlock getPageSettings() { + if (_psBlock == null) { + _psBlock = new PageSettingsBlock(); + RecordOrderer.addNewSheetRecord(records, _psBlock); dimsloc++; } - return _rowBreaksRecord; + return _psBlock; } - - private PageBreakRecord getColumnBreaksRecord() { - if (_columnBreaksRecord == null) { - _columnBreaksRecord = new VerticalPageBreakRecord(); - RecordOrderer.addNewSheetRecord(records, _columnBreaksRecord); - dimsloc++; - } - return _columnBreaksRecord; - } - - + /** * Sets a page break at the indicated row * @param row */ public void setRowBreak(int row, short fromCol, short toCol) { - getRowBreaksRecord().addBreak((short)row, fromCol, toCol); + getPageSettings().setRowBreak(row, fromCol, toCol); } /** @@ -2087,9 +1891,7 @@ public final class Sheet implements Model { * @param row */ public void removeRowBreak(int row) { - if (getRowBreaks() == null) - throw new IllegalArgumentException("Sheet does not define any row breaks"); - getRowBreaksRecord().removeBreak((short)row); + getPageSettings().removeRowBreak(row); } /** @@ -2098,7 +1900,7 @@ public final class Sheet implements Model { * @return true if the specified row has a page break */ public boolean isRowBroken(int row) { - return getRowBreaksRecord().getBreak(row) != null; + return getPageSettings().isRowBroken(row); } /** @@ -2106,7 +1908,7 @@ public final class Sheet implements Model { * */ public void setColumnBreak(short column, short fromRow, short toRow) { - getColumnBreaksRecord().addBreak(column, fromRow, toRow); + getPageSettings().setColumnBreak(column, fromRow, toRow); } /** @@ -2114,7 +1916,7 @@ public final class Sheet implements Model { * */ public void removeColumnBreak(short column) { - getColumnBreaksRecord().removeBreak(column); + getPageSettings().removeColumnBreak(column); } /** @@ -2123,7 +1925,7 @@ public final class Sheet implements Model { * @return true if the specified column has a page break */ public boolean isColumnBroken(short column) { - return getColumnBreaksRecord().getBreak(column) != null; + return getPageSettings().isColumnBroken(column); } /** @@ -2133,7 +1935,7 @@ public final class Sheet implements Model { * @param count */ public void shiftRowBreaks(int startingRow, int endingRow, int count) { - shiftBreaks(getRowBreaksRecord(), startingRow, endingRow, count); + getPageSettings().shiftRowBreaks(startingRow, endingRow, count); } /** @@ -2143,35 +1945,35 @@ public final class Sheet implements Model { * @param count */ public void shiftColumnBreaks(short startingCol, short endingCol, short count) { - shiftBreaks(getColumnBreaksRecord(), startingCol, endingCol, count); + getPageSettings().shiftColumnBreaks(startingCol, endingCol, count); } /** * @return all the horizontal page breaks, never null */ public int[] getRowBreaks() { - return getRowBreaksRecord().getBreaks(); + return getPageSettings().getRowBreaks(); } /** * @return the number of row page breaks */ public int getNumRowBreaks(){ - return getRowBreaksRecord().getNumBreaks(); + return getPageSettings().getNumRowBreaks(); } /** * @return all the column page breaks, never null */ public int[] getColumnBreaks(){ - return getColumnBreaksRecord().getBreaks(); + return getPageSettings().getColumnBreaks(); } /** * @return the number of column page breaks */ public int getNumColumnBreaks(){ - return getColumnBreaksRecord().getNumBreaks(); + return getPageSettings().getNumColumnBreaks(); } public void setColumnGroupCollapsed( short columnNumber, boolean collapsed ) diff --git a/src/java/org/apache/poi/hssf/record/PrintSetupRecord.java b/src/java/org/apache/poi/hssf/record/PrintSetupRecord.java index 874f304abd..a8518c7b31 100644 --- a/src/java/org/apache/poi/hssf/record/PrintSetupRecord.java +++ b/src/java/org/apache/poi/hssf/record/PrintSetupRecord.java @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -15,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - package org.apache.poi.hssf.record; @@ -24,18 +22,15 @@ import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; /** - * Title: Print Setup Record

- * Description: Stores print setup options -- bogus for HSSF (and marked as such)

- * REFERENCE: PG 385 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

+ * Title: PAGESETUP (0x00A1)

+ * Description: Stores print setup options -- bogus for HSSF (and marked as such)

+ * REFERENCE: PG 385 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)

* @author Andrew C. Oliver (acoliver at apache dot org) * @author Jason Height (jheight at chariot dot net dot au) * @version 2.0-pre */ - -public class PrintSetupRecord - extends Record -{ - public final static short sid = 0xa1; +public class PrintSetupRecord extends Record { + public final static short sid = 0x00A1; private short field_1_paper_size; private short field_2_scale; private short field_3_page_start; diff --git a/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java b/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java new file mode 100644 index 0000000000..04f5089673 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java @@ -0,0 +1,526 @@ +/* ==================================================================== + 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 java.util.ArrayList; +import java.util.Iterator; +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.FooterRecord; +import org.apache.poi.hssf.record.HCenterRecord; +import org.apache.poi.hssf.record.HeaderRecord; +import org.apache.poi.hssf.record.HorizontalPageBreakRecord; +import org.apache.poi.hssf.record.LeftMarginRecord; +import org.apache.poi.hssf.record.Margin; +import org.apache.poi.hssf.record.PageBreakRecord; +import org.apache.poi.hssf.record.PrintSetupRecord; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RightMarginRecord; +import org.apache.poi.hssf.record.TopMarginRecord; +import org.apache.poi.hssf.record.VCenterRecord; +import org.apache.poi.hssf.record.VerticalPageBreakRecord; + +/** + * Groups the page settings records for a worksheet.

+ * + * See OOO excelfileformat.pdf sec 4.4 'Page Settings Block' + * + * @author Josh Micich + */ +public final class PageSettingsBlock extends RecordAggregate { + // Every one of these component records is optional + // (The whole PageSettingsBlock may not be present) + private PageBreakRecord _rowBreaksRecord; + private PageBreakRecord _columnBreaksRecord; + private HeaderRecord header; + private FooterRecord footer; + private HCenterRecord _hCenter; + private VCenterRecord _vCenter; + private LeftMarginRecord _leftMargin; + private RightMarginRecord _rightMargin; + private TopMarginRecord _topMargin; + private BottomMarginRecord _bottomMargin; + private Record _pls; + private PrintSetupRecord printSetup; + private Record _bitmap; + + public PageSettingsBlock(RecordStream rs) { + while(true) { + if (!readARecord(rs)) { + break; + } + } + } + + /** + * Creates a PageSettingsBlock with default settings + */ + public PageSettingsBlock() { + _rowBreaksRecord = new HorizontalPageBreakRecord(); + _columnBreaksRecord = new VerticalPageBreakRecord(); + header = createHeader(); + footer = createFooter(); + _hCenter = createHCenter(); + _vCenter = createVCenter(); + printSetup = createPrintSetup(); + } + + /** + * @return true if the specified Record sid is one belonging to the + * 'Page Settings Block'. + */ + public static boolean isComponentRecord(int sid) { + switch (sid) { + case HorizontalPageBreakRecord.sid: + case VerticalPageBreakRecord.sid: + case HeaderRecord.sid: + case FooterRecord.sid: + case HCenterRecord.sid: + case VCenterRecord.sid: + case LeftMarginRecord.sid: + case RightMarginRecord.sid: + case TopMarginRecord.sid: + case BottomMarginRecord.sid: + case 0x004D: // PLS + case PrintSetupRecord.sid: + case 0x00E9: // BITMAP + return true; + } + return false; + } + + private boolean readARecord(RecordStream rs) { + switch (rs.peekNextSid()) { + case HorizontalPageBreakRecord.sid: + _rowBreaksRecord = (PageBreakRecord) rs.getNext(); + break; + case VerticalPageBreakRecord.sid: + _columnBreaksRecord = (PageBreakRecord) rs.getNext(); + break; + case HeaderRecord.sid: + header = (HeaderRecord) rs.getNext(); + break; + case FooterRecord.sid: + footer = (FooterRecord) rs.getNext(); + break; + case HCenterRecord.sid: + _hCenter = (HCenterRecord) rs.getNext(); + break; + case VCenterRecord.sid: + _vCenter = (VCenterRecord) rs.getNext(); + break; + case LeftMarginRecord.sid: + _leftMargin = (LeftMarginRecord) rs.getNext(); + break; + case RightMarginRecord.sid: + _rightMargin = (RightMarginRecord) rs.getNext(); + break; + case TopMarginRecord.sid: + _topMargin = (TopMarginRecord) rs.getNext(); + break; + case BottomMarginRecord.sid: + _bottomMargin = (BottomMarginRecord) rs.getNext(); + break; + case 0x004D: // PLS + _pls = rs.getNext(); + break; + case PrintSetupRecord.sid: + printSetup = (PrintSetupRecord)rs.getNext(); + break; + case 0x00E9: // BITMAP + _bitmap = rs.getNext(); + break; + default: + // all other record types are not part of the PageSettingsBlock + return false; + } + return true; + } + + private PageBreakRecord getRowBreaksRecord() { + if (_rowBreaksRecord == null) { + _rowBreaksRecord = new HorizontalPageBreakRecord(); + } + return _rowBreaksRecord; + } + + private PageBreakRecord getColumnBreaksRecord() { + if (_columnBreaksRecord == null) { + _columnBreaksRecord = new VerticalPageBreakRecord(); + } + return _columnBreaksRecord; + } + + + /** + * Sets a page break at the indicated column + * + */ + public void setColumnBreak(short column, short fromRow, short toRow) { + getColumnBreaksRecord().addBreak(column, fromRow, toRow); + } + + /** + * Removes a page break at the indicated column + * + */ + public void removeColumnBreak(short column) { + getColumnBreaksRecord().removeBreak(column); + } + + + + + public void visitContainedRecords(RecordVisitor rv) { + visitIfPresent(_rowBreaksRecord, rv); + visitIfPresent(_columnBreaksRecord, rv); + visitIfPresent(header, rv); + visitIfPresent(footer, rv); + visitIfPresent(_hCenter, rv); + visitIfPresent(_vCenter, rv); + visitIfPresent(_leftMargin, rv); + visitIfPresent(_rightMargin, rv); + visitIfPresent(_topMargin, rv); + visitIfPresent(_bottomMargin, rv); + visitIfPresent(_pls, rv); + visitIfPresent(printSetup, rv); + visitIfPresent(_bitmap, rv); + } + private static void visitIfPresent(Record r, RecordVisitor rv) { + if (r != null) { + rv.visitRecord(r); + } + } + + /** + * creates the Header Record and sets it to nothing/0 length + */ + private static HeaderRecord createHeader() { + HeaderRecord retval = new HeaderRecord(); + + retval.setHeaderLength(( byte ) 0); + retval.setHeader(null); + return retval; + } + + /** + * creates the Footer Record and sets it to nothing/0 length + */ + private static FooterRecord createFooter() { + FooterRecord retval = new FooterRecord(); + + retval.setFooterLength(( byte ) 0); + retval.setFooter(null); + return retval; + } + + /** + * creates the HCenter Record and sets it to false (don't horizontally center) + */ + private static HCenterRecord createHCenter() { + HCenterRecord retval = new HCenterRecord(); + + retval.setHCenter(false); + return retval; + } + + /** + * creates the VCenter Record and sets it to false (don't horizontally center) + */ + private static VCenterRecord createVCenter() { + VCenterRecord retval = new VCenterRecord(); + + retval.setVCenter(false); + return retval; + } + + /** + * creates the PrintSetup Record and sets it to defaults and marks it invalid + * @see org.apache.poi.hssf.record.PrintSetupRecord + * @see org.apache.poi.hssf.record.Record + * @return record containing a PrintSetupRecord + */ + private static PrintSetupRecord createPrintSetup() { + PrintSetupRecord retval = new PrintSetupRecord(); + + retval.setPaperSize(( short ) 1); + retval.setScale(( short ) 100); + retval.setPageStart(( short ) 1); + retval.setFitWidth(( short ) 1); + retval.setFitHeight(( short ) 1); + retval.setOptions(( short ) 2); + retval.setHResolution(( short ) 300); + retval.setVResolution(( short ) 300); + retval.setHeaderMargin( 0.5); + retval.setFooterMargin( 0.5); + retval.setCopies(( short ) 0); + return retval; + } + + + /** + * Returns the HeaderRecord. + * @return HeaderRecord for the sheet. + */ + public HeaderRecord getHeader () + { + return header; + } + + /** + * Sets the HeaderRecord. + * @param newHeader The new HeaderRecord for the sheet. + */ + public void setHeader (HeaderRecord newHeader) + { + header = newHeader; + } + + /** + * Returns the FooterRecord. + * @return FooterRecord for the sheet. + */ + public FooterRecord getFooter () + { + return footer; + } + + /** + * Sets the FooterRecord. + * @param newFooter The new FooterRecord for the sheet. + */ + public void setFooter (FooterRecord newFooter) + { + footer = newFooter; + } + + /** + * Returns the PrintSetupRecord. + * @return PrintSetupRecord for the sheet. + */ + public PrintSetupRecord getPrintSetup () + { + return printSetup; + } + + /** + * Sets the PrintSetupRecord. + * @param newPrintSetup The new PrintSetupRecord for the sheet. + */ + public void setPrintSetup (PrintSetupRecord newPrintSetup) + { + printSetup = newPrintSetup; + } + + + private Margin getMarginRec(int marginIndex) { + switch (marginIndex) { + case Sheet.LeftMargin: return _leftMargin; + case Sheet.RightMargin: return _rightMargin; + case Sheet.TopMargin: return _topMargin; + case Sheet.BottomMargin: return _bottomMargin; + } + throw new RuntimeException( "Unknown margin constant: " + marginIndex ); + } + + + /** + * Gets the size of the margin in inches. + * @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; + } + 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 ); + } + + /** + * Shifts all the page breaks in the range "count" number of rows/columns + * @param breaks The page record to be shifted + * @param start Starting "main" value to shift breaks + * @param stop Ending "main" value to shift breaks + * @param count number of units (rows/columns) to shift by + */ + private static void shiftBreaks(PageBreakRecord breaks, int start, int stop, int count) { + + Iterator iterator = breaks.getBreaksIterator(); + List shiftedBreak = new ArrayList(); + while(iterator.hasNext()) + { + PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next(); + int breakLocation = breakItem.main; + boolean inStart = (breakLocation >= start); + boolean inEnd = (breakLocation <= stop); + if(inStart && inEnd) + shiftedBreak.add(breakItem); + } + + iterator = shiftedBreak.iterator(); + while (iterator.hasNext()) { + PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next(); + breaks.removeBreak(breakItem.main); + breaks.addBreak((short)(breakItem.main+count), breakItem.subFrom, breakItem.subTo); + } + } + + + /** + * Sets a page break at the indicated row + * @param row + */ + public void setRowBreak(int row, short fromCol, short toCol) { + getRowBreaksRecord().addBreak((short)row, fromCol, toCol); + } + + /** + * Removes a page break at the indicated row + * @param row + */ + public void removeRowBreak(int row) { + if (getRowBreaksRecord().getBreaks().length < 1) + throw new IllegalArgumentException("Sheet does not define any row breaks"); + getRowBreaksRecord().removeBreak((short)row); + } + + /** + * Queries if the specified row has a page break + * @param row + * @return true if the specified row has a page break + */ + public boolean isRowBroken(int row) { + return getRowBreaksRecord().getBreak(row) != null; + } + + + /** + * Queries if the specified column has a page break + * + * @return true if the specified column has a page break + */ + public boolean isColumnBroken(short column) { + return getColumnBreaksRecord().getBreak(column) != null; + } + + /** + * Shifts the horizontal page breaks for the indicated count + * @param startingRow + * @param endingRow + * @param count + */ + public void shiftRowBreaks(int startingRow, int endingRow, int count) { + shiftBreaks(getRowBreaksRecord(), startingRow, endingRow, count); + } + + /** + * Shifts the vertical page breaks for the indicated count + * @param startingCol + * @param endingCol + * @param count + */ + public void shiftColumnBreaks(short startingCol, short endingCol, short count) { + shiftBreaks(getColumnBreaksRecord(), startingCol, endingCol, count); + } + + /** + * @return all the horizontal page breaks, never null + */ + public int[] getRowBreaks() { + return getRowBreaksRecord().getBreaks(); + } + + /** + * @return the number of row page breaks + */ + public int getNumRowBreaks(){ + return getRowBreaksRecord().getNumBreaks(); + } + + /** + * @return all the column page breaks, never null + */ + public int[] getColumnBreaks(){ + return getColumnBreaksRecord().getBreaks(); + } + + /** + * @return the number of column page breaks + */ + public int getNumColumnBreaks(){ + return getColumnBreaksRecord().getNumBreaks(); + } + + public VCenterRecord getVCenter() { + return _vCenter; + } + + public HCenterRecord getHCenter() { + return _hCenter; + } + +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index 746b2d2f1f..13f942c298 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -547,10 +547,7 @@ public final class HSSFSheet { public void setVerticallyCenter(boolean value) { - VCenterRecord record = - (VCenterRecord) sheet.findFirstRecordBySid(VCenterRecord.sid); - - record.setVCenter(value); + sheet.getPageSettings().getVCenter().setVCenter(value); } /** @@ -566,10 +563,7 @@ public final class HSSFSheet { */ public boolean getVerticallyCenter() { - VCenterRecord record = - (VCenterRecord) sheet.findFirstRecordBySid(VCenterRecord.sid); - - return record.getVCenter(); + return sheet.getPageSettings().getVCenter().getVCenter(); } /** @@ -579,10 +573,7 @@ public final class HSSFSheet { public void setHorizontallyCenter(boolean value) { - HCenterRecord record = - (HCenterRecord) sheet.findFirstRecordBySid(HCenterRecord.sid); - - record.setHCenter(value); + sheet.getPageSettings().getHCenter().setHCenter(value); } /** @@ -591,10 +582,8 @@ public final class HSSFSheet { public boolean getHorizontallyCenter() { - HCenterRecord record = - (HCenterRecord) sheet.findFirstRecordBySid(HCenterRecord.sid); - return record.getHCenter(); + return sheet.getPageSettings().getHCenter().getHCenter(); } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/SanityChecker.java b/src/testcases/org/apache/poi/hssf/usermodel/SanityChecker.java index 0235564b35..0d5fbdc9bf 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/SanityChecker.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/SanityChecker.java @@ -23,6 +23,7 @@ import junit.framework.Assert; import org.apache.poi.hssf.model.Sheet; import org.apache.poi.hssf.model.Workbook; import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.record.aggregates.PageSettingsBlock; import java.util.List; @@ -106,7 +107,6 @@ public class SanityChecker } return matchOneOrMany( records, firstRecord ); -// return matchOneOrMany( records, recordIdx ); } private int matchRequired( int firstRecord, List records, int recordIdx ) @@ -117,7 +117,6 @@ public class SanityChecker } return matchOneOrMany( records, firstRecord ); -// return matchOneOrMany( records, recordIdx ); } private int matchOneOrMany( List records, int recordIdx ) @@ -204,11 +203,7 @@ public class SanityChecker new CheckRecord(GutsRecord.class, '1'), new CheckRecord(DefaultRowHeightRecord.class, '1'), new CheckRecord(WSBoolRecord.class, '1'), - new CheckRecord(HeaderRecord.class, '1'), - new CheckRecord(FooterRecord.class, '1'), - new CheckRecord(HCenterRecord.class, '1'), - new CheckRecord(VCenterRecord.class, '1'), - new CheckRecord(PrintSetupRecord.class, '1'), + new CheckRecord(PageSettingsBlock.class, '1'), new CheckRecord(DefaultColWidthRecord.class, '1'), new CheckRecord(DimensionsRecord.class, '1'), new CheckRecord(WindowTwoRecord.class, '1'), @@ -275,7 +270,7 @@ public class SanityChecker } } */ - private static int findFirstRecord( List records, Class record, int startIndex ) + /* package */ static int findFirstRecord( List records, Class record, int startIndex ) { for (int i = startIndex; i < records.size(); i++) { @@ -285,11 +280,6 @@ public class SanityChecker return -1; } -// private static int findFirstRecord( List records, Class record ) -// { -// return findFirstRecord ( records, record, 0 ); -// } - void checkRecordOrder(List records, CheckRecord[] check) { int recordIdx = 0; diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java index 1a678af682..1550f77216 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java @@ -70,8 +70,7 @@ public final class TestHSSFSheet extends TestCase { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet s = wb.createSheet(); Sheet sheet = s.getSheet(); - VCenterRecord record = - (VCenterRecord) sheet.findFirstRecordBySid(VCenterRecord.sid); + VCenterRecord record = sheet.getPageSettings().getVCenter(); assertEquals(false, record.getVCenter()); s.setVerticallyCenter(true); @@ -87,8 +86,7 @@ public final class TestHSSFSheet extends TestCase { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet s = wb.createSheet(); Sheet sheet = s.getSheet(); - HCenterRecord record = - (HCenterRecord) sheet.findFirstRecordBySid(HCenterRecord.sid); + HCenterRecord record = sheet.getPageSettings().getHCenter(); assertEquals(false, record.getHCenter()); s.setHorizontallyCenter(true);