Bug 53500: split setRepatingRowsAndColumns into setRepeatingRows and setRepeatingColumns

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1369290 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2012-08-04 08:51:49 +00:00
parent 63f3987cb0
commit 02678b3073
16 changed files with 557 additions and 210 deletions

View File

@ -865,26 +865,31 @@ Examples:
<section><title>Repeating rows and columns</title>
<p>
It's possible to set up repeating rows and columns in
your printouts by using the setRepeatingRowsAndColumns()
function in the HSSFWorkbook class.
your printouts by using the setRepeatingRows() and
setRepeatingColumns() methods in the Sheet class.
</p>
<p>
This function Contains 5 parameters.
The first parameter is the index to the sheet (0 = first sheet).
The second and third parameters specify the range for the columns to repreat.
To stop the columns from repeating pass in -1 as the start and end column.
The fourth and fifth parameters specify the range for the rows to repeat.
To stop the columns from repeating pass in -1 as the start and end rows.
These methods expect a CellRangeAddress parameter
which specifies the range for the rows or columns to
repeat.
For setRepeatingRows(), it should specify a range of
rows to repeat, with the column part spanning all
columns.
For setRepeatingColums(), it should specify a range of
columns to repeat, with the row part spanning all
rows.
If the parameter is null, the repeating rows or columns
will be removed.
</p>
<source>
Workbook wb = new HSSFWorkbook();
Sheet sheet1 = wb.createSheet("new sheet");
Sheet sheet2 = wb.createSheet("second sheet");
Workbook wb = new HSSFWorkbook(); // or new XSSFWorkbook();
Sheet sheet1 = wb.createSheet("Sheet1");
Sheet sheet2 = wb.createSheet("Sheet2");
// Set the columns to repeat from column 0 to 2 on the first sheet
wb.setRepeatingRowsAndColumns(0,0,2,-1,-1);
// Set the the repeating rows and columns on the second sheet.
wb.setRepeatingRowsAndColumns(1,4,5,1,2);
// Set the rows to repeat from row 4 to 5 on the first sheet.
sheet1.setRepeatingRows(CellRangeAddress.valueOf("4:5"));
// Set the columns to repeat from column A to C on the second sheet
sheet2.setRepeatingColumns(CellRangeAddress.valueOf("A:C"));
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);

View File

