From: Evgeniy Berlog Date: Sun, 5 Aug 2012 13:05:44 +0000 (+0000) Subject: merged with trunk X-Git-Tag: 3.10-beta1~161^2~3 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=de70938945b079b631bc94c7c5bf6943be22898c;p=poi.git merged with trunk git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1369572 13f79535-47bb-0310-9956-ffa450edef68 --- de70938945b079b631bc94c7c5bf6943be22898c diff --cc src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java index 5236e184b8,30d3fc6295..c183b5070a --- a/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java @@@ -210,432 -212,432 +212,432 @@@ public final class PageSettingsBlock ex _sviewHeaderFooters.add(hf); } break; - default: - // all other record types are not part of the PageSettingsBlock - return false; - } - return true; - } - - private void checkNotPresent(Record rec) { - if (rec != null) { - throw new RecordFormatException("Duplicate PageSettingsBlock record (sid=0x" - + Integer.toHexString(rec.getSid()) + ")"); - } - } - - 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(int column) { - getColumnBreaksRecord().removeBreak(column); - } - - - - - public void visitContainedRecords(RecordVisitor rv) { - // Replicates record order from Excel 2007, though this is not critical - - visitIfPresent(_rowBreaksRecord, rv); - visitIfPresent(_columnBreaksRecord, rv); - // Write out empty header / footer records if these are missing - if (_header == null) { - rv.visitRecord(new HeaderRecord("")); - } else { - rv.visitRecord(_header); - } - if (_footer == null) { - rv.visitRecord(new FooterRecord("")); - } else { - rv.visitRecord(_footer); - } - visitIfPresent(_hCenter, rv); - visitIfPresent(_vCenter, rv); - visitIfPresent(_leftMargin, rv); - visitIfPresent(_rightMargin, rv); - visitIfPresent(_topMargin, rv); - visitIfPresent(_bottomMargin, rv); - for (RecordAggregate pls : _plsRecords) { - pls.visitContainedRecords(rv); - } - visitIfPresent(_printSetup, rv); - visitIfPresent(_printSize, rv); - visitIfPresent(_headerFooter, rv); + default: + // all other record types are not part of the PageSettingsBlock + return false; + } + return true; + } + + private void checkNotPresent(Record rec) { + if (rec != null) { + throw new RecordFormatException("Duplicate PageSettingsBlock record (sid=0x" + + Integer.toHexString(rec.getSid()) + ")"); + } + } + + 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(int column) { + getColumnBreaksRecord().removeBreak(column); + } + + + + + public void visitContainedRecords(RecordVisitor rv) { + // Replicates record order from Excel 2007, though this is not critical + + visitIfPresent(_rowBreaksRecord, rv); + visitIfPresent(_columnBreaksRecord, rv); + // Write out empty header / footer records if these are missing + if (_header == null) { + rv.visitRecord(new HeaderRecord("")); + } else { + rv.visitRecord(_header); + } + if (_footer == null) { + rv.visitRecord(new FooterRecord("")); + } else { + rv.visitRecord(_footer); + } + visitIfPresent(_hCenter, rv); + visitIfPresent(_vCenter, rv); + visitIfPresent(_leftMargin, rv); + visitIfPresent(_rightMargin, rv); + visitIfPresent(_topMargin, rv); + visitIfPresent(_bottomMargin, rv); + for (RecordAggregate pls : _plsRecords) { + pls.visitContainedRecords(rv); + } + visitIfPresent(_printSetup, rv); - visitIfPresent(_bitmap, rv); + visitIfPresent(_printSize, rv); + visitIfPresent(_headerFooter, rv); + visitIfPresent(_bitmap, rv); - } - private static void visitIfPresent(Record r, RecordVisitor rv) { - if (r != null) { - rv.visitRecord(r); - } - } - private static void visitIfPresent(PageBreakRecord r, RecordVisitor rv) { - if (r != null) { - if (r.isEmpty()) { - // its OK to not serialize empty page break records - return; - } - rv.visitRecord(r); - } - } - - /** - * 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 ) 1); - 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 InternalSheet.LeftMargin: return _leftMargin; - case InternalSheet.RightMargin: return _rightMargin; - case InternalSheet.TopMargin: return _topMargin; - case InternalSheet.BottomMargin: return _bottomMargin; - } - throw new IllegalArgumentException( "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(); - } - switch (margin) { - case InternalSheet.LeftMargin: return .75; - case InternalSheet.RightMargin: return .75; - case InternalSheet.TopMargin: return 1.0; - case InternalSheet.BottomMargin: return 1.0; - } - throw new IllegalArgumentException( "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 InternalSheet.LeftMargin: - _leftMargin = new LeftMarginRecord(); - m = _leftMargin; - break; - case InternalSheet.RightMargin: - _rightMargin = new RightMarginRecord(); - m = _rightMargin; - break; - case InternalSheet.TopMargin: - _topMargin = new TopMarginRecord(); - m = _topMargin; - break; - case InternalSheet.BottomMargin: - _bottomMargin = new BottomMarginRecord(); - m = _bottomMargin; - break; - default : - throw new IllegalArgumentException( "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 = 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 = 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(int 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; - } - - /** - * HEADERFOOTER is new in 2007. Some apps seem to have scattered this record long after - * the {@link PageSettingsBlock} where it belongs. - */ - public void addLateHeaderFooter(HeaderFooterRecord rec) { - if (_headerFooter != null) { - throw new IllegalStateException("This page settings block already has a header/footer record"); - } - if (rec.getSid() != HeaderFooterRecord.sid) { - throw new RecordFormatException("Unexpected header-footer record sid: 0x" + Integer.toHexString(rec.getSid())); - } - _headerFooter = rec; - } - - /** - * This method reads PageSettingsBlock records from the supplied RecordStream until the first - * non-PageSettingsBlock record is encountered. As each record is read, it is incorporated - * into this PageSettingsBlock. - *

