Bugzilla 53500 - Getter for repeating rows and columns

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1364061 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2012-07-21 10:33:00 +00:00
parent 765b7627dc
commit d619711ea4
12 changed files with 239 additions and 25 deletions

View File

@ -34,6 +34,7 @@
<changes> <changes>
<release version="3.9-beta1" date="2012-??-??"> <release version="3.9-beta1" date="2012-??-??">
<action dev="poi-developers" type="add">53500 - Getter for repeating rows and columns</action>
<action dev="poi-developers" type="fix">53369 - Fixed tests failing on JDK 1.7</action> <action dev="poi-developers" type="fix">53369 - Fixed tests failing on JDK 1.7</action>
<action dev="poi-developers" type="fix">53360 - Fixed SXSSF to correctly write text before escaped Unicode control character</action> <action dev="poi-developers" type="fix">53360 - Fixed SXSSF to correctly write text before escaped Unicode control character</action>
<action dev="poi-developers" type="add">Change HSMF Types to have full data on ID, Name and Length, rather than just being a simple ID</action> <action dev="poi-developers" type="add">Change HSMF Types to have full data on ID, Name and Length, rather than just being a simple ID</action>

View File

@ -2003,4 +2003,71 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
return new HSSFAutoFilter(this); return new HSSFAutoFilter(this);
} }
@Override
public CellRangeAddress getRepeatingRows() {
return getRepeatingRowsOrColums(true);
}
@Override
public CellRangeAddress getRepeatingColumns() {
return getRepeatingRowsOrColums(false);
}
private CellRangeAddress getRepeatingRowsOrColums(boolean rows) {
NameRecord rec = getBuiltinNameRecord(NameRecord.BUILTIN_PRINT_TITLE);
if (rec == null) {
return null;
}
Ptg[] nameDefinition = rec.getNameDefinition();
if (rec.getNameDefinition() == 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;
}
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);
}
} }

View File

@ -76,7 +76,7 @@ import org.apache.commons.codec.digest.DigestUtils;
public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook { public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook {
private static final Pattern COMMA_PATTERN = Pattern.compile(","); private static final Pattern COMMA_PATTERN = Pattern.compile(",");
private static final int MAX_ROW = 0xFFFF; private static final int MAX_ROW = 0xFFFF;
private static final short MAX_COLUMN = (short)0x00FF; private static final int MAX_COLUMN = (short)0x00FF;
/** /**
* The maximum number of cell styles in a .xls workbook. * The maximum number of cell styles in a .xls workbook.
@ -1034,7 +1034,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
} }
private int findExistingBuiltinNameRecordIdx(int sheetIndex, byte builtinCode) { int findExistingBuiltinNameRecordIdx(int sheetIndex, byte builtinCode) {
for(int defNameIndex =0; defNameIndex<names.size(); defNameIndex++) { for(int defNameIndex =0; defNameIndex<names.size(); defNameIndex++) {
NameRecord r = workbook.getNameRecord(defNameIndex); NameRecord r = workbook.getNameRecord(defNameIndex);
if (r == null) { if (r == null) {

View File

@ -927,4 +927,48 @@ public interface Sheet extends Iterable<Row> {
*/ */
SheetConditionalFormatting getSheetConditionalFormatting(); SheetConditionalFormatting getSheetConditionalFormatting();
/**
* Gets the repeating rows used when printing the sheet, as found in
* File->PageSetup->Sheet.
* <p/>
* Repeating rows cover a range of contiguous rows, e.g.:
* <pre>
* Sheet1!$1:$1
* Sheet2!$5:$8
* </pre>
* The {@link CellRangeAddress} returned contains a column part which spans
* all columns, and a row part which specifies the contiguous range of
* repeating rows.
* <p/>
* If the Sheet does not have any repeating rows defined, null is returned.
*
* @return an {@link CellRangeAddress} containing the repeating rows for the
* Sheet, or null.
*/
CellRangeAddress getRepeatingRows();
/**
* Gets the repeating columns used when printing the sheet, as found in
* File->PageSetup->Sheet.
* <p/>
* Repeating columns cover a range of contiguous columns, e.g.:
* <pre>
* Sheet1!$A:$A
* Sheet2!$C:$F
* </pre>
* The {@link CellRangeAddress} returned contains a row part which spans all
* rows, and a column part which specifies the contiguous range of
* repeating columns.
* <p/>
* If the Sheet does not have any repeating columns defined, null is
* returned.
*
* @return an {@link CellRangeAddress} containing the repeating columns for the
* Sheet, or null.
*/
CellRangeAddress getRepeatingColumns();
} }