@ -200,6 +200,18 @@ public final class HSSFName implements Name {
return HSSFFormulaParser.toFormulaString(_book, ptgs);
}
/**
* Sets the NameParsedFormula structure that specifies the formula for the
* defined name.
*
* @param ptgs the sequence of {@link Ptg}s for the formula.
*/
void setNameDefinition(Ptg[] ptgs) {
_definedNameRec.setNameDefinition(ptgs);
}
public boolean isDeleted(){
Ptg[] ptgs = _definedNameRec.getNameDefinition();
return Ptg.doesFormulaReferToDeletedCell(ptgs);

View File

@ -32,8 +32,10 @@ import org.apache.poi.hssf.record.aggregates.DataValidityTable;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.aggregates.WorksheetProtectionBlock;
import org.apache.poi.ss.formula.FormulaShifter;
import org.apache.poi.ss.formula.ptg.MemFuncPtg;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.Area3DPtg;
import org.apache.poi.ss.formula.ptg.UnionPtg;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.FormulaType;
@ -2004,16 +2006,110 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
}
@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);
}
return;
}
if (name == null) {
name = _workbook.createBuiltInName(
NameRecord.BUILTIN_PRINT_TITLE, sheetIndex);
}
List<Ptg> ptgList = new ArrayList<Ptg>();
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) {
@ -2021,7 +2117,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
}
Ptg[] nameDefinition = rec.getNameDefinition();
if (rec.getNameDefinition() == null) {
if (nameDefinition == null) {
return null;
}

View File

@ -49,13 +49,10 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.formula.FormulaShifter;
import org.apache.poi.ss.formula.FormulaType;
import org.apache.poi.ss.formula.SheetNameFormatter;
import org.apache.poi.ss.formula.ptg.Area3DPtg;
import org.apache.poi.ss.formula.ptg.MemFuncPtg;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.UnionPtg;
import org.apache.poi.ss.formula.udf.AggregatingUDFFinder;
import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.WorkbookUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
@ -75,8 +72,6 @@ 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 int MAX_COLUMN = (short)0x00FF;
/**
* The maximum number of cell styles in a .xls workbook.
@ -957,80 +952,27 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
* @param endColumn 0 based end of repeating columns.
* @param startRow 0 based start of repeating rows.
* @param endRow 0 based end of repeating rows.
*
* @deprecated use {@link HSSFSheet#setRepeatingRows(CellRangeAddress)}
* or {@link HSSFSheet#setRepeatingColumns(CellRangeAddress)}
*/
public void setRepeatingRowsAndColumns(int sheetIndex,
int startColumn, int endColumn,
int startRow, int endRow)
{
// Check arguments
if (startColumn == -1 && endColumn != -1) throw new IllegalArgumentException("Invalid column range specification");
if (startRow == -1 && endRow != -1) throw new IllegalArgumentException("Invalid row range specification");
if (startColumn < -1 || startColumn >= MAX_COLUMN) throw new IllegalArgumentException("Invalid column range specification");
if (endColumn < -1 || endColumn >= MAX_COLUMN) throw new IllegalArgumentException("Invalid column range specification");
if (startRow < -1 || startRow > MAX_ROW) throw new IllegalArgumentException("Invalid row range specification");
if (endRow < -1 || endRow > MAX_ROW) throw new IllegalArgumentException("Invalid row range specification");
if (startColumn > endColumn) throw new IllegalArgumentException("Invalid column range specification");
if (startRow > endRow) throw new IllegalArgumentException("Invalid row range specification");
int startRow, int endRow) {
HSSFSheet sheet = getSheetAt(sheetIndex);
short externSheetIndex = getWorkbook().checkExternSheet(sheetIndex);
boolean settingRowAndColumn =
startColumn != -1 && endColumn != -1 && startRow != -1 && endRow != -1;
boolean removingRange =
startColumn == -1 && endColumn == -1 && startRow == -1 && endRow == -1;
CellRangeAddress rows = null;
CellRangeAddress cols = null;
int rowColHeaderNameIndex = findExistingBuiltinNameRecordIdx(sheetIndex, NameRecord.BUILTIN_PRINT_TITLE);
if (removingRange) {
if (rowColHeaderNameIndex >= 0) {
workbook.removeName(rowColHeaderNameIndex);
if (startRow != -1) {
rows = new CellRangeAddress(startRow, endRow, -1, -1);
}
return;
}
boolean isNewRecord;
NameRecord nameRecord;
if (rowColHeaderNameIndex < 0) {
//does a lot of the house keeping for builtin records, like setting lengths to zero etc
nameRecord = workbook.createBuiltInName(NameRecord.BUILTIN_PRINT_TITLE, sheetIndex+1);
isNewRecord = true;
} else {
nameRecord = workbook.getNameRecord(rowColHeaderNameIndex);
isNewRecord = false;
if (startColumn != -1) {
cols = new CellRangeAddress(-1, -1, startColumn, endColumn);
}
List temp = new ArrayList();
if (settingRowAndColumn) {
final int exprsSize = 2 * 11 + 1; // 2 * Area3DPtg.SIZE + UnionPtg.SIZE
temp.add(new MemFuncPtg(exprsSize));
}
if (startColumn >= 0) {
Area3DPtg colArea = new Area3DPtg(0, MAX_ROW, startColumn, endColumn,
false, false, false, false, externSheetIndex);
temp.add(colArea);
}
if (startRow >= 0) {
Area3DPtg rowArea = new Area3DPtg(startRow, endRow, 0, MAX_COLUMN,
false, false, false, false, externSheetIndex);
temp.add(rowArea);
}
if (settingRowAndColumn) {
temp.add(UnionPtg.instance);
}
Ptg[] ptgs = new Ptg[temp.size()];
temp.toArray(ptgs);
nameRecord.setNameDefinition(ptgs);
if (isNewRecord)
{
HSSFName newName = new HSSFName(this, nameRecord, nameRecord.isBuiltInName() ? null : workbook.getNameCommentRecord(nameRecord));
names.add(newName);
}
HSSFPrintSetup printSetup = sheet.getPrintSetup();
printSetup.setValidSettings(false);
sheet.setActive(true);
sheet.setRepeatingRows(rows);
sheet.setRepeatingColumns(cols);
}
@ -1050,6 +992,26 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
return -1;
}
HSSFName createBuiltInName(byte builtinCode, int sheetIndex) {
NameRecord nameRecord =
workbook.createBuiltInName(builtinCode, sheetIndex + 1);
HSSFName newName = new HSSFName(this, nameRecord, null);
names.add(newName);
return newName;
}
HSSFName getBuiltInName(byte builtinCode, int sheetIndex) {
int index = findExistingBuiltinNameRecordIdx(sheetIndex, builtinCode);
if (index < 0) {
return null;
} else {
return names.get(index);
}
}
/**
* create a new Font and add it to the workbook's font table
* @return new font object
@ -1477,6 +1439,25 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
}
/**
* As {@link #getNameIndex(String)} is not necessarily unique
* (name + sheet index is unique), this method is more accurate.
*
* @param name the name whose index in the list of names of this workbook
* should be looked up.
* @return an index value >= 0 if the name was found; -1, if the name was
* not found
*/
int getNameIndex(HSSFName name) {
for (int k = 0; k < names.size(); k++) {
if (name == names.get(k)) {
return k;
}
}
return -1;
}
public void removeName(int index){
names.remove(index);
workbook.removeName(index);
@ -1497,7 +1478,18 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
public void removeName(String name) {
int index = getNameIndex(name);
removeName(index);
}
/**
* As {@link #removeName(String)} is not necessarily unique
* (name + sheet index is unique), this method is more accurate.
*
* @param name the name to remove.
*/
void removeName(HSSFName name) {
int index = getNameIndex(name);
removeName(index);
}

View File

@ -965,10 +965,57 @@ public interface Sheet extends Iterable<Row> {
* 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.
* @return an {@link CellRangeAddress} containing the repeating columns for
* the Sheet, or null.
*/
CellRangeAddress getRepeatingColumns();
/**
* Sets 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 parameter {@link CellRangeAddress} should specify a column part
* which spans all columns, and a row part which specifies the contiguous
* range of repeating rows, e.g.:
* <pre>
* sheet.setRepeatingRows(CellRangeAddress.valueOf("2:3"));</pre>
* A null parameter value indicates that repeating rows should be removed
* from the Sheet:
* <pre>
* sheet.setRepeatingRows(null);</pre>
*
* @param rowRangeRef a {@link CellRangeAddress} containing the repeating
* rows for the Sheet, or null.
*/
void setRepeatingRows(CellRangeAddress rowRangeRef);
/**
* Sets 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 parameter {@link CellRangeAddress} should specify a row part
* which spans all rows, and a column part which specifies the contiguous
* range of repeating columns, e.g.:
* <pre>
* sheet.setRepeatingColumns(CellRangeAddress.valueOf("B:C"));</pre>
* A null parameter value indicates that repeating columns should be removed
* from the Sheet:
* <pre>
* sheet.setRepeatingColumns(null);</pre>
*
* @param columnRangeRef a {@link CellRangeAddress} containing the repeating
* columns for the Sheet, or null.
*/
void setRepeatingColumns(CellRangeAddress columnRangeRef);
}

View File

@ -23,6 +23,7 @@ import java.util.List;
import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
import org.apache.poi.ss.util.CellRangeAddress;
/**
* High level representation of a Excel workbook. This is the first object most users
@ -284,6 +285,9 @@ public interface Workbook {
* @param endColumn 0 based end of repeating columns.
* @param startRow 0 based start of repeating rows.
* @param endRow 0 based end of repeating rows.
*
* @deprecated use {@link Sheet#setRepeatingRows(CellRangeAddress)}
* or {@link Sheet#setRepeatingColumns(CellRangeAddress)}
*/
void setRepeatingRowsAndColumns(int sheetIndex, int startColumn, int endColumn, int startRow, int endRow);

View File

@ -111,8 +111,12 @@ public class CellRangeAddress extends CellRangeAddressBase {
}
/**
* @param ref usually a standard area ref (e.g. "B1:D8"). May be a single cell
* ref (e.g. "B5") in which case the result is a 1 x 1 cell range.
* Creates a CellRangeAddress from a cell range reference string.
*
* @param ref usually a standard area ref (e.g. "B1:D8"). May be a single
* cell ref (e.g. "B5") in which case the result is a 1 x 1 cell
* range. May also be a whole row range (e.g. "3:5"), or a whole
* column range (e.g. "C:F")
*/
public static CellRangeAddress valueOf(String ref) {
int sep = ref.indexOf(":");

View File

@ -17,20 +17,32 @@
package org.apache.poi.xssf.streaming;
import java.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.TreeMap;
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;
import java.util.TreeMap;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.AutoFilter;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellRange;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Footer;
import org.apache.poi.ss.usermodel.Header;
import org.apache.poi.ss.usermodel.PrintSetup;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.SheetUtil;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetFormatPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
@ -1266,15 +1278,28 @@ public class SXSSFSheet implements Sheet, Cloneable
}
@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
/**

View File

@ -42,6 +42,7 @@ import java.util.zip.ZipEntry;
import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
import org.apache.poi.ss.util.CellRangeAddress;
/**
* Streaming version of XSSFWorkbook implementing the "BigGridDemo" strategy.
@ -662,6 +663,9 @@ public class SXSSFWorkbook implements Workbook
* @param endColumn 0 based end of repeating columns.
* @param startRow 0 based start of repeating rows.
* @param endRow 0 based end of repeating rows.
*
* @deprecated use {@link SXSSFSheet#setRepeatingRows(CellRangeAddress)}
* or {@link SXSSFSheet#setRepeatingColumns(CellRangeAddress)}
*/
public void setRepeatingRowsAndColumns(int sheetIndex, int startColumn, int endColumn, int startRow, int endRow)
{

View File

@ -41,6 +41,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.FormulaShifter;
import org.apache.poi.ss.formula.SheetNameFormatter;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
@ -3187,15 +3188,130 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
}
@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);
@ -3232,5 +3348,4 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
return null;
}
}