- * The latest Excel version seems to write the PageSettingsBlock uninterrupted. However there - * are several examples (that Excel reads OK) where these records are not written together: - *

    - *
  • HEADER_FOOTER(0x089C) after WINDOW2 - This record is new in 2007. Some apps - * seem to have scattered this record long after the PageSettingsBlock where it belongs - * test samples: SharedFormulaTest.xls, ex44921-21902.xls, ex42570-20305.xls
  • - *
  • PLS, WSBOOL, PageSettingsBlock - WSBOOL is not a PSB record. - * This happens in the test sample file "NoGutsRecords.xls" and "WORKBOOK_in_capitals.xls"
  • - *
  • Margins after DIMENSION - All of PSB should be before DIMENSION. (Bug-47199)
  • - *
- * These were probably written by other applications (or earlier versions of Excel). It was - * decided to not write specific code for detecting each of these cases. POI now tolerates - * PageSettingsBlock records scattered all over the sheet record stream, and in any order, but - * does not allow duplicates of any of those records. - * - *

- * Note - when POI writes out this PageSettingsBlock, the records will always be written - * in one consolidated block (in the standard ordering) regardless of how scattered the records - * were when they were originally read. - * - * @throws RecordFormatException if any PSB record encountered has the same type (sid) as - * a record that is already part of this PageSettingsBlock - */ - public void addLateRecords(RecordStream rs) { - while(true) { - if (!readARecord(rs)) { - break; - } - } - } + } + private static void visitIfPresent(Record r, RecordVisitor rv) { + if (r != null) { + rv.visitRecord(r); + } + } + private static void visitIfPresent(PageBreakRecord r, RecordVisitor rv) { + if (r != null) { + if (r.isEmpty()) { + // its OK to not serialize empty page break records + return; + } + rv.visitRecord(r); + } + } + + /** + * 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 ) 1); + 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 InternalSheet.LeftMargin: return _leftMargin; + case InternalSheet.RightMargin: return _rightMargin; + case InternalSheet.TopMargin: return _topMargin; + case InternalSheet.BottomMargin: return _bottomMargin; + } + throw new IllegalArgumentException( "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(); + } + switch (margin) { + case InternalSheet.LeftMargin: return .75; + case InternalSheet.RightMargin: return .75; + case InternalSheet.TopMargin: return 1.0; + case InternalSheet.BottomMargin: return 1.0; + } + throw new IllegalArgumentException( "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 InternalSheet.LeftMargin: + _leftMargin = new LeftMarginRecord(); + m = _leftMargin; + break; + case InternalSheet.RightMargin: + _rightMargin = new RightMarginRecord(); + m = _rightMargin; + break; + case InternalSheet.TopMargin: + _topMargin = new TopMarginRecord(); + m = _topMargin; + break; + case InternalSheet.BottomMargin: + _bottomMargin = new BottomMarginRecord(); + m = _bottomMargin; + break; + default : + throw new IllegalArgumentException( "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 = 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 = 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(int 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; + } + + /** + * HEADERFOOTER is new in 2007. Some apps seem to have scattered this record long after + * the {@link PageSettingsBlock} where it belongs. + */ + public void addLateHeaderFooter(HeaderFooterRecord rec) { + if (_headerFooter != null) { + throw new IllegalStateException("This page settings block already has a header/footer record"); + } + if (rec.getSid() != HeaderFooterRecord.sid) { + throw new RecordFormatException("Unexpected header-footer record sid: 0x" + Integer.toHexString(rec.getSid())); + } + _headerFooter = rec; + } + + /** + * This method reads PageSettingsBlock records from the supplied RecordStream until the first + * non-PageSettingsBlock record is encountered. As each record is read, it is incorporated + * into this PageSettingsBlock. + *

+ * The latest Excel version seems to write the PageSettingsBlock uninterrupted. However there + * are several examples (that Excel reads OK) where these records are not written together: + *

    + *
  • HEADER_FOOTER(0x089C) after WINDOW2 - This record is new in 2007. Some apps + * seem to have scattered this record long after the PageSettingsBlock where it belongs + * test samples: SharedFormulaTest.xls, ex44921-21902.xls, ex42570-20305.xls
  • + *
  • PLS, WSBOOL, PageSettingsBlock - WSBOOL is not a PSB record. + * This happens in the test sample file "NoGutsRecords.xls" and "WORKBOOK_in_capitals.xls"
  • + *
  • Margins after DIMENSION - All of PSB should be before DIMENSION. (Bug-47199)
  • + *
+ * These were probably written by other applications (or earlier versions of Excel). It was + * decided to not write specific code for detecting each of these cases. POI now tolerates + * PageSettingsBlock records scattered all over the sheet record stream, and in any order, but + * does not allow duplicates of any of those records. + * + *

+ * Note - when POI writes out this PageSettingsBlock, the records will always be written + * in one consolidated block (in the standard ordering) regardless of how scattered the records + * were when they were originally read. + * + * @throws RecordFormatException if any PSB record encountered has the same type (sid) as + * a record that is already part of this PageSettingsBlock + */ + public void addLateRecords(RecordStream rs) { + while(true) { + if (!readARecord(rs)) { + break; + } + } + } /** * Some apps can define multiple HeaderFooterRecord records for a sheet. diff --cc src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index f0ec2d6804,40f85033cf..bb3c92ced0 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@@ -371,6 -363,6 +373,7 @@@ public final class HSSFSheet implement /** * Creates a data validation object ++ * * @param dataValidation The Data validation object settings */ public void addValidationData(DataValidation dataValidation) { @@@ -522,7 -508,7 +525,8 @@@ /** * get the default row height for the sheet (if the rows do not define their own height) in * twips (1/20 of a point) - * @return default row height ++ * + * @return default row height */ public short getDefaultRowHeight() { return _sheet.getDefaultRowHeight(); @@@ -531,11 -517,12 +535,12 @@@ /** * get the default row height for the sheet (if the rows do not define their own height) in * points. - * @return default row height in points ++ * + * @return default row height in points */ - public float getDefaultRowHeightInPoints() - { - return ((float)_sheet.getDefaultRowHeight() / 20); + public float getDefaultRowHeightInPoints() { + return ((float) _sheet.getDefaultRowHeight() / 20); } /** @@@ -813,6 -801,6 +818,7 @@@ /** * used internally in the API to get the low level Sheet record represented by this * Object. ++ * * @return Sheet - low level representation of this HSSFSheet. */ InternalSheet getSheet() { @@@ -821,7 -809,7 +827,8 @@@ /** * whether alternate expression evaluation is on - * @param b alternative expression evaluation or not ++ * + * @param b alternative expression evaluation or not */ public void setAlternativeExpression(boolean b) { WSBoolRecord record = @@@ -832,7 -820,7 +839,8 @@@ /** * whether alternative formula entry is on - * @param b alternative formulas or not ++ * + * @param b alternative formulas or not */ public void setAlternativeFormula(boolean b) { WSBoolRecord record = @@@ -843,7 -831,7 +851,8 @@@ /** * show automatic page breaks or not - * @param b whether to show auto page breaks ++ * + * @param b whether to show auto page breaks */ public void setAutobreaks(boolean b) { WSBoolRecord record = @@@ -854,7 -842,7 +863,8 @@@ /** * set whether sheet is a dialog sheet or not - * @param b isDialog or not ++ * + * @param b isDialog or not */ public void setDialog(boolean b) { WSBoolRecord record = @@@ -877,7 -865,7 +887,8 @@@ /** * fit to page option is on - * @param b fit or not ++ * + * @param b fit or not */ public void setFitToPage(boolean b) { WSBoolRecord record = @@@ -888,7 -876,7 +899,8 @@@ /** * set if row summaries appear below detail in the outline - * @param b below or not ++ * + * @param b below or not */ public void setRowSumsBelow(boolean b) { WSBoolRecord record = @@@ -901,7 -889,7 +913,8 @@@ /** * set if col summaries appear right of the detail in the outline - * @param b right or not ++ * + * @param b right or not */ public void setRowSumsRight(boolean b) { WSBoolRecord record = @@@ -912,6 -900,6 +925,7 @@@ /** * whether alternate expression evaluation is on ++ * * @return alternative expression evaluation or not */ public boolean getAlternateExpression() { @@@ -921,6 -909,6 +935,7 @@@ /** * whether alternative formula entry is on ++ * * @return alternative formulas or not */ public boolean getAlternateFormula() { @@@ -930,6 -918,6 +945,7 @@@ /** * show automatic page breaks or not ++ * * @return whether to show auto page breaks */ public boolean getAutobreaks() { @@@ -939,6 -927,6 +955,7 @@@ /** * get whether sheet is a dialog sheet or not ++ * * @return isDialog or not */ public boolean getDialog() { @@@ -963,9 -951,9 +980,10 @@@ *

* In Excel 2003 this option can be changed in the Options dialog on the View tab. *

++ * * @return whether all zero values on the worksheet are displayed */ - public boolean isDisplayZeros(){ + public boolean isDisplayZeros() { return _sheet.getWindowTwo().getDisplayZeros(); } @@@ -975,14 -963,14 +993,16 @@@ *

* In Excel 2003 this option can be set in the Options dialog on the View tab. *

++ * * @param value whether to display or hide all zero values on the worksheet */ - public void setDisplayZeros(boolean value){ + public void setDisplayZeros(boolean value) { _sheet.getWindowTwo().setDisplayZeros(value); } /** * fit to page option is on ++ * * @return fit or not */ public boolean getFitToPage() { @@@ -992,6 -980,6 +1012,7 @@@ /** * get if row summaries appear below detail in the outline ++ * * @return below or not */ public boolean getRowSumsBelow() { @@@ -1001,6 -989,6 +1022,7 @@@ /** * get if col summaries appear right of the detail in the outline ++ * * @return right or not */ public boolean getRowSumsRight() { @@@ -1010,6 -998,6 +1032,7 @@@ /** * Returns whether gridlines are printed. ++ * * @return Gridlines are printed */ public boolean isPrintGridlines() { @@@ -1018,8 -1006,8 +1041,9 @@@ /** * Turns on or off the printing of gridlines. ++ * * @param newPrintGridlines boolean to turn on or off the printing of -- * gridlines ++ * gridlines */ public void setPrintGridlines(boolean newPrintGridlines) { getSheet().getPrintGridlines().setPrintGridlines(newPrintGridlines); @@@ -1027,6 -1015,6 +1051,7 @@@ /** * Gets the print setup object. ++ * * @return The user model for the print setup object. */ public HSSFPrintSetup getPrintSetup() { @@@ -1766,43 -1751,9 +1791,42 @@@ return _patriarch; } + private HSSFPatriarch getPatriarch(boolean createIfMissing) { + HSSFPatriarch patriarch = null; + if (_patriarch != null) { + return _patriarch; + } + DrawingManager2 dm = _book.findDrawingGroup(); + if (null == dm) { + if (!createIfMissing) { + return null; + } else { + _book.createDrawingGroup(); + dm = _book.getDrawingManager(); + } + } + EscherAggregate agg = (EscherAggregate) _sheet.findFirstRecordBySid(EscherAggregate.sid); + if (null == agg) { + int pos = _sheet.aggregateDrawingRecords(dm, false); + if (-1 == pos) { + if (createIfMissing) { + pos = _sheet.aggregateDrawingRecords(dm, true); + agg = (EscherAggregate) _sheet.getRecords().get(pos); + patriarch = new HSSFPatriarch(this, agg); + patriarch.afterCreate(); + return patriarch; + } else { + return null; + } + } + agg = (EscherAggregate) _sheet.getRecords().get(pos); + } + return new HSSFPatriarch(this, agg); + } + - /** - * @deprecated (Sep 2008) use {@link #setColumnGroupCollapsed(int, boolean)} - */ - + /** + * @deprecated (Sep 2008) use {@link #setColumnGroupCollapsed(int, boolean)} + */ public void setColumnGroupCollapsed(short columnNumber, boolean collapsed) { setColumnGroupCollapsed(columnNumber & 0xFFFF, collapsed); } @@@ -2043,31 -2005,163 +2067,187 @@@ return new HSSFAutoFilter(this); } + protected HSSFComment findCellComment(int row, int column) { + HSSFPatriarch patriarch = getDrawingPatriarch(); + if (null == patriarch) { + patriarch = createDrawingPatriarch(); + } + return lookForComment(patriarch, row, column); + } + + private HSSFComment lookForComment(HSSFShapeContainer container, int row, int column) { + for (Object object : container.getChildren()) { + HSSFShape shape = (HSSFShape) object; + if (shape instanceof HSSFShapeGroup) { + HSSFShape res = lookForComment((HSSFShapeContainer) shape, row, column); + if (null != res) { + return (HSSFComment) res; + } + continue; + } + if (shape instanceof HSSFComment) { + HSSFComment comment = (HSSFComment) shape; + if (comment.getColumn() == column && comment.getRow() == row) { + return comment; + } + } + } + return null; + } ++ ++ ++ public CellRangeAddress getRepeatingRows() { ++ return getRepeatingRowsOrColums(true); ++ } ++ ++ ++ public CellRangeAddress getRepeatingColumns() { ++ return getRepeatingRowsOrColums(false); ++ } ++ ++ ++ public void setRepeatingRows(CellRangeAddress rowRangeRef) { ++ CellRangeAddress columnRangeRef = getRepeatingColumns(); ++ setRepeatingRowsAndColumns(rowRangeRef, columnRangeRef); ++ } ++ ++ ++ public void setRepeatingColumns(CellRangeAddress columnRangeRef) { ++ CellRangeAddress rowRangeRef = getRepeatingRows(); ++ setRepeatingRowsAndColumns(rowRangeRef, columnRangeRef); ++ } ++ ++ ++ private void setRepeatingRowsAndColumns( ++ CellRangeAddress rowDef, CellRangeAddress colDef) { ++ int sheetIndex = _workbook.getSheetIndex(this); ++ int maxRowIndex = SpreadsheetVersion.EXCEL97.getLastRowIndex(); ++ int maxColIndex = SpreadsheetVersion.EXCEL97.getLastColumnIndex(); ++ ++ int col1 = -1; ++ int col2 = -1; ++ int row1 = -1; ++ int row2 = -1; ++ ++ if (rowDef != null) { ++ row1 = rowDef.getFirstRow(); ++ row2 = rowDef.getLastRow(); ++ if ((row1 == -1 && row2 != -1) || (row1 > row2) ++ || (row1 < 0 || row1 > maxRowIndex) ++ || (row2 < 0 || row2 > maxRowIndex)) { ++ throw new IllegalArgumentException("Invalid row range specification"); ++ } ++ } ++ if (colDef != null) { ++ col1 = colDef.getFirstColumn(); ++ col2 = colDef.getLastColumn(); ++ if ((col1 == -1 && col2 != -1) || (col1 > col2) ++ || (col1 < 0 || col1 > maxColIndex) ++ || (col2 < 0 || col2 > maxColIndex)) { ++ throw new IllegalArgumentException("Invalid column range specification"); ++ } ++ } ++ ++ short externSheetIndex = ++ _workbook.getWorkbook().checkExternSheet(sheetIndex); ++ ++ boolean setBoth = rowDef != null && colDef != null; ++ boolean removeAll = rowDef == null && colDef == null; ++ ++ HSSFName name = _workbook.getBuiltInName( ++ NameRecord.BUILTIN_PRINT_TITLE, sheetIndex); ++ if (removeAll) { ++ if (name != null) { ++ _workbook.removeName(name); ++ } ++ return; ++ } ++ if (name == null) { ++ name = _workbook.createBuiltInName( ++ NameRecord.BUILTIN_PRINT_TITLE, sheetIndex); ++ } + - @Override - public CellRangeAddress getRepeatingRows() { - return getRepeatingRowsOrColums(true); - } - - - @Override - public CellRangeAddress getRepeatingColumns() { - return getRepeatingRowsOrColums(false); - } - - - @Override - public void setRepeatingRows(CellRangeAddress rowRangeRef) { - CellRangeAddress columnRangeRef = getRepeatingColumns(); - setRepeatingRowsAndColumns(rowRangeRef, columnRangeRef); - } - - - @Override - public void setRepeatingColumns(CellRangeAddress columnRangeRef) { - CellRangeAddress rowRangeRef = getRepeatingRows(); - setRepeatingRowsAndColumns(rowRangeRef, columnRangeRef); - } - - - private void setRepeatingRowsAndColumns( - CellRangeAddress rowDef, CellRangeAddress colDef) { - int sheetIndex = _workbook.getSheetIndex(this); - int maxRowIndex = SpreadsheetVersion.EXCEL97.getLastRowIndex(); - int maxColIndex = SpreadsheetVersion.EXCEL97.getLastColumnIndex(); - - int col1 = -1; - int col2 = -1; - int row1 = -1; - int row2 = -1; - - if (rowDef != null) { - row1 = rowDef.getFirstRow(); - row2 = rowDef.getLastRow(); - if ((row1 == -1 && row2 != -1) || (row1 > row2) - || (row1 < 0 || row1 > maxRowIndex) - || (row2 < 0 || row2 > maxRowIndex)) { - throw new IllegalArgumentException("Invalid row range specification"); - } - } - if (colDef != null) { - col1 = colDef.getFirstColumn(); - col2 = colDef.getLastColumn(); - if ((col1 == -1 && col2 != -1) || (col1 > col2) - || (col1 < 0 || col1 > maxColIndex) - || (col2 < 0 || col2 > maxColIndex)) { - throw new IllegalArgumentException("Invalid column range specification"); - } - } - - short externSheetIndex = - _workbook.getWorkbook().checkExternSheet(sheetIndex); - - boolean setBoth = rowDef != null && colDef != null; - boolean removeAll = rowDef == null && colDef == null; - - HSSFName name = _workbook.getBuiltInName( - NameRecord.BUILTIN_PRINT_TITLE, sheetIndex); - if (removeAll) { - if (name != null) { - _workbook.removeName(name); ++ List ptgList = new ArrayList(); ++ if (setBoth) { ++ final int exprsSize = 2 * 11 + 1; // 2 * Area3DPtg.SIZE + UnionPtg.SIZE ++ ptgList.add(new MemFuncPtg(exprsSize)); + } - return; - } - if (name == null) { - name = _workbook.createBuiltInName( - NameRecord.BUILTIN_PRINT_TITLE, sheetIndex); - } - - List ptgList = new ArrayList(); - if (setBoth) { - final int exprsSize = 2 * 11 + 1; // 2 * Area3DPtg.SIZE + UnionPtg.SIZE - ptgList.add(new MemFuncPtg(exprsSize)); - } - if (colDef != null) { - Area3DPtg colArea = new Area3DPtg(0, maxRowIndex, col1, col2, - false, false, false, false, externSheetIndex); - ptgList.add(colArea); - } - if (rowDef != null) { - Area3DPtg rowArea = new Area3DPtg(row1, row2, 0, maxColIndex, - false, false, false, false, externSheetIndex); - ptgList.add(rowArea); - } - if (setBoth) { - ptgList.add(UnionPtg.instance); - } - - Ptg[] ptgs = new Ptg[ptgList.size()]; - ptgList.toArray(ptgs); - name.setNameDefinition(ptgs); - - HSSFPrintSetup printSetup = getPrintSetup(); - printSetup.setValidSettings(false); - setActive(true); - } - - - private CellRangeAddress getRepeatingRowsOrColums(boolean rows) { - NameRecord rec = getBuiltinNameRecord(NameRecord.BUILTIN_PRINT_TITLE); - if (rec == null) { - return null; - } - - Ptg[] nameDefinition = rec.getNameDefinition(); - if (nameDefinition == null) { - return null; - } - - int maxRowIndex = SpreadsheetVersion.EXCEL97.getLastRowIndex(); - int maxColIndex = SpreadsheetVersion.EXCEL97.getLastColumnIndex(); - - for (Ptg ptg :nameDefinition) { - - if (ptg instanceof Area3DPtg) { - Area3DPtg areaPtg = (Area3DPtg) ptg; - - if (areaPtg.getFirstColumn() == 0 - && areaPtg.getLastColumn() == maxColIndex) { - if (rows) { - CellRangeAddress rowRange = new CellRangeAddress( - areaPtg.getFirstRow(), areaPtg.getLastRow(), -1, -1); - return rowRange; - } - } else if (areaPtg.getFirstRow() == 0 - && areaPtg.getLastRow() == maxRowIndex) { - if (!rows) { - CellRangeAddress columnRange = new CellRangeAddress(-1, -1, - areaPtg.getFirstColumn(), areaPtg.getLastColumn()); - return columnRange; - } ++ if (colDef != null) { ++ Area3DPtg colArea = new Area3DPtg(0, maxRowIndex, col1, col2, ++ false, false, false, false, externSheetIndex); ++ ptgList.add(colArea); + } - - } - ++ if (rowDef != null) { ++ Area3DPtg rowArea = new Area3DPtg(row1, row2, 0, maxColIndex, ++ false, false, false, false, externSheetIndex); ++ ptgList.add(rowArea); ++ } ++ if (setBoth) { ++ ptgList.add(UnionPtg.instance); ++ } ++ ++ Ptg[] ptgs = new Ptg[ptgList.size()]; ++ ptgList.toArray(ptgs); ++ name.setNameDefinition(ptgs); ++ ++ HSSFPrintSetup printSetup = getPrintSetup(); ++ printSetup.setValidSettings(false); ++ setActive(true); + } - - return null; - } + + - private NameRecord getBuiltinNameRecord(byte builtinCode) { - int sheetIndex = _workbook.getSheetIndex(this); - int recIndex = - _workbook.findExistingBuiltinNameRecordIdx(sheetIndex, builtinCode); - if (recIndex == -1) { - return null; ++ private CellRangeAddress getRepeatingRowsOrColums(boolean rows) { ++ NameRecord rec = getBuiltinNameRecord(NameRecord.BUILTIN_PRINT_TITLE); ++ if (rec == null) { ++ return null; ++ } ++ ++ Ptg[] nameDefinition = rec.getNameDefinition(); ++ if (nameDefinition == null) { ++ return null; ++ } ++ ++ int maxRowIndex = SpreadsheetVersion.EXCEL97.getLastRowIndex(); ++ int maxColIndex = SpreadsheetVersion.EXCEL97.getLastColumnIndex(); ++ ++ for (Ptg ptg : nameDefinition) { ++ ++ if (ptg instanceof Area3DPtg) { ++ Area3DPtg areaPtg = (Area3DPtg) ptg; ++ ++ if (areaPtg.getFirstColumn() == 0 ++ && areaPtg.getLastColumn() == maxColIndex) { ++ if (rows) { ++ CellRangeAddress rowRange = new CellRangeAddress( ++ areaPtg.getFirstRow(), areaPtg.getLastRow(), -1, -1); ++ return rowRange; ++ } ++ } else if (areaPtg.getFirstRow() == 0 ++ && areaPtg.getLastRow() == maxRowIndex) { ++ if (!rows) { ++ CellRangeAddress columnRange = new CellRangeAddress(-1, -1, ++ areaPtg.getFirstColumn(), areaPtg.getLastColumn()); ++ return columnRange; ++ } ++ } ++ ++ } ++ ++ } ++ ++ return null; + } - return _workbook.getNameRecord(recIndex); - } + - ++ ++ private NameRecord getBuiltinNameRecord(byte builtinCode) { ++ int sheetIndex = _workbook.getSheetIndex(this); ++ int recIndex = ++ _workbook.findExistingBuiltinNameRecordIdx(sheetIndex, builtinCode); ++ if (recIndex == -1) { ++ return null; ++ } ++ return _workbook.getNameRecord(recIndex); ++ } ++ ++ } diff --cc src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java index afe8612002,84589a6fdc..77ae26f76a --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java @@@ -1263,7 -1276,31 +1276,27 @@@ public class SXSSFSheet implements Shee public SheetConditionalFormatting getSheetConditionalFormatting(){ return _sh.getSheetConditionalFormatting(); } - + + - @Override + public CellRangeAddress getRepeatingRows() { + return _sh.getRepeatingRows(); + } + + - @Override + public CellRangeAddress getRepeatingColumns() { + return _sh.getRepeatingColumns(); + } + - @Override + public void setRepeatingRows(CellRangeAddress rowRangeRef) { + _sh.setRepeatingRows(rowRangeRef); + } + - @Override + public void setRepeatingColumns(CellRangeAddress columnRangeRef) { + _sh.setRepeatingColumns(columnRangeRef); + } + + + //end of interface implementation /** * Specifies how many rows can be accessed at most via getRow(). diff --cc src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index fbed5b06dd,a69bf09f43..ccf2419873 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@@ -3185,4 -3186,166 +3186,162 @@@ public class XSSFSheet extends POIXMLDo color.setIndexed(colorIndex); pr.setTabColor(color); } + + - @Override + public CellRangeAddress getRepeatingRows() { + return getRepeatingRowsOrColums(true); + } + + - @Override + public CellRangeAddress getRepeatingColumns() { + return getRepeatingRowsOrColums(false); + } + - @Override + public void setRepeatingRows(CellRangeAddress rowRangeRef) { + CellRangeAddress columnRangeRef = getRepeatingColumns(); + setRepeatingRowsAndColumns(rowRangeRef, columnRangeRef); + } + + - @Override + public void setRepeatingColumns(CellRangeAddress columnRangeRef) { + CellRangeAddress rowRangeRef = getRepeatingRows(); + setRepeatingRowsAndColumns(rowRangeRef, columnRangeRef); + } + + + private void setRepeatingRowsAndColumns( + CellRangeAddress rowDef, CellRangeAddress colDef) { + int col1 = -1; + int col2 = -1; + int row1 = -1; + int row2 = -1; + + if (rowDef != null) { + row1 = rowDef.getFirstRow(); + row2 = rowDef.getLastRow(); + if ((row1 == -1 && row2 != -1) + || row1 < -1 || row2 < -1 || row1 > row2) { + throw new IllegalArgumentException("Invalid row range specification"); + } + } + if (colDef != null) { + col1 = colDef.getFirstColumn(); + col2 = colDef.getLastColumn(); + if ((col1 == -1 && col2 != -1) + || col1 < -1 || col2 < -1 || col1 > col2) { + throw new IllegalArgumentException( + "Invalid column range specification"); + } + } + + int sheetIndex = getWorkbook().getSheetIndex(this); + + boolean removeAll = rowDef == null && colDef == null; + + XSSFName name = getWorkbook().getBuiltInName( + XSSFName.BUILTIN_PRINT_TITLE, sheetIndex); + if (removeAll) { + if (name != null) { + getWorkbook().removeName(name); + } + return; + } + if (name == null) { + name = getWorkbook().createBuiltInName( + XSSFName.BUILTIN_PRINT_TITLE, sheetIndex); + } + + String reference = getReferenceBuiltInRecord( + name.getSheetName(), col1, col2, row1, row2); + name.setRefersToFormula(reference); + + // If the print setup isn't currently defined, then add it + // in but without printer defaults + // If it's already there, leave it as-is! + if (worksheet.isSetPageSetup() && worksheet.isSetPageMargins()) { + // Everything we need is already there + } else { + // Have initial ones put in place + getPrintSetup().setValidSettings(false); + } + } + + private static String getReferenceBuiltInRecord( + String sheetName, int startC, int endC, int startR, int endR) { + // Excel example for built-in title: + // 'second sheet'!$E:$F,'second sheet'!$2:$3 + + CellReference colRef = + new CellReference(sheetName, 0, startC, true, true); + CellReference colRef2 = + new CellReference(sheetName, 0, endC, true, true); + CellReference rowRef = + new CellReference(sheetName, startR, 0, true, true); + CellReference rowRef2 = + new CellReference(sheetName, endR, 0, true, true); + + String escapedName = SheetNameFormatter.format(sheetName); + + String c = ""; + String r = ""; + + if(startC == -1 && endC == -1) { + } else { + c = escapedName + "!$" + colRef.getCellRefParts()[2] + + ":$" + colRef2.getCellRefParts()[2]; + } + + if (startR == -1 && endR == -1) { + + } else if (!rowRef.getCellRefParts()[1].equals("0") + && !rowRef2.getCellRefParts()[1].equals("0")) { + r = escapedName + "!$" + rowRef.getCellRefParts()[1] + + ":$" + rowRef2.getCellRefParts()[1]; + } + + StringBuffer rng = new StringBuffer(); + rng.append(c); + if(rng.length() > 0 && r.length() > 0) { + rng.append(','); + } + rng.append(r); + return rng.toString(); + } + + + private CellRangeAddress getRepeatingRowsOrColums(boolean rows) { + int sheetIndex = getWorkbook().getSheetIndex(this); + XSSFName name = getWorkbook().getBuiltInName( + XSSFName.BUILTIN_PRINT_TITLE, sheetIndex); + if (name == null ) { + return null; + } + String refStr = name.getRefersToFormula(); + if (refStr == null) { + return null; + } + String[] parts = refStr.split(","); + int maxRowIndex = SpreadsheetVersion.EXCEL2007.getLastRowIndex(); + int maxColIndex = SpreadsheetVersion.EXCEL2007.getLastColumnIndex(); + for (String part : parts) { + CellRangeAddress range = CellRangeAddress.valueOf(part); + if ((range.getFirstColumn() == 0 + && range.getLastColumn() == maxColIndex) + || (range.getFirstColumn() == -1 + && range.getLastColumn() == -1)) { + if (rows) { + return range; + } + } else if (range.getFirstRow() == 0 + && range.getLastRow() == maxRowIndex + || (range.getFirstRow() == -1 + && range.getLastRow() == -1)) { + if (!rows) { + return range; + } + } + } + return null; + } + }