Bugzilla 51160: Initial version of SXSSF, a low memory foortprint API to produce xlsx files

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1104120 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2011-05-17 10:46:35 +00:00
parent a3f7224e14
commit 339149dd5e
6 changed files with 3861 additions and 1 deletions

View File

@ -34,7 +34,8 @@
<changes>
<release version="3.8-beta3" date="2011-??-??">
<action dev="poi-developers" type="add">51171 - Improved performance of opening large .xls files</action>
<action dev="poi-developers" type="add">51160 - Initial version of SXSSF, a low memory foortprint API to produce xlsx files</action>
<action dev="poi-developers" type="fix">51171 - Improved performance of opening large .xls files</action>
<action dev="poi-developers" type="add">51172 - Add XWPF support for GIF pictures</action>
<action dev="poi-developers" type="add">NPOIFS Mini Streams now support extending the underlying big block stream to fit more data</action>
<action dev="poi-developers" type="fix">51148 - XWPFDocument now properly tracks paragraphs and tables when adding/removing them</action>

View File

@ -0,0 +1,204 @@
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.apache.poi.ss.examples;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
public class SSPerformanceTest {
public static void main(String[] args) {
if (args.length != 4) usage("need four command arguments");
String type = args[0];
long timeStarted = System.currentTimeMillis();
Workbook workBook = createWorkbook(type);
boolean isHType = workBook instanceof HSSFWorkbook;
int rows = parseInt(args[1], "Failed to parse rows value as integer");
int cols = parseInt(args[2], "Failed to parse cols value as integer");
boolean saveFile = parseInt(args[3], "Failed to parse saveFile value as integer") != 0;
Map<String, CellStyle> styles = createStyles(workBook);
Sheet sheet = workBook.createSheet("Main Sheet");
Cell headerCell = sheet.createRow(0).createCell(0);
headerCell.setCellValue("Header text is spanned across multiple cells");
headerCell.setCellStyle(styles.get("header"));
sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$F$1"));
int sheetNo = 0;
int rowIndexInSheet = 1;
double value = 0;
Calendar calendar = Calendar.getInstance();
for (int rowIndex = 0; rowIndex < rows; rowIndex++) {
if (isHType && sheetNo != rowIndex / 0x10000) {
sheet = workBook.createSheet("Spillover from sheet " + (++sheetNo));
headerCell.setCellValue("Header text is spanned across multiple cells");
headerCell.setCellStyle(styles.get("header"));
sheet.addMergedRegion(CellRangeAddress.valueOf("$A$1:$F$1"));
rowIndexInSheet = 1;
}
Row row = sheet.createRow(rowIndexInSheet);
for (int colIndex = 0; colIndex < cols; colIndex++) {
Cell cell = row.createCell(colIndex);
String address = new CellReference(cell).formatAsString();
switch (colIndex){
case 0:
// column A: default number format
cell.setCellValue(value++);
break;
case 1:
// column B: #,##0
cell.setCellValue(value++);
cell.setCellStyle(styles.get("#,##0.00"));
break;
case 2:
// column C: $#,##0.00
cell.setCellValue(value++);
cell.setCellStyle(styles.get("$#,##0.00"));
break;
case 3:
// column D: red bold text on yellow background
cell.setCellValue(address);
cell.setCellStyle(styles.get("red-bold"));
break;
case 4:
// column E: boolean
// TODO booleans are shown as 1/0 instead of TRUE/FALSE
cell.setCellValue(rowIndex % 2 == 0);
break;
case 5:
// column F: date / time
cell.setCellValue(calendar);
cell.setCellStyle(styles.get("m/d/yyyy"));
calendar.roll(Calendar.DAY_OF_YEAR, -1);
break;
case 6:
// column F: formula
// TODO formulas are not yet supported in SXSSF
//cell.setCellFormula("SUM(A" + (rowIndex+1) + ":E" + (rowIndex+1)+ ")");
//break;
default:
cell.setCellValue(value++);
break;
}
}
rowIndexInSheet++;
}
if (saveFile) {
String fileName = type + "_" + rows + "_" + cols + "." + getFileSuffix(args[0]);
try {
FileOutputStream out = new FileOutputStream(fileName);
workBook.write(out);
out.close();
} catch (IOException ioe) {
System.err.println("Error: failed to write to file \"" + fileName + "\", reason=" + ioe.getMessage());
}
}
long timeFinished = System.currentTimeMillis();
System.out.println("Elapsed " + (timeFinished-timeStarted)/1000 + " seconds");
}
static Map<String, CellStyle> createStyles(Workbook wb) {
Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
CellStyle style;
Font headerFont = wb.createFont();
headerFont.setFontHeightInPoints((short) 14);
headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
style = wb.createCellStyle();
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
style.setFont(headerFont);
style.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
style.setFillPattern(CellStyle.SOLID_FOREGROUND);
styles.put("header", style);
Font monthFont = wb.createFont();
monthFont.setFontHeightInPoints((short)12);
monthFont.setColor(IndexedColors.RED.getIndex());
monthFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
style = wb.createCellStyle();
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
style.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
style.setFillPattern(CellStyle.SOLID_FOREGROUND);
style.setFont(monthFont);
styles.put("red-bold", style);
String[] nfmt = {"#,##0.00", "$#,##0.00", "m/d/yyyy"};
for(String fmt : nfmt){
style = wb.createCellStyle();
style.setDataFormat(wb.createDataFormat().getFormat(fmt));
styles.put(fmt, style);
}
return styles;
}
static void usage(String message) {
System.err.println(message);
System.err.println("usage: java SSPerformanceTest HSSF|XSSF|SXSSF rows cols saveFile (0|1)? ");
System.exit(1);
}
static Workbook createWorkbook(String type) {
if ("HSSF".equals(type))
return new HSSFWorkbook();
else if ("XSSF".equals(type))
return new XSSFWorkbook();
else if ("SXSSF".equals(type))
return new SXSSFWorkbook();
else
usage("Unknown type \"" + type + "\"");
return null;
}
static String getFileSuffix(String type) {
if ("HSSF".equals(type))
return "xls";
else if ("XSSF".equals(type))
return "xlsx";
else if ("SXSSF".equals(type))
return "xlsx";
return null;
}
static int parseInt(String value, String msg) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
usage(msg);
}
return 0;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,388 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xssf.streaming;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Streaming version of XSSFRow implementing the "BigGridDemo" strategy.
*
* @author Alex Geller, Four J's Development Tools
*/
public class SXSSFRow implements Row
{
SXSSFSheet _sheet;
SXSSFCell[] _cells;
int _maxColumn=-1;
short _height=-1;
//TODO: Need to set the correct default value for _zHeight
boolean _zHeight;
public SXSSFRow(SXSSFSheet sheet, int initialSize)
{
_sheet=sheet;
_cells=new SXSSFCell[initialSize];
}
public Iterator<Cell> allCellsIterator()
{
return new CellIterator();
}
public boolean hasCustomHeight()
{
return _height!=-1;
}
//begin of interface implementation
public Iterator<Cell> iterator()
{
return new FilledCellIterator();
}
/**
* Use this to create new cells within the row and return it.
* <p>
* The cell that is returned is a {@link Cell#CELL_TYPE_BLANK}. The type can be changed
* either through calling <code>setCellValue</code> or <code>setCellType</code>.
*
* @param column - the column number this cell represents
* @return Cell a high level representation of the created cell.
* @throws IllegalArgumentException if columnIndex < 0 or greater than the maximum number of supported columns
* (255 for *.xls, 1048576 for *.xlsx)
*/
public Cell createCell(int column)
{
return createCell(column,Cell.CELL_TYPE_BLANK);
}
/**
* Use this to create new cells within the row and return it.
* <p>
* The cell that is returned is a {@link Cell#CELL_TYPE_BLANK}. The type can be changed
* either through calling setCellValue or setCellType.
*
* @param column - the column number this cell represents
* @return Cell a high level representation of the created cell.
* @throws IllegalArgumentException if columnIndex < 0 or greate than a maximum number of supported columns
* (255 for *.xls, 1048576 for *.xlsx)
*/
public Cell createCell(int column, int type)
{
if(column>=_cells.length)
{
SXSSFCell[] newCells=new SXSSFCell[Math.max(column+1,_cells.length*2)];
System.arraycopy(_cells,0,newCells,0,_cells.length);
_cells=newCells;
}
_cells[column]=new SXSSFCell(this,type);
if(column>_maxColumn) _maxColumn=column;
return _cells[column];
}
/**
* Remove the Cell from this row.
*
* @param cell the cell to remove
*/
public void removeCell(Cell cell)
{
int index=getCellIndex(cell);
if(index>=0)
{
_cells[index]=null;
while(_maxColumn>=0&&_cells[_maxColumn]==null) _maxColumn--;
}
}
int getCellIndex(Cell cell)
{
for(int i=0;i<=_maxColumn;i++)
{
if(_cells[i]==cell) return i;
}
return -1;
}
/**
* Set the row number of this row.
*
* @param rowNum the row number (0-based)
* @throws IllegalArgumentException if rowNum < 0
*/
public void setRowNum(int rowNum)
{
_sheet.changeRowNum(this,rowNum);
}
/**
* Get row number this row represents
*
* @return the row number (0 based)
*/
public int getRowNum()
{
return _sheet.getRowNum(this);
}
/**
* Get the cell representing a given column (logical cell) 0-based. If you
* ask for a cell that is not defined....you get a null.
*
* @param cellnum 0 based column number
* @return Cell representing that column or null if undefined.
* @see #getCell(int, org.apache.poi.ss.usermodel.Row.MissingCellPolicy)
*/
public Cell getCell(int cellnum)
{
return cellnum>_maxColumn?null:_cells[cellnum];
}
/**
* Returns the cell at the given (0 based) index, with the specified {@link org.apache.poi.ss.usermodel.Row.MissingCellPolicy}
*
* @return the cell at the given (0 based) index
* @throws IllegalArgumentException if cellnum < 0 or the specified MissingCellPolicy is invalid
* @see Row#RETURN_NULL_AND_BLANK
* @see Row#RETURN_BLANK_AS_NULL
* @see Row#CREATE_NULL_AS_BLANK
*/
public Cell getCell(int cellnum, MissingCellPolicy policy)
{
assert false;
Cell cell = getCell(cellnum);
if(policy == RETURN_NULL_AND_BLANK)
{
return cell;
}
if(policy == RETURN_BLANK_AS_NULL)
{
if(cell == null) return cell;
if(cell.getCellType() == Cell.CELL_TYPE_BLANK)
{
return null;
}
return cell;
}
if(policy == CREATE_NULL_AS_BLANK)
{
if(cell == null)
{
return createCell(cellnum, Cell.CELL_TYPE_BLANK);
}
return cell;
}
throw new IllegalArgumentException("Illegal policy " + policy + " (" + policy.id + ")");
}
/**
* Get the number of the first cell contained in this row.
*
* @return short representing the first logical cell in the row,
* or -1 if the row does not contain any cells.
*/
public short getFirstCellNum()
{
for(int i=0;i<=_maxColumn;i++)
if(_cells[i]!=null) return (short)i;
return -1;
}
/**
* Gets the index of the last cell contained in this row <b>PLUS ONE</b>. The result also
* happens to be the 1-based column number of the last cell. This value can be used as a
* standard upper bound when iterating over cells:
* <pre>
* short minColIx = row.getFirstCellNum();
* short maxColIx = row.getLastCellNum();
* for(short colIx=minColIx; colIx&lt;maxColIx; colIx++) {
* Cell cell = row.getCell(colIx);
* if(cell == null) {
* continue;
* }
* //... do something with cell
* }
* </pre>
*
* @return short representing the last logical cell in the row <b>PLUS ONE</b>,
* or -1 if the row does not contain any cells.
*/
public short getLastCellNum()
{
return (short)(_maxColumn+1);
}
/**
* Gets the number of defined cells (NOT number of cells in the actual row!).
* That is to say if only columns 0,4,5 have values then there would be 3.
*
* @return int representing the number of defined cells in the row.
*/
public int getPhysicalNumberOfCells()
{
int count=0;
for(int i=0;i<=_maxColumn;i++)
{
if(_cells[i]!=null) count++;
}
return count;
}
/**
* Set the row's height or set to ff (-1) for undefined/default-height. Set the height in "twips" or
* 1/20th of a point.
*
* @param height rowheight or 0xff for undefined (use sheet default)
*/
public void setHeight(short height)
{
_height=height;
}
/**
* Set whether or not to display this row with 0 height
*
* @param zHeight height is zero or not.
*/
public void setZeroHeight(boolean zHeight)
{
_zHeight=zHeight;
}
/**
* Get whether or not to display this row with 0 height
*
* @return - zHeight height is zero or not.
*/
public boolean getZeroHeight()
{
return _zHeight;
}
/**
* Set the row's height in points.
*
* @param height the height in points. <code>-1</code> resets to the default height
*/
public void setHeightInPoints(float height)
{
if(height==-1)
_height=-1;
else
_height=(short)(height*20);
}
/**
* Get the row's height measured in twips (1/20th of a point). If the height is not set, the default worksheet value is returned,
* See {@link Sheet#getDefaultRowHeightInPoints()}
*
* @return row height measured in twips (1/20th of a point)
*/
public short getHeight()
{
return (short)(_height==-1?getSheet().getDefaultRowHeightInPoints()*20:_height);
}
/**
* Returns row height measured in point size. If the height is not set, the default worksheet value is returned,
* See {@link Sheet#getDefaultRowHeightInPoints()}
*
* @return row height measured in point size
* @see Sheet#getDefaultRowHeightInPoints()
*/
public float getHeightInPoints()
{
return (float)(_height==-1?getSheet().getDefaultRowHeightInPoints():(float)_height/20.0);
}
/**
* @return Cell iterator of the physically defined cells. Note element 4 may
* actually be row cell depending on how many are defined!
*/
public Iterator<Cell> cellIterator()
{
return iterator();
}
/**
* Returns the Sheet this row belongs to
*
* @return the Sheet that owns this row
*/
public Sheet getSheet()
{
return _sheet;
}
//end of interface implementation
/** returns all filled cells (created via Row.createCell())*/
public class FilledCellIterator implements Iterator<Cell>
{
int pos=0;
public boolean hasNext()
{
return pos <= _maxColumn;
}
void advanceToNext()
{
pos++;
while(pos<=_maxColumn&&_cells[pos]==null) pos++;
}
public Cell next() throws NoSuchElementException
{
if (hasNext())
{
Cell retval=_cells[pos];
advanceToNext();
return retval;
}
else
{
throw new NoSuchElementException();
}
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
/** returns all cells including empty cells in which case "null" is returned*/
public class CellIterator implements Iterator<Cell>
{
int pos=0;
public boolean hasNext()
{
return pos <= _maxColumn;
}
public Cell next() throws NoSuchElementException
{
if (hasNext())
return _cells[pos++];
else
throw new NoSuchElementException();
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,779 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.xssf.streaming;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import java.io.File;
import java.util.List;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import java.util.zip.ZipEntry;
import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
/**
* Streaming version of XSSFWorkbook implementing the "BigGridDemo" strategy.
*
* @author Alex Geller, Four J's Development Tools
*/
public class SXSSFWorkbook implements Workbook
{
XSSFWorkbook _wb=new XSSFWorkbook();
Hashtable<SXSSFSheet,XSSFSheet> _sxFromXHash=new Hashtable<SXSSFSheet,XSSFSheet>();
Hashtable<XSSFSheet,SXSSFSheet> _xFromSxHash=new Hashtable<XSSFSheet,SXSSFSheet>();
XSSFSheet getXSSFSheet(SXSSFSheet sheet)
{
XSSFSheet result=_sxFromXHash.get(sheet);
assert result!=null;
return result;
}
SXSSFSheet getSXSSFSheet(XSSFSheet sheet)
{
SXSSFSheet result=_xFromSxHash.get(sheet);
assert result!=null;
return result;
}
void registerSheetMapping(SXSSFSheet sxSheet,XSSFSheet xSheet)
{
_sxFromXHash.put(sxSheet,xSheet);
_xFromSxHash.put(xSheet,sxSheet);
}
void deregisterSheetMapping(XSSFSheet xSheet)
{
SXSSFSheet sxSheet=getSXSSFSheet(xSheet);
_sxFromXHash.remove(sxSheet);
_xFromSxHash.remove(xSheet);
}
private XSSFSheet getSheetFromZipEntryName(String sheetRef)
{
Enumeration<XSSFSheet> sheets=_sxFromXHash.elements();
while(sheets.hasMoreElements())
{
XSSFSheet sheet=sheets.nextElement();
if(sheetRef.equals(sheet.getPackagePart().getPartName().getName().substring(1))) return sheet;
}
return null;
}
private void injectData(File zipfile, OutputStream out) throws IOException
{
ZipFile zip = new ZipFile(zipfile);
ZipOutputStream zos = new ZipOutputStream(out);
@SuppressWarnings("unchecked")
Enumeration<ZipEntry> en = (Enumeration<ZipEntry>) zip.entries();
while (en.hasMoreElements())
{
ZipEntry ze = en.nextElement();
zos.putNextEntry(new ZipEntry(ze.getName()));
InputStream is = zip.getInputStream(ze);
XSSFSheet xSheet=getSheetFromZipEntryName(ze.getName());
if(xSheet!=null)
{
SXSSFSheet sxSheet=getSXSSFSheet(xSheet);
copyStreamAndInjectWorksheet(is,zos,sxSheet.getWorksheetXMLInputStream());
}
else
{
copyStream(is, zos);
}
is.close();
}
zos.close();
}
private static void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] chunk = new byte[1024];
int count;
while ((count = in.read(chunk)) >=0 ) {
out.write(chunk,0,count);
}
}
private static void copyStreamAndInjectWorksheet(InputStream in, OutputStream out,InputStream worksheetData) throws IOException {
InputStreamReader inReader=new InputStreamReader(in,"UTF-8"); //TODO: Is it always UTF-8 or do we need to read the xml encoding declaration in the file? If not, we should perhaps use a SAX reader instead.
OutputStreamWriter outWriter=new OutputStreamWriter(out,"UTF-8");
int c;
int pos=0;
String s="<sheetData/>";
int n=s.length();
//Copy from "in" to "out" up to the string "<sheetData/>" (excluding).
while(((c=inReader.read())!=-1))
{
if(c==s.charAt(pos))
{
pos++;
if(pos==n) break;
}
else
{
if(pos>0) outWriter.write(s,0,pos);
if(c==s.charAt(0))
{
pos=1;
}
else
{
outWriter.write(c);
pos=0;
}
}
}
outWriter.flush();
//Copy the worksheet data to "out".
copyStream(worksheetData,out);
//Copy the rest of "in" to "out".
while(((c=inReader.read())!=-1))
outWriter.write(c);
outWriter.flush();
}
public XSSFWorkbook getXSSFWorkbook()
{
return _wb;
}
//start of interface implementation
/**
* Convenience method to get the active sheet. The active sheet is is the sheet
* which is currently displayed when the workbook is viewed in Excel.
* 'Selected' sheet(s) is a distinct concept.
*
* @return the index of the active sheet (0-based)
*/
public int getActiveSheetIndex()
{
return _wb.getActiveSheetIndex();
}
/**
* Convenience method to set the active sheet. The active sheet is is the sheet
* which is currently displayed when the workbook is viewed in Excel.
* 'Selected' sheet(s) is a distinct concept.
*
* @param sheetIndex index of the active sheet (0-based)
*/
public void setActiveSheet(int sheetIndex)
{
_wb.setActiveSheet(sheetIndex);
}
/**
* Gets the first tab that is displayed in the list of tabs in excel.
*
* @return the first tab that to display in the list of tabs (0-based).
*/
public int getFirstVisibleTab()
{
return _wb.getFirstVisibleTab();
}
/**
* Sets the first tab that is displayed in the list of tabs in excel.
*
* @param sheetIndex the first tab that to display in the list of tabs (0-based)
*/
public void setFirstVisibleTab(int sheetIndex)
{
_wb.setFirstVisibleTab(sheetIndex);
}
/**
* Sets the order of appearance for a given sheet.
*
* @param sheetname the name of the sheet to reorder
* @param pos the position that we want to insert the sheet into (0 based)
*/
public void setSheetOrder(String sheetname, int pos)
{
_wb.setSheetOrder(sheetname,pos);
}
/**
* Sets the tab whose data is actually seen when the sheet is opened.
* This may be different from the "selected sheet" since excel seems to
* allow you to show the data of one sheet when another is seen "selected"
* in the tabs (at the bottom).
*
* @see Sheet#setSelected(boolean)
* @param index the index of the sheet to select (0 based)
*/
public void setSelectedTab(int index)
{
_wb.setSelectedTab(index);
}
/**
* Set the sheet name.
*
* @param sheet number (0 based)
* @throws IllegalArgumentException if the name is greater than 31 chars or contains <code>/\?*[]</code>
*/
public void setSheetName(int sheet, String name)
{
_wb.setSheetName(sheet,name);
}
/**
* Set the sheet name
*
* @param sheet sheet number (0 based)
* @return Sheet name
*/
public String getSheetName(int sheet)
{
return _wb.getSheetName(sheet);
}
/**
* Returns the index of the sheet by his name
*
* @param name the sheet name
* @return index of the sheet (0 based)
*/
public int getSheetIndex(String name)
{
return _wb.getSheetIndex(name);
}
/**
* Returns the index of the given sheet
*
* @param sheet the sheet to look up
* @return index of the sheet (0 based)
*/
public int getSheetIndex(Sheet sheet)
{
assert sheet instanceof SXSSFSheet;
return _wb.getSheetIndex(getXSSFSheet((SXSSFSheet)sheet));
}
/**
* Sreate an Sheet for this Workbook, adds it to the sheets and returns
* the high level representation. Use this to create new sheets.
*
* @return Sheet representing the new sheet.
*/
public Sheet createSheet()
{
return createAndRegisterSXSSFSheet(_wb.createSheet());
}
SXSSFSheet createAndRegisterSXSSFSheet(XSSFSheet xSheet)
{
SXSSFSheet sxSheet=null;
try
{
sxSheet=new SXSSFSheet(this,xSheet);
}
catch (IOException ioe)
{
throw new RuntimeException(ioe);
}
registerSheetMapping(sxSheet,xSheet);
return sxSheet;
}
/**
* Create an Sheet for this Workbook, adds it to the sheets and returns
* the high level representation. Use this to create new sheets.
*
* @param sheetname sheetname to set for the sheet.
* @return Sheet representing the new sheet.
* @throws IllegalArgumentException if the name is greater than 31 chars or contains <code>/\?*[]</code>
*/
public Sheet createSheet(String sheetname)
{
return createAndRegisterSXSSFSheet(_wb.createSheet(sheetname));
}
/**
* Create an Sheet from an existing sheet in the Workbook.
*
* @return Sheet representing the cloned sheet.
*/
public Sheet cloneSheet(int sheetNum)
{
return createAndRegisterSXSSFSheet(_wb.cloneSheet(sheetNum));
}
/**
* Get the number of spreadsheets in the workbook
*
* @return the number of sheets
*/
public int getNumberOfSheets()
{
return _wb.getNumberOfSheets();
}
/**
* Get the Sheet object at the given index.
*
* @param index of the sheet number (0-based physical & logical)
* @return Sheet at the provided index
*/
public Sheet getSheetAt(int index)
{
return getSXSSFSheet(_wb.getSheetAt(index));
}
/**
* Get sheet with the given name
*
* @param name of the sheet
* @return Sheet with the name provided or <code>null</code> if it does not exist
*/
public Sheet getSheet(String name)
{
return getSXSSFSheet(_wb.getSheet(name));
}
/**
* Removes sheet at the given index
*
* @param index of the sheet to remove (0-based)
*/
public void removeSheetAt(int index)
{
XSSFSheet xSheet=_wb.getSheetAt(index);
_wb.removeSheetAt(index);
deregisterSheetMapping(xSheet);
}
/**
* Sets the repeating rows and columns for a sheet (as found in
* File->PageSetup->Sheet). This is function is included in the workbook
* because it creates/modifies name records which are stored at the
* workbook level.
* <p>
* To set just repeating columns:
* <pre>
* workbook.setRepeatingRowsAndColumns(0,0,1,-1-1);
* </pre>
* To set just repeating rows:
* <pre>
* workbook.setRepeatingRowsAndColumns(0,-1,-1,0,4);
* </pre>
* To remove all repeating rows and columns for a sheet.
* <pre>
* workbook.setRepeatingRowsAndColumns(0,-1,-1,-1,-1);
* </pre>
*
* @param sheetIndex 0 based index to sheet.
* @param startColumn 0 based start of repeating columns.
* @param endColumn 0 based end of repeating columns.
* @param startRow 0 based start of repeating rows.
* @param endRow 0 based end of repeating rows.
*/
public void setRepeatingRowsAndColumns(int sheetIndex, int startColumn, int endColumn, int startRow, int endRow)
{
_wb.setRepeatingRowsAndColumns(sheetIndex,startColumn,endColumn,startRow,endRow);
}
/**
* Create a new Font and add it to the workbook's font table
*
* @return new font object
*/
public Font createFont()
{
return _wb.createFont();
}
/**
* Finds a font that matches the one with the supplied attributes
*
* @return the font with the matched attributes or <code>null</code>
*/
public Font findFont(short boldWeight, short color, short fontHeight, String name, boolean italic, boolean strikeout, short typeOffset, byte underline)
{
return _wb.findFont(boldWeight, color, fontHeight, name, italic, strikeout, typeOffset, underline);
}
/**
* Get the number of fonts in the font table
*
* @return number of fonts
*/
public short getNumberOfFonts()
{
return _wb.getNumberOfFonts();
}
/**
* Get the font at the given index number
*
* @param idx index number (0-based)
* @return font at the index
*/
public Font getFontAt(short idx)
{
return _wb.getFontAt(idx);
}
/**
* Create a new Cell style and add it to the workbook's style table
*
* @return the new Cell Style object
*/
public CellStyle createCellStyle()
{
return _wb.createCellStyle();
}
/**
* Get the number of styles the workbook contains
*
* @return count of cell styles
*/
public short getNumCellStyles()
{
return _wb.getNumCellStyles();
}
/**
* Get the cell style object at the given index
*
* @param idx index within the set of styles (0-based)
* @return CellStyle object at the index
*/
public CellStyle getCellStyleAt(short idx)
{
return _wb.getCellStyleAt(idx);
}
/**
* Write out this workbook to an Outputstream.
*
* @param stream - the java OutputStream you wish to write to
* @exception IOException if anything can't be written.
*/
public void write(OutputStream stream) throws IOException
{
//Save the template
File tmplFile = File.createTempFile("template", ".xlsx");
FileOutputStream os = new FileOutputStream(tmplFile);
_wb.write(os);
os.close();
//Substitute the template entries with the generated sheet data files
injectData(tmplFile, stream);
tmplFile.delete();
}
/**
* @return the total number of defined names in this workbook
*/
public int getNumberOfNames()
{
return _wb.getNumberOfNames();
}
/**
* @param name the name of the defined name
* @return the defined name with the specified name. <code>null</code> if not found.
*/
public Name getName(String name)
{
return _wb.getName(name);
}
/**
* @param nameIndex position of the named range (0-based)
* @return the defined name at the specified index
* @throws IllegalArgumentException if the supplied index is invalid
*/
public Name getNameAt(int nameIndex)
{
return _wb.getNameAt(nameIndex);
}
/**
* Creates a new (uninitialised) defined name in this workbook
*
* @return new defined name object
*/
public Name createName()
{
return _wb.createName();
}
/**
* Gets the defined name index by name<br/>
* <i>Note:</i> Excel defined names are case-insensitive and
* this method performs a case-insensitive search.
*
* @param name the name of the defined name
* @return zero based index of the defined name. <tt>-1</tt> if not found.
*/
public int getNameIndex(String name)
{
return _wb.getNameIndex(name);
}
/**
* Remove the defined name at the specified index
*
* @param index named range index (0 based)
*/
public void removeName(int index)
{
_wb.removeName(index);
}
/**
* Remove a defined name by name
*
* @param name the name of the defined name
*/
public void removeName(String name)
{
_wb.removeName(name);
}
/**
* Sets the printarea for the sheet provided
* <p>
* i.e. Reference = $A$1:$B$2
* @param sheetIndex Zero-based sheet index (0 Represents the first sheet to keep consistent with java)
* @param reference Valid name Reference for the Print Area
*/
public void setPrintArea(int sheetIndex, String reference)
{
_wb.setPrintArea(sheetIndex,reference);
}
/**
* For the Convenience of Java Programmers maintaining pointers.
* @see #setPrintArea(int, String)
* @param sheetIndex Zero-based sheet index (0 = First Sheet)
* @param startColumn Column to begin printarea
* @param endColumn Column to end the printarea
* @param startRow Row to begin the printarea
* @param endRow Row to end the printarea
*/
public void setPrintArea(int sheetIndex, int startColumn, int endColumn, int startRow, int endRow)
{
_wb.setPrintArea(sheetIndex, startColumn, endColumn, startRow, endRow);
}
/**
* Retrieves the reference for the printarea of the specified sheet,
* the sheet name is appended to the reference even if it was not specified.
*
* @param sheetIndex Zero-based sheet index (0 Represents the first sheet to keep consistent with java)
* @return String Null if no print area has been defined
*/
public String getPrintArea(int sheetIndex)
{
return _wb.getPrintArea(sheetIndex);
}
/**
* Delete the printarea for the sheet specified
*
* @param sheetIndex Zero-based sheet index (0 = First Sheet)
*/
public void removePrintArea(int sheetIndex)
{
_wb.removePrintArea(sheetIndex);
}
/**
* Retrieves the current policy on what to do when
* getting missing or blank cells from a row.
* <p>
* The default is to return blank and null cells.
* {@link MissingCellPolicy}
* </p>
*/
public MissingCellPolicy getMissingCellPolicy()
{
return _wb.getMissingCellPolicy();
}
/**
* Sets the policy on what to do when
* getting missing or blank cells from a row.
*
* This will then apply to all calls to
* {@link org.apache.poi.ss.usermodel.Row#getCell(int)}. See
* {@link MissingCellPolicy}
*/
public void setMissingCellPolicy(MissingCellPolicy missingCellPolicy)
{
_wb.setMissingCellPolicy(missingCellPolicy);
}
/**
* Returns the instance of DataFormat for this workbook.
*
* @return the DataFormat object
*/
public DataFormat createDataFormat()
{
return _wb.createDataFormat();
}
/**
* Adds a picture to the workbook.
*
* @param pictureData The bytes of the picture
* @param format The format of the picture.
*
* @return the index to this picture (1 based).
* @see #PICTURE_TYPE_EMF
* @see #PICTURE_TYPE_WMF
* @see #PICTURE_TYPE_PICT
* @see #PICTURE_TYPE_JPEG
* @see #PICTURE_TYPE_PNG
* @see #PICTURE_TYPE_DIB
*/
public int addPicture(byte[] pictureData, int format)
{
return _wb.addPicture(pictureData,format);
}
/**
* Gets all pictures from the Workbook.
*
* @return the list of pictures (a list of {@link PictureData} objects.)
*/
public List<? extends PictureData> getAllPictures()
{
return _wb.getAllPictures();
}
/**
* Returns an object that handles instantiating concrete
* classes of the various instances one needs for HSSF and XSSF.
*/
public CreationHelper getCreationHelper()
{
return _wb.getCreationHelper();
}
/**
* @return <code>false</code> if this workbook is not visible in the GUI
*/
public boolean isHidden()
{
return _wb.isHidden();
}
/**
* @param hiddenFlag pass <code>false</code> to make the workbook visible in the GUI
*/
public void setHidden(boolean hiddenFlag)
{
_wb.setHidden(hiddenFlag);
}
/**
* Check whether a sheet is hidden.
* <p>
* Note that a sheet could instead be set to be very hidden, which is different
* ({@link #isSheetVeryHidden(int)})
* </p>
* @param sheetIx Number
* @return <code>true</code> if sheet is hidden
*/
public boolean isSheetHidden(int sheetIx)
{
return _wb.isSheetHidden(sheetIx);
}
/**
* Check whether a sheet is very hidden.
* <p>
* This is different from the normal hidden status
* ({@link #isSheetHidden(int)})
* </p>
* @param sheetIx sheet index to check
* @return <code>true</code> if sheet is very hidden
*/
public boolean isSheetVeryHidden(int sheetIx)
{
return _wb.isSheetVeryHidden(sheetIx);
}
/**
* Hide or unhide a sheet
*
* @param sheetIx the sheet index (0-based)
* @param hidden True to mark the sheet as hidden, false otherwise
*/
public void setSheetHidden(int sheetIx, boolean hidden)
{
_wb.setSheetHidden(sheetIx,hidden);
}
/**
* Hide or unhide a sheet.
*
* <ul>
* <li>0 - visible. </li>
* <li>1 - hidden. </li>
* <li>2 - very hidden.</li>
* </ul>
* @param sheetIx the sheet index (0-based)
* @param hidden one of the following <code>Workbook</code> constants:
* <code>Workbook.SHEET_STATE_VISIBLE</code>,
* <code>Workbook.SHEET_STATE_HIDDEN</code>, or
* <code>Workbook.SHEET_STATE_VERY_HIDDEN</code>.
* @throws IllegalArgumentException if the supplied sheet index or state is invalid
*/
public void setSheetHidden(int sheetIx, int hidden)
{
_wb.setSheetHidden(sheetIx,hidden);
}
/**
* Register a new toolpack in this workbook.
*
* @param toopack the toolpack to register
*/
public void addToolPack(UDFFinder toopack)
{
_wb.addToolPack(toopack);
}
//end of interface implementation
}