View File

@ -52,6 +52,7 @@ import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.WorkbookUtil;
import org.apache.poi.util.*;
@ -925,6 +926,20 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
throw new IllegalArgumentException("Named range was not found: " + name);
}
/**
* As {@link #removeName(String)} is not necessarily unique
* (name + sheet index is unique), this method is more accurate.
*
* @param name the name to remove.
*/
void removeName(XSSFName name) {
if (!namedRanges.remove(name)) {
throw new IllegalArgumentException("Name was not found: " + name);
}
}
/**
* Delete the printarea for the sheet specified
*
@ -1129,71 +1144,27 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
* @param endColumn 0 based end of repeating columns.
* @param startRow 0 based start of repeating rows.
* @param endRow 0 based end of repeating rows.
*
* @deprecated use {@link XSSFSheet#setRepeatingRows(CellRangeAddress)}
* or {@link XSSFSheet#setRepeatingColumns(CellRangeAddress)}
*/
public void setRepeatingRowsAndColumns(int sheetIndex,
int startColumn, int endColumn,
int startRow, int endRow) {
// Check arguments
if ((startColumn == -1 && endColumn != -1) || startColumn < -1 || endColumn < -1 || startColumn > endColumn)
throw new IllegalArgumentException("Invalid column range specification");
if ((startRow == -1 && endRow != -1) || startRow < -1 || endRow < -1 || startRow > endRow)
throw new IllegalArgumentException("Invalid row range specification");
XSSFSheet sheet = getSheetAt(sheetIndex);
boolean removingRange = startColumn == -1 && endColumn == -1 && startRow == -1 && endRow == -1;
XSSFName name = getBuiltInName(XSSFName.BUILTIN_PRINT_TITLE, sheetIndex);
if (removingRange) {
if(name != null)namedRanges.remove(name);
return;
CellRangeAddress rows = null;
CellRangeAddress cols = null;
if (startRow != -1) {
rows = new CellRangeAddress(startRow, endRow, -1, -1);
}
if (name == null) {
name = createBuiltInName(XSSFName.BUILTIN_PRINT_TITLE, sheetIndex);
if (startColumn != -1) {
cols = new CellRangeAddress(-1, -1, startColumn, endColumn);
}
String reference = getReferenceBuiltInRecord(name.getSheetName(), startColumn, endColumn, startRow, endRow);
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!
CTWorksheet ctSheet = sheet.getCTWorksheet();
if(ctSheet.isSetPageSetup() && ctSheet.isSetPageMargins()) {
// Everything we need is already there
} else {
// Have initial ones put in place
XSSFPrintSetup printSetup = sheet.getPrintSetup();
printSetup.setValidSettings(false);
}
}
private static String getReferenceBuiltInRecord(String sheetName, int startC, int endC, int startR, int endR) {
//windows 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);
String escapedName = SheetNameFormatter.format(sheetName);
String c;
if(startC == -1 && endC == -1) c= "";
else c = escapedName + "!$" + colRef.getCellRefParts()[2] + ":$" + colRef2.getCellRefParts()[2];
CellReference rowRef = new CellReference(sheetName, startR, 0, true, true);
CellReference rowRef2 = new CellReference(sheetName, endR, 0, true, true);
String r = "";
if(startR == -1 && endR == -1) r = "";
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();
sheet.setRepeatingRows(rows);
sheet.setRepeatingColumns(cols);
}
private static String getReferencePrintArea(String sheetName, int startC, int endC, int startR, int endR) {

View File

@ -20,6 +20,7 @@ package org.apache.poi.xssf.usermodel;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.ss.usermodel.BaseTestNamedRange;
import org.apache.poi.ss.util.CellRangeAddress;
/**
* @author Yegor Kozlov
@ -35,13 +36,15 @@ public final class TestXSSFName extends BaseTestNamedRange {
// First test that setting RR&C for same sheet more than once only creates a
// single Print_Titles built-in record
XSSFWorkbook wb = new XSSFWorkbook();
wb.createSheet("First Sheet");
XSSFSheet sheet1 = wb.createSheet("First Sheet");
wb.setRepeatingRowsAndColumns(0, -1, -1, -1, -1);
sheet1.setRepeatingRows(null);
sheet1.setRepeatingColumns(null);
// set repeating rows and columns twice for the first sheet
for (int i = 0; i < 2; i++) {
wb.setRepeatingRowsAndColumns(0, 0, 0, 0, 3);
sheet1.setRepeatingRows(CellRangeAddress.valueOf("1:4"));
sheet1.setRepeatingColumns(CellRangeAddress.valueOf("A:A"));
//sheet.createFreezePane(0, 3);
}
assertEquals(1, wb.getNumberOfNames());
@ -51,18 +54,18 @@ public final class TestXSSFName extends BaseTestNamedRange {
assertEquals("'First Sheet'!$A:$A,'First Sheet'!$1:$4", nr1.getRefersToFormula());
//remove the columns part
wb.setRepeatingRowsAndColumns(0, -1, -1, 0, 3);
sheet1.setRepeatingColumns(null);
assertEquals("'First Sheet'!$1:$4", nr1.getRefersToFormula());
//revert
wb.setRepeatingRowsAndColumns(0, 0, 0, 0, 3);
sheet1.setRepeatingColumns(CellRangeAddress.valueOf("A:A"));
//remove the rows part
wb.setRepeatingRowsAndColumns(0, 0, 0, -1, -1);
sheet1.setRepeatingRows(null);
assertEquals("'First Sheet'!$A:$A", nr1.getRefersToFormula());
//revert
wb.setRepeatingRowsAndColumns(0, 0, 0, 0, 3);
sheet1.setRepeatingRows(CellRangeAddress.valueOf("1:4"));
// Save and re-open
XSSFWorkbook nwb = XSSFTestDataSamples.writeOutAndReadBack(wb);
@ -75,8 +78,9 @@ public final class TestXSSFName extends BaseTestNamedRange {
// check that setting RR&C on a second sheet causes a new Print_Titles built-in
// name to be created
nwb.createSheet("SecondSheet");
nwb.setRepeatingRowsAndColumns(1, 1, 2, 0, 0);
XSSFSheet sheet2 = nwb.createSheet("SecondSheet");
sheet2.setRepeatingRows(CellRangeAddress.valueOf("1:1"));
sheet2.setRepeatingColumns(CellRangeAddress.valueOf("B:C"));
assertEquals(2, nwb.getNumberOfNames());
XSSFName nr2 = nwb.getNameAt(1);
@ -84,6 +88,7 @@ public final class TestXSSFName extends BaseTestNamedRange {
assertEquals(XSSFName.BUILTIN_PRINT_TITLE, nr2.getNameName());
assertEquals("SecondSheet!$B:$C,SecondSheet!$1:$1", nr2.getRefersToFormula());
nwb.setRepeatingRowsAndColumns(1, -1, -1, -1, -1);
sheet2.setRepeatingRows(null);
sheet2.setRepeatingColumns(null);
}
}

View File

@ -57,6 +57,22 @@ public final class TestHSSFSheet extends BaseTestSheet {
super(HSSFITestDataProvider.instance);
}
/**
* Test for Bugzilla #29747.
* Moved from TestHSSFWorkbook#testSetRepeatingRowsAndColumns().
*/
public void testSetRepeatingRowsAndColumnsBug29747() {
HSSFWorkbook wb = new HSSFWorkbook();
wb.createSheet();
wb.createSheet();
HSSFSheet sheet2 = wb.createSheet();
sheet2.setRepeatingRows(CellRangeAddress.valueOf("1:2"));
NameRecord nameRecord = wb.getWorkbook().getNameRecord(0);
assertEquals(3, nameRecord.getSheetNumber());
}
public void testTestGetSetMargin() {
baseTestGetSetMargin(new double[]{0.75, 0.75, 1.0, 1.0, 0.3, 0.3});
}

View File

@ -56,17 +56,6 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
return wb.getWorkbook();
}
public void testSetRepeatingRowsAndColumns() {
// Test bug 29747
HSSFWorkbook b = new HSSFWorkbook( );
b.createSheet();
b.createSheet();
b.createSheet();
b.setRepeatingRowsAndColumns( 2, 0,1,-1,-1 );
NameRecord nameRecord = b.getWorkbook().getNameRecord( 0 );
assertEquals(3, nameRecord.getSheetNumber());
}
public void testWindowOneDefaults() {
HSSFWorkbook b = new HSSFWorkbook( );
try {
@ -501,7 +490,8 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
assertEquals("Sheet2!$A$1:$IV$1", HSSFFormulaParser.toFormulaString(wb, nr.getNameDefinition())); // 1:1
try {
wb.setRepeatingRowsAndColumns(3, 4, 5, 8, 11);
wb.getSheetAt(3).setRepeatingRows(CellRangeAddress.valueOf("9:12"));
wb.getSheetAt(3).setRepeatingColumns(CellRangeAddress.valueOf("E:F"));
} catch (RuntimeException e) {
if (e.getMessage().equals("Builtin (7) already exists for sheet (4)")) {
// there was a problem in the code which locates the existing print titles name record

View File

@ -712,4 +712,78 @@ public abstract class BaseTestSheet extends TestCase {
assertNull(sheet.getPaneInformation());
}
public void testGetRepeatingRowsAndColumns() {
Workbook wb = _testDataProvider.openSampleWorkbook(
"RepeatingRowsCols."
+ _testDataProvider.getStandardFileNameExtension());
checkRepeatingRowsAndColumns(wb.getSheetAt(0), null, null);
checkRepeatingRowsAndColumns(wb.getSheetAt(1), "1:1", null);
checkRepeatingRowsAndColumns(wb.getSheetAt(2), null, "A:A");
checkRepeatingRowsAndColumns(wb.getSheetAt(3), "2:3", "A:B");
}
public void testSetRepeatingRowsAndColumnsBug47294(){
Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet1 = wb.createSheet();
sheet1.setRepeatingRows(CellRangeAddress.valueOf("1:4"));
assertEquals("1:4", sheet1.getRepeatingRows().formatAsString());
//must handle sheets with quotas, see Bugzilla #47294
Sheet sheet2 = wb.createSheet("My' Sheet");
sheet2.setRepeatingRows(CellRangeAddress.valueOf("1:4"));
assertEquals("1:4", sheet2.getRepeatingRows().formatAsString());
}
public void testSetRepeatingRowsAndColumns() {
Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet1 = wb.createSheet("Sheet1");
Sheet sheet2 = wb.createSheet("Sheet2");
Sheet sheet3 = wb.createSheet("Sheet3");
checkRepeatingRowsAndColumns(sheet1, null, null);
sheet1.setRepeatingRows(CellRangeAddress.valueOf("4:5"));
sheet2.setRepeatingColumns(CellRangeAddress.valueOf("A:C"));
sheet3.setRepeatingRows(CellRangeAddress.valueOf("1:4"));
sheet3.setRepeatingColumns(CellRangeAddress.valueOf("A:A"));
checkRepeatingRowsAndColumns(sheet1, "4:5", null);
checkRepeatingRowsAndColumns(sheet2, null, "A:C");
checkRepeatingRowsAndColumns(sheet3, "1:4", "A:A");
// write out, read back, and test refrain...
wb = _testDataProvider.writeOutAndReadBack(wb);
sheet1 = wb.getSheetAt(0);
sheet2 = wb.getSheetAt(1);
sheet3 = wb.getSheetAt(2);
checkRepeatingRowsAndColumns(sheet1, "4:5", null);
checkRepeatingRowsAndColumns(sheet2, null, "A:C");
checkRepeatingRowsAndColumns(sheet3, "1:4", "A:A");
// check removing repeating rows and columns
sheet3.setRepeatingRows(null);
checkRepeatingRowsAndColumns(sheet3, null, "A:A");
sheet3.setRepeatingColumns(null);
checkRepeatingRowsAndColumns(sheet3, null, null);
}
private void checkRepeatingRowsAndColumns(
Sheet s, String expectedRows, String expectedCols) {
if (expectedRows == null) {
assertNull(s.getRepeatingRows());
} else {
assertEquals(expectedRows, s.getRepeatingRows().formatAsString());
}
if (expectedCols == null) {
assertNull(s.getRepeatingColumns());
} else {
assertEquals(expectedCols, s.getRepeatingColumns().formatAsString());
}
}
}

View File

@ -360,39 +360,26 @@ public abstract class BaseTestWorkbook extends TestCase {
}
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());
}
/**
* Test is kept to ensure stub for deprecated business method passes test.
*
* @Deprecated remove this test when
* {@link Workbook#setRepeatingRowsAndColumns(int, int, int, int, int)}
* is removed
*/
@Deprecated
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());
assertEquals("A:A", sheet1.getRepeatingColumns().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());
assertEquals("A:A", sheet1.getRepeatingColumns().formatAsString());
}
/**