git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1364061 13f79535-47bb-0310-9956-ffa450edef68tags/3.10-beta1
@@ -34,6 +34,7 @@ | |||
<changes> | |||
<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">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> |
@@ -2003,4 +2003,71 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { | |||
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); | |||
} | |||
} |
@@ -76,7 +76,7 @@ import org.apache.commons.codec.digest.DigestUtils; | |||
public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook { | |||
private static final Pattern COMMA_PATTERN = Pattern.compile(","); | |||
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. | |||
@@ -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++) { | |||
NameRecord r = workbook.getNameRecord(defNameIndex); | |||
if (r == null) { |
@@ -927,4 +927,48 @@ public interface Sheet extends Iterable<Row> { | |||
*/ | |||
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(); | |||
} |
@@ -100,7 +100,10 @@ public class CellRangeAddress extends CellRangeAddressBase { | |||
sb.append(cellRefFrom.formatAsString()); | |||
//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(cellRefTo.formatAsString()); | |||
} |
@@ -76,11 +76,13 @@ public abstract class CellRangeAddressBase { | |||
//TODO use the correct SpreadsheetVersion | |||
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 | |||
public final boolean isFullRowRange() { | |||
return _firstCol == 0 && _lastCol == SpreadsheetVersion.EXCEL97.getLastColumnIndex(); | |||
return (_firstCol == 0 && _lastCol == SpreadsheetVersion.EXCEL97.getLastColumnIndex()) | |||
|| (_firstCol == -1 && _lastCol == -1); | |||
} | |||
/** |
@@ -91,25 +91,28 @@ public class CellReference { | |||
String[] parts = separateRefParts(cellRef); | |||
_sheetName = parts[0]; | |||
String colRef = parts[1]; | |||
if (colRef.length() < 1) { | |||
throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'"); | |||
} | |||
_isColAbs = colRef.charAt(0) == '$'; | |||
_isColAbs = (colRef.length() > 0) && colRef.charAt(0) == '$'; | |||
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]; | |||
if (rowRef.length() < 1) { | |||
throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'"); | |||
} | |||
_isRowAbs = rowRef.charAt(0) == '$'; | |||
_isRowAbs = (rowRef.length() > 0) && rowRef.charAt(0) == '$'; | |||
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) { | |||
@@ -482,14 +485,18 @@ public class CellReference { | |||
* Sheet name is not included. | |||
*/ | |||
/* package */ void appendCellReference(StringBuffer sb) { | |||
if(_isColAbs) { | |||
sb.append(ABSOLUTE_REFERENCE_MARKER); | |||
} | |||
sb.append( convertNumToColString(_colIndex)); | |||
if(_isRowAbs) { | |||
sb.append(ABSOLUTE_REFERENCE_MARKER); | |||
if (_colIndex != -1) { | |||
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(_rowIndex+1); | |||
} | |||
/** |
@@ -25,6 +25,7 @@ import java.util.Map; | |||
import org.apache.poi.ss.SpreadsheetVersion; | |||
import org.apache.poi.ss.usermodel.*; | |||
import org.apache.poi.ss.util.AreaReference; | |||
import org.apache.poi.ss.util.SheetUtil; | |||
import org.apache.poi.xssf.usermodel.XSSFSheet; | |||
@@ -1263,7 +1264,20 @@ public class SXSSFSheet implements Sheet, Cloneable | |||
public SheetConditionalFormatting getSheetConditionalFormatting(){ | |||
return _sh.getSheetConditionalFormatting(); | |||
} | |||
@Override | |||
public CellRangeAddress getRepeatingRows() { | |||
return _sh.getRepeatingRows(); | |||
} | |||
@Override | |||
public CellRangeAddress getRepeatingColumns() { | |||
return _sh.getRepeatingColumns(); | |||
} | |||
//end of interface implementation | |||
/** | |||
* Specifies how many rows can be accessed at most via getRow(). |
@@ -3185,4 +3185,54 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { | |||
color.setIndexed(colorIndex); | |||
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; | |||
} | |||
} |
@@ -359,14 +359,40 @@ public abstract class BaseTestWorkbook extends TestCase { | |||
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(){ | |||
Workbook wb = _testDataProvider.createWorkbook(); | |||
Sheet sheet1 = wb.createSheet(); | |||
wb.setRepeatingRowsAndColumns(wb.getSheetIndex(sheet1), 0, 0, 0, 3); | |||
assertEquals("1:4", sheet1.getRepeatingRows().formatAsString()); | |||
//must handle sheets with quotas, see Bugzilla #47294 | |||
Sheet sheet2 = wb.createSheet("My' Sheet"); | |||
wb.setRepeatingRowsAndColumns(wb.getSheetIndex(sheet2), 0, 0, 0, 3); | |||
assertEquals("1:4", sheet2.getRepeatingRows().formatAsString()); | |||
} | |||
/** |