View File

@ -100,7 +100,10 @@ public class CellRangeAddress extends CellRangeAddressBase {
sb.append(cellRefFrom.formatAsString()); sb.append(cellRefFrom.formatAsString());
//for a single-cell reference return A1 instead of A1:A1 //for a single-cell reference return A1 instead of A1:A1
if(!cellRefFrom.equals(cellRefTo)){ //for full-column ranges or full-row ranges return A:A instead of A,
//and 1:1 instead of 1
if(!cellRefFrom.equals(cellRefTo)
|| isFullColumnRange() || isFullRowRange()){
sb.append(':'); sb.append(':');
sb.append(cellRefTo.formatAsString()); sb.append(cellRefTo.formatAsString());
} }

View File

@ -76,11 +76,13 @@ public abstract class CellRangeAddressBase {
//TODO use the correct SpreadsheetVersion //TODO use the correct SpreadsheetVersion
public final boolean isFullColumnRange() { public final boolean isFullColumnRange() {
return _firstRow == 0 && _lastRow == SpreadsheetVersion.EXCEL97.getLastRowIndex(); return (_firstRow == 0 && _lastRow == SpreadsheetVersion.EXCEL97.getLastRowIndex())
|| (_firstRow == -1 && _lastRow == -1);
} }
//TODO use the correct SpreadsheetVersion //TODO use the correct SpreadsheetVersion
public final boolean isFullRowRange() { public final boolean isFullRowRange() {
return _firstCol == 0 && _lastCol == SpreadsheetVersion.EXCEL97.getLastColumnIndex(); return (_firstCol == 0 && _lastCol == SpreadsheetVersion.EXCEL97.getLastColumnIndex())
|| (_firstCol == -1 && _lastCol == -1);
} }
/** /**

View File

@ -91,25 +91,28 @@ public class CellReference {
String[] parts = separateRefParts(cellRef); String[] parts = separateRefParts(cellRef);
_sheetName = parts[0]; _sheetName = parts[0];
String colRef = parts[1]; String colRef = parts[1];
if (colRef.length() < 1) { _isColAbs = (colRef.length() > 0) && colRef.charAt(0) == '$';
throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
}
_isColAbs = colRef.charAt(0) == '$';
if (_isColAbs) { if (_isColAbs) {
colRef=colRef.substring(1); colRef = colRef.substring(1);
}
if (colRef.length() == 0) {
_colIndex = -1;
} else {
_colIndex = convertColStringToIndex(colRef);
} }
_colIndex = convertColStringToIndex(colRef);
String rowRef=parts[2]; String rowRef=parts[2];
if (rowRef.length() < 1) { _isRowAbs = (rowRef.length() > 0) && rowRef.charAt(0) == '$';
throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
}
_isRowAbs = rowRef.charAt(0) == '$';
if (_isRowAbs) { if (_isRowAbs) {
rowRef=rowRef.substring(1); rowRef = rowRef.substring(1);
}
if (rowRef.length() == 0) {
_rowIndex = -1;
} else {
_rowIndex = Integer.parseInt(rowRef)-1; // -1 to convert 1-based to zero-based
} }
_rowIndex = Integer.parseInt(rowRef)-1; // -1 to convert 1-based to zero-based
} }
public CellReference(int pRow, int pCol) { public CellReference(int pRow, int pCol) {
@ -482,14 +485,18 @@ public class CellReference {
* Sheet name is not included. * Sheet name is not included.
*/ */
/* package */ void appendCellReference(StringBuffer sb) { /* package */ void appendCellReference(StringBuffer sb) {
if(_isColAbs) { if (_colIndex != -1) {
sb.append(ABSOLUTE_REFERENCE_MARKER); if(_isColAbs) {
sb.append(ABSOLUTE_REFERENCE_MARKER);
}
sb.append( convertNumToColString(_colIndex));
}
if (_rowIndex != -1) {
if(_isRowAbs) {
sb.append(ABSOLUTE_REFERENCE_MARKER);
}
sb.append(_rowIndex+1);
} }
sb.append( convertNumToColString(_colIndex));
if(_isRowAbs) {
sb.append(ABSOLUTE_REFERENCE_MARKER);
}
sb.append(_rowIndex+1);
} }
/** /**

View File

@ -25,6 +25,7 @@ import java.util.Map;
import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.SheetUtil; import org.apache.poi.ss.util.SheetUtil;
import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFSheet;
@ -1264,6 +1265,19 @@ public class SXSSFSheet implements Sheet, Cloneable
return _sh.getSheetConditionalFormatting(); return _sh.getSheetConditionalFormatting();
} }
@Override
public CellRangeAddress getRepeatingRows() {
return _sh.getRepeatingRows();
}
@Override
public CellRangeAddress getRepeatingColumns() {
return _sh.getRepeatingColumns();
}
//end of interface implementation //end of interface implementation
/** /**
* Specifies how many rows can be accessed at most via getRow(). * Specifies how many rows can be accessed at most via getRow().

View File

@ -3185,4 +3185,54 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
color.setIndexed(colorIndex); color.setIndexed(colorIndex);
pr.setTabColor(color); pr.setTabColor(color);
} }
@Override
public CellRangeAddress getRepeatingRows() {
return getRepeatingRowsOrColums(true);
}
@Override
public CellRangeAddress getRepeatingColumns() {
return getRepeatingRowsOrColums(false);
}
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;
}
} }

View File

@ -359,14 +359,40 @@ public abstract class BaseTestWorkbook extends TestCase {
assertSame(row, cell.getRow()); assertSame(row, cell.getRow());
} }
public void testGetRepeatingRowsAnsColumns(){
Workbook wb = _testDataProvider.openSampleWorkbook(
"RepeatingRowsCols."
+ _testDataProvider.getStandardFileNameExtension());
Sheet sheet0 = wb.getSheetAt(0);
assertNull(sheet0.getRepeatingRows());
assertNull(sheet0.getRepeatingColumns());
Sheet sheet1 = wb.getSheetAt(1);
assertEquals("1:1", sheet1.getRepeatingRows().formatAsString());
assertNull(sheet1.getRepeatingColumns());
Sheet sheet2 = wb.getSheetAt(2);
assertNull(sheet2.getRepeatingRows());
assertEquals("A:A", sheet2.getRepeatingColumns().formatAsString());
Sheet sheet3 = wb.getSheetAt(3);
assertEquals("2:3", sheet3.getRepeatingRows().formatAsString());
assertEquals("A:B", sheet3.getRepeatingColumns().formatAsString());
}
public void testSetRepeatingRowsAnsColumns(){ public void testSetRepeatingRowsAnsColumns(){
Workbook wb = _testDataProvider.createWorkbook(); Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet1 = wb.createSheet(); Sheet sheet1 = wb.createSheet();
wb.setRepeatingRowsAndColumns(wb.getSheetIndex(sheet1), 0, 0, 0, 3); wb.setRepeatingRowsAndColumns(wb.getSheetIndex(sheet1), 0, 0, 0, 3);
assertEquals("1:4", sheet1.getRepeatingRows().formatAsString());
//must handle sheets with quotas, see Bugzilla #47294 //must handle sheets with quotas, see Bugzilla #47294
Sheet sheet2 = wb.createSheet("My' Sheet"); Sheet sheet2 = wb.createSheet("My' Sheet");
wb.setRepeatingRowsAndColumns(wb.getSheetIndex(sheet2), 0, 0, 0, 3); wb.setRepeatingRowsAndColumns(wb.getSheetIndex(sheet2), 0, 0, 0, 3);
assertEquals("1:4", sheet2.getRepeatingRows().formatAsString());
} }
/** /**

Binary file not shown.

Binary file not shown.