2002-01-30 21:22:28 -05:00
/ * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2006-12-22 14:18:16 -05:00
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
2004-04-09 09:05:39 -04:00
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 .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = * /
2004-08-23 04:52:54 -04:00
2002-01-30 21:22:28 -05:00
/ *
* HSSFWorkbook . java
*
* Created on September 30 , 2001 , 3 : 37 PM
* /
package org.apache.poi.hssf.usermodel ;
2007-09-19 10:34:31 -04:00
import org.apache.poi.POIDocument ;
2005-05-01 07:26:18 -04:00
import org.apache.poi.ddf.EscherBSERecord ;
import org.apache.poi.ddf.EscherBitmapBlip ;
import org.apache.poi.ddf.EscherRecord ;
2007-04-16 06:48:20 -04:00
import org.apache.poi.ddf.EscherBlipRecord ;
2002-11-23 14:03:00 -05:00
import org.apache.poi.hssf.eventmodel.EventRecordFactory ;
2002-03-10 07:00:33 -05:00
import org.apache.poi.hssf.model.Sheet ;
import org.apache.poi.hssf.model.Workbook ;
2003-07-18 22:48:17 -04:00
import org.apache.poi.hssf.record.* ;
2003-02-06 05:29:45 -05:00
import org.apache.poi.hssf.record.formula.Area3DPtg ;
2003-03-07 16:52:37 -05:00
import org.apache.poi.hssf.record.formula.MemFuncPtg ;
2003-02-06 05:29:45 -05:00
import org.apache.poi.hssf.record.formula.UnionPtg ;
2003-03-07 16:52:37 -05:00
import org.apache.poi.hssf.util.CellReference ;
2004-08-24 08:54:01 -04:00
import org.apache.poi.poifs.filesystem.* ;
2004-08-23 04:52:54 -04:00
import org.apache.poi.util.POILogFactory ;
2002-03-10 07:00:33 -05:00
import org.apache.poi.util.POILogger ;
2004-08-24 08:54:01 -04:00
import java.io.ByteArrayInputStream ;
2006-11-30 11:15:55 -05:00
import java.io.FileNotFoundException ;
2004-08-24 08:54:01 -04:00
import java.io.IOException ;
import java.io.InputStream ;
import java.io.OutputStream ;
2005-05-01 07:26:18 -04:00
import java.io.PrintWriter ;
2004-08-24 08:54:01 -04:00
import java.util.ArrayList ;
import java.util.Iterator ;
import java.util.List ;
import java.util.Stack ;
2002-01-30 21:22:28 -05:00
/ * *
* High level representation of a workbook . This is the first object most users
* will construct whether they are reading or writing a workbook . It is also the
* top level object for creating new sheets / etc .
*
* @see org . apache . poi . hssf . model . Workbook
* @see org . apache . poi . hssf . usermodel . HSSFSheet
* @author Andrew C . Oliver ( acoliver at apache dot org )
2002-02-10 23:23:11 -05:00
* @author Glen Stampoultzis ( glens at apache . org )
2002-10-04 22:38:07 -04:00
* @author Shawn Laubach ( slaubach at apache dot org )
2002-01-30 21:22:28 -05:00
* @version 2 . 0 - pre
* /
2007-09-19 10:34:31 -04:00
public class HSSFWorkbook extends POIDocument
2002-01-30 21:22:28 -05:00
{
2002-03-10 07:00:33 -05:00
private static final int DEBUG = POILogger . DEBUG ;
2002-01-30 21:22:28 -05:00
/ * *
* used for compile - time performance / memory optimization . This determines the
* initial capacity for the sheet collection . Its currently set to 3 .
* Changing it in this release will decrease performance
* since you ' re never allowed to have more or less than three sheets !
* /
2002-03-10 07:00:33 -05:00
public final static int INITIAL_CAPACITY = 3 ;
2002-01-30 21:22:28 -05:00
/ * *
* this is the reference to the low level Workbook object
* /
2002-03-10 07:00:33 -05:00
private Workbook workbook ;
2002-01-30 21:22:28 -05:00
/ * *
* this holds the HSSFSheet objects attached to this workbook
* /
2004-08-24 08:54:01 -04:00
protected ArrayList sheets ;
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
/ * *
* this holds the HSSFName objects attached to this workbook
* /
private ArrayList names ;
2004-08-23 04:52:54 -04:00
2002-09-16 14:14:31 -04:00
/ * *
* holds whether or not to preserve other nodes in the POIFS . Used
2004-08-23 04:52:54 -04:00
* for macros and embedded objects .
2002-09-16 14:14:31 -04:00
* /
private boolean preserveNodes ;
2003-07-25 09:39:08 -04:00
/ * *
* Used to keep track of the data formatter so that all
* createDataFormatter calls return the same one for a given
* book . This ensures that updates from one places is visible
* someplace else .
* /
private HSSFDataFormat formatter ;
2004-08-23 04:52:54 -04:00
2005-05-01 07:26:18 -04:00
/** Extended windows meta file */
2007-04-16 06:48:20 -04:00
public static final int PICTURE_TYPE_EMF = 2 ;
2005-05-01 07:26:18 -04:00
/** Windows Meta File */
2007-04-16 06:48:20 -04:00
public static final int PICTURE_TYPE_WMF = 3 ;
2005-05-01 07:26:18 -04:00
/** Mac PICT format */
2007-04-16 06:48:20 -04:00
public static final int PICTURE_TYPE_PICT = 4 ;
2005-05-01 07:26:18 -04:00
/** JPEG format */
public static final int PICTURE_TYPE_JPEG = 5 ;
/** PNG format */
public static final int PICTURE_TYPE_PNG = 6 ;
/** Device independant bitmap */
public static final int PICTURE_TYPE_DIB = 7 ;
2002-03-14 06:05:10 -05:00
private static POILogger log = POILogFactory . getLogger ( HSSFWorkbook . class ) ;
2002-01-30 21:22:28 -05:00
2005-05-01 07:26:18 -04:00
2002-01-30 21:22:28 -05:00
/ * *
* Creates new HSSFWorkbook from scratch ( start here ! )
*
* /
public HSSFWorkbook ( )
{
2004-08-24 08:54:01 -04:00
this ( Workbook . createWorkbook ( ) ) ;
}
protected HSSFWorkbook ( Workbook book )
{
workbook = book ;
sheets = new ArrayList ( INITIAL_CAPACITY ) ;
names = new ArrayList ( INITIAL_CAPACITY ) ;
2002-01-30 21:22:28 -05:00
}
2002-09-16 14:14:31 -04:00
public HSSFWorkbook ( POIFSFileSystem fs ) throws IOException {
this ( fs , true ) ;
}
2002-01-30 21:22:28 -05:00
/ * *
* given a POI POIFSFileSystem object , read in its Workbook and populate the high and
* low level models . If you ' re reading in a workbook . . . start here .
*
* @param fs the POI filesystem that contains the Workbook stream .
2004-08-23 04:52:54 -04:00
* @param preserveNodes whether to preseve other nodes , such as
2002-09-16 14:14:31 -04:00
* macros . This takes more memory , so only say yes if you
2007-09-19 10:34:31 -04:00
* need to . If set , will store all of the POIFSFileSystem
* in memory
2002-01-30 21:22:28 -05:00
* @see org . apache . poi . poifs . filesystem . POIFSFileSystem
* @exception IOException if the stream cannot be read
* /
2002-09-16 14:14:31 -04:00
public HSSFWorkbook ( POIFSFileSystem fs , boolean preserveNodes )
2002-03-10 07:00:33 -05:00
throws IOException
2002-01-30 21:22:28 -05:00
{
2002-09-16 14:14:31 -04:00
this . preserveNodes = preserveNodes ;
2007-09-19 10:34:31 -04:00
this . filesystem = fs ;
// If we're not preserving nodes, don't track the
// POIFS any more
if ( ! preserveNodes ) {
this . filesystem = null ;
2002-09-16 14:14:31 -04:00
}
2002-01-30 21:22:28 -05:00
sheets = new ArrayList ( INITIAL_CAPACITY ) ;
2002-04-23 18:24:41 -04:00
names = new ArrayList ( INITIAL_CAPACITY ) ;
2006-11-30 11:15:55 -05:00
// Normally, the Workbook will be in a POIFS Stream
// called "Workbook". However, some wierd XLS generators
// put theirs in one called "WORKBOOK"
String workbookName = " Workbook " ;
try {
fs . getRoot ( ) . getEntry ( workbookName ) ;
// Is the default name
} catch ( FileNotFoundException fe ) {
// Try the upper case form
try {
workbookName = " WORKBOOK " ;
fs . getRoot ( ) . getEntry ( workbookName ) ;
} catch ( FileNotFoundException wfe ) {
// Doesn't contain it in either form
throw new IllegalArgumentException ( " The supplied POIFSFileSystem contained neither a 'Workbook' entry, nor a 'WORKBOOK' entry. Is it really an excel file? " ) ;
}
}
2004-08-23 04:52:54 -04:00
2006-11-30 11:15:55 -05:00
// Grab the data from the workbook stream, however
// it happens to be spelt.
InputStream stream = fs . createDocumentInputStream ( workbookName ) ;
2004-08-23 04:52:54 -04:00
EventRecordFactory factory = new EventRecordFactory ( ) ;
2002-03-10 07:00:33 -05:00
List records = RecordFactory . createRecords ( stream ) ;
2002-01-30 21:22:28 -05:00
workbook = Workbook . createWorkbook ( records ) ;
setPropertiesFromWorkbook ( workbook ) ;
2002-08-21 07:56:49 -04:00
int recOffset = workbook . getNumRecords ( ) ;
2002-04-12 04:26:29 -04:00
int sheetNum = 0 ;
2007-09-08 12:34:10 -04:00
2005-08-25 23:40:34 -04:00
// convert all LabelRecord records to LabelSSTRecord
convertLabelRecords ( records , recOffset ) ;
2002-08-21 07:56:49 -04:00
while ( recOffset < records . size ( ) )
2002-01-30 21:22:28 -05:00
{
2002-08-21 07:56:49 -04:00
Sheet sheet = Sheet . createSheet ( records , sheetNum + + , recOffset ) ;
2002-01-30 21:22:28 -05:00
2002-08-21 07:56:49 -04:00
recOffset = sheet . getEofLoc ( ) + 1 ;
2007-04-16 06:48:20 -04:00
if ( recOffset = = 1 )
{
break ;
}
2007-09-24 08:57:38 -04:00
HSSFSheet hsheet = new HSSFSheet ( this , sheet ) ;
2002-01-30 21:22:28 -05:00
sheets . add ( hsheet ) ;
// workbook.setSheetName(sheets.size() -1, "Sheet"+sheets.size());
}
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
for ( int i = 0 ; i < workbook . getNumNames ( ) ; + + i ) {
HSSFName name = new HSSFName ( workbook , workbook . getNameRecord ( i ) ) ;
names . add ( name ) ;
}
2002-01-30 21:22:28 -05:00
}
2002-09-16 14:14:31 -04:00
public HSSFWorkbook ( InputStream s ) throws IOException {
this ( s , true ) ;
}
2002-01-30 21:22:28 -05:00
/ * *
* Companion to HSSFWorkbook ( POIFSFileSystem ) , this constructs the POI filesystem around your
* inputstream .
*
2002-03-10 07:00:33 -05:00
* @param s the POI filesystem that contains the Workbook stream .
2004-08-23 04:52:54 -04:00
* @param preserveNodes whether to preseve other nodes , such as
2002-09-16 14:14:31 -04:00
* macros . This takes more memory , so only say yes if you
* need to .
2002-01-30 21:22:28 -05:00
* @see org . apache . poi . poifs . filesystem . POIFSFileSystem
* @see # HSSFWorkbook ( POIFSFileSystem )
* @exception IOException if the stream cannot be read
* /
2002-09-16 14:14:31 -04:00
public HSSFWorkbook ( InputStream s , boolean preserveNodes )
2002-03-10 07:00:33 -05:00
throws IOException
2002-01-30 21:22:28 -05:00
{
2002-09-16 14:14:31 -04:00
this ( new POIFSFileSystem ( s ) , preserveNodes ) ;
2002-01-30 21:22:28 -05:00
}
/ * *
* used internally to set the workbook properties .
* /
private void setPropertiesFromWorkbook ( Workbook book )
{
this . workbook = book ;
// none currently
}
2005-08-25 23:40:34 -04:00
/ * *
* This is basically a kludge to deal with the now obsolete Label records . If
* you have to read in a sheet that contains Label records , be aware that the rest
* of the API doesn ' t deal with them , the low level structure only provides read - only
* semi - immutable structures ( the sets are there for interface conformance with NO
* impelmentation ) . In short , you need to call this function passing it a reference
* to the Workbook object . All labels will be converted to LabelSST records and their
* contained strings will be written to the Shared String tabel ( SSTRecord ) within
* the Workbook .
*
* @param wb sheet ' s matching low level Workbook structure containing the SSTRecord .
* @see org . apache . poi . hssf . record . LabelRecord
* @see org . apache . poi . hssf . record . LabelSSTRecord
* @see org . apache . poi . hssf . record . SSTRecord
* /
private void convertLabelRecords ( List records , int offset )
{
if ( log . check ( POILogger . DEBUG ) )
log . log ( POILogger . DEBUG , " convertLabelRecords called " ) ;
for ( int k = offset ; k < records . size ( ) ; k + + )
{
Record rec = ( Record ) records . get ( k ) ;
if ( rec . getSid ( ) = = LabelRecord . sid )
{
LabelRecord oldrec = ( LabelRecord ) rec ;
records . remove ( k ) ;
LabelSSTRecord newrec = new LabelSSTRecord ( ) ;
int stringid =
workbook . addSSTString ( new UnicodeString ( oldrec . getValue ( ) ) ) ;
newrec . setRow ( oldrec . getRow ( ) ) ;
newrec . setColumn ( oldrec . getColumn ( ) ) ;
newrec . setXFIndex ( oldrec . getXFIndex ( ) ) ;
newrec . setSSTIndex ( stringid ) ;
records . add ( k , newrec ) ;
}
}
if ( log . check ( POILogger . DEBUG ) )
log . log ( POILogger . DEBUG , " convertLabelRecords exit " ) ;
}
2004-08-23 04:52:54 -04:00
2003-03-18 14:26:12 -05:00
/ * *
* 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 )
* /
2004-08-23 04:52:54 -04:00
2003-03-18 14:26:12 -05:00
public void setSheetOrder ( String sheetname , int pos ) {
2007-06-04 09:52:57 -04:00
sheets . add ( pos , sheets . remove ( getSheetIndex ( sheetname ) ) ) ;
2003-03-18 14:26:12 -05:00
workbook . setSheetOrder ( sheetname , pos ) ;
}
2005-08-24 12:26:20 -04:00
/ * *
* 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 org . apache . poi . hssf . usermodel . HSSFSheet # setSelected ( boolean )
* @param index
* /
public void setSelectedTab ( short index ) {
workbook . getWindowOne ( ) . setSelectedTab ( index ) ;
}
/ * *
* gets 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 org . apache . poi . hssf . usermodel . HSSFSheet # setSelected ( boolean )
* /
public short getSelectedTab ( ) {
return workbook . getWindowOne ( ) . getSelectedTab ( ) ;
}
/ * *
* sets the first tab that is displayed in the list of tabs
* in excel .
* @param index
* /
public void setDisplayedTab ( short index ) {
workbook . getWindowOne ( ) . setDisplayedTab ( index ) ;
}
/ * *
* sets the first tab that is displayed in the list of tabs
* in excel .
* /
public short getDisplayedTab ( ) {
return workbook . getWindowOne ( ) . getDisplayedTab ( ) ;
}
2004-08-23 04:52:54 -04:00
2006-01-03 06:41:36 -05:00
/ * *
* @deprecated POI will now properly handle unicode strings without
* forceing an encoding
* /
2002-09-01 22:11:16 -04:00
public final static byte ENCODING_COMPRESSED_UNICODE = 0 ;
2006-01-03 06:41:36 -05:00
/ * *
* @deprecated POI will now properly handle unicode strings without
* forceing an encoding
* /
2002-09-01 22:11:16 -04:00
public final static byte ENCODING_UTF_16 = 1 ;
2004-08-23 04:52:54 -04:00
2002-01-30 21:22:28 -05:00
/ * *
2003-10-26 21:01:21 -05:00
* set the sheet name .
* Will throw IllegalArgumentException if the name is greater than 31 chars
* or contains / \ ? * [ ]
2004-08-23 04:52:54 -04:00
* @param sheet number ( 0 based )
2002-01-30 21:22:28 -05:00
* /
public void setSheetName ( int sheet , String name )
2002-09-01 22:11:16 -04:00
{
2004-09-18 22:06:54 -04:00
if ( workbook . doesContainsSheetName ( name , sheet ) )
throw new IllegalArgumentException ( " The workbook already contains a sheet with this name " ) ;
2006-01-03 06:41:36 -05:00
if ( sheet > ( sheets . size ( ) - 1 ) )
{
throw new RuntimeException ( " Sheet out of bounds " ) ;
}
workbook . setSheetName ( sheet , name ) ;
2002-09-01 22:11:16 -04:00
}
2006-01-03 06:41:36 -05:00
/ * *
* set the sheet name forcing the encoding . Forcing the encoding IS A BAD IDEA ! ! !
* @deprecated 3 - Jan - 2006 POI now automatically detects unicode and sets the encoding
* appropriately . Simply use setSheetName ( int sheet , String encoding )
* @throws IllegalArgumentException if the name is greater than 31 chars
* or contains / \ ? * [ ]
* @param sheet number ( 0 based )
* /
2002-09-01 22:11:16 -04:00
public void setSheetName ( int sheet , String name , short encoding )
2002-01-30 21:22:28 -05:00
{
2004-09-18 22:06:54 -04:00
if ( workbook . doesContainsSheetName ( name , sheet ) )
throw new IllegalArgumentException ( " The workbook already contains a sheet with this name " ) ;
2002-01-30 21:22:28 -05:00
if ( sheet > ( sheets . size ( ) - 1 ) )
{
throw new RuntimeException ( " Sheet out of bounds " ) ;
}
2004-08-23 04:52:54 -04:00
2002-09-01 22:11:16 -04:00
switch ( encoding ) {
case ENCODING_COMPRESSED_UNICODE :
case ENCODING_UTF_16 :
break ;
2004-08-23 04:52:54 -04:00
2002-09-01 22:11:16 -04:00
default :
// TODO java.io.UnsupportedEncodingException
throw new RuntimeException ( " Unsupported encoding " ) ;
}
2004-08-23 04:52:54 -04:00
2002-09-01 22:11:16 -04:00
workbook . setSheetName ( sheet , name , encoding ) ;
2002-01-30 21:22:28 -05:00
}
2002-07-28 18:54:43 -04:00
2002-01-30 21:22:28 -05:00
/ * *
* get the sheet name
* @param sheet Number
* @return Sheet name
* /
public String getSheetName ( int sheet )
{
if ( sheet > ( sheets . size ( ) - 1 ) )
{
throw new RuntimeException ( " Sheet out of bounds " ) ;
}
return workbook . getSheetName ( sheet ) ;
}
2008-01-08 06:59:26 -05:00
/ * *
* check whether a sheet is hidden
* @param sheet Number
* @return True if sheet is hidden
* /
public boolean isSheetHidden ( int sheet ) {
if ( sheet > ( sheets . size ( ) - 1 ) )
{
throw new RuntimeException ( " Sheet out of bounds " ) ;
}
return workbook . isSheetHidden ( sheet ) ;
}
/ * *
* Hide or unhide a sheet
*
* @param sheetnum The sheet number
* @param hidden True to mark the sheet as hidden , false otherwise
* /
public void setSheetHidden ( int sheet , boolean hidden ) {
if ( sheet > ( sheets . size ( ) - 1 ) )
{
throw new RuntimeException ( " Sheet out of bounds " ) ;
}
workbook . setSheetHidden ( sheet , hidden ) ;
}
2002-04-23 18:24:41 -04:00
/ *
2002-01-30 21:22:28 -05:00
* get the sheet ' s index
2002-03-10 07:00:33 -05:00
* @param name sheet name
2002-01-30 21:22:28 -05:00
* @return sheet index or - 1 if it was not found .
* /
2002-04-23 18:24:41 -04:00
/ * * Returns the index of the sheet by his name
* @param name the sheet name
* @return index of the sheet ( 0 based )
2004-08-23 04:52:54 -04:00
* /
2002-01-30 21:22:28 -05:00
public int getSheetIndex ( String name )
{
2002-04-23 18:24:41 -04:00
int retval = workbook . getSheetIndex ( name ) ;
2004-08-23 04:52:54 -04:00
2002-01-30 21:22:28 -05:00
return retval ;
}
2004-08-23 04:52:54 -04:00
2007-09-24 08:57:38 -04:00
/ * * Returns the index of the given sheet
* @param sheet the sheet to look up
* @return index of the sheet ( 0 based )
* /
public int getSheetIndex ( HSSFSheet sheet )
{
for ( int i = 0 ; i < sheets . size ( ) ; i + + ) {
if ( sheets . get ( i ) = = sheet ) {
return i ;
}
}
return - 1 ;
}
2002-01-30 21:22:28 -05:00
/ * *
* create an HSSFSheet for this HSSFWorkbook , adds it to the sheets and returns
* the high level representation . Use this to create new sheets .
*
* @return HSSFSheet representing the new sheet .
* /
public HSSFSheet createSheet ( )
{
2002-03-10 07:00:33 -05:00
// if (getNumberOfSheets() == 3)
2002-01-30 21:22:28 -05:00
// throw new RuntimeException("You cannot have more than three sheets in HSSF 1.0");
2007-09-24 08:57:38 -04:00
HSSFSheet sheet = new HSSFSheet ( this ) ;
2002-01-30 21:22:28 -05:00
sheets . add ( sheet ) ;
workbook . setSheetName ( sheets . size ( ) - 1 ,
2002-03-10 07:00:33 -05:00
" Sheet " + ( sheets . size ( ) - 1 ) ) ;
WindowTwoRecord windowTwo = ( WindowTwoRecord ) sheet . getSheet ( ) . findFirstRecordBySid ( WindowTwoRecord . sid ) ;
windowTwo . setSelected ( sheets . size ( ) = = 1 ) ;
windowTwo . setPaged ( sheets . size ( ) = = 1 ) ;
2002-01-30 21:22:28 -05:00
return sheet ;
}
2002-09-04 20:26:28 -04:00
/ * *
* create an HSSFSheet from an existing sheet in the HSSFWorkbook .
*
* @return HSSFSheet representing the cloned sheet .
* /
public HSSFSheet cloneSheet ( int sheetNum ) {
HSSFSheet srcSheet = ( HSSFSheet ) sheets . get ( sheetNum ) ;
String srcName = workbook . getSheetName ( sheetNum ) ;
if ( srcSheet ! = null ) {
2007-09-24 08:57:38 -04:00
HSSFSheet clonedSheet = srcSheet . cloneSheet ( this ) ;
2002-09-04 20:26:28 -04:00
WindowTwoRecord windowTwo = ( WindowTwoRecord ) clonedSheet . getSheet ( ) . findFirstRecordBySid ( WindowTwoRecord . sid ) ;
windowTwo . setSelected ( sheets . size ( ) = = 1 ) ;
windowTwo . setPaged ( sheets . size ( ) = = 1 ) ;
sheets . add ( clonedSheet ) ;
2006-01-05 02:29:36 -05:00
int i = 1 ;
while ( true ) {
//Try and find the next sheet name that is unique
String name = srcName ;
String index = Integer . toString ( i + + ) ;
if ( name . length ( ) + index . length ( ) + 2 < 31 )
name = name + " ( " + index + " ) " ;
else name = name . substring ( 0 , 31 - index . length ( ) - 2 ) + " ( " + index + " ) " ;
//If the sheet name is unique, then set it otherwise move on to the next number.
if ( workbook . getSheetIndex ( name ) = = - 1 ) {
workbook . setSheetName ( sheets . size ( ) - 1 , name ) ;
break ;
}
2003-10-26 21:01:21 -05:00
}
2002-09-04 20:26:28 -04:00
return clonedSheet ;
}
return null ;
}
2002-01-30 21:22:28 -05:00
/ * *
* create an HSSFSheet for this HSSFWorkbook , adds it to the sheets and returns
* the high level representation . Use this to create new sheets .
*
2002-03-10 07:00:33 -05:00
* @param sheetname sheetname to set for the sheet .
2002-01-30 21:22:28 -05:00
* @return HSSFSheet representing the new sheet .
* /
public HSSFSheet createSheet ( String sheetname )
{
2005-04-21 03:43:22 -04:00
if ( workbook . doesContainsSheetName ( sheetname , sheets . size ( ) ) )
2004-09-18 22:06:54 -04:00
throw new IllegalArgumentException ( " The workbook already contains a sheet of this name " ) ;
2002-01-30 21:22:28 -05:00
2007-09-24 08:57:38 -04:00
HSSFSheet sheet = new HSSFSheet ( this ) ;
2002-01-30 21:22:28 -05:00
sheets . add ( sheet ) ;
workbook . setSheetName ( sheets . size ( ) - 1 , sheetname ) ;
2002-03-10 07:00:33 -05:00
WindowTwoRecord windowTwo = ( WindowTwoRecord ) sheet . getSheet ( ) . findFirstRecordBySid ( WindowTwoRecord . sid ) ;
windowTwo . setSelected ( sheets . size ( ) = = 1 ) ;
windowTwo . setPaged ( sheets . size ( ) = = 1 ) ;
2002-01-30 21:22:28 -05:00
return sheet ;
}
/ * *
* get the number of spreadsheets in the workbook ( this will be three after serialization )
* @return number of sheets
* /
public int getNumberOfSheets ( )
{
return sheets . size ( ) ;
}
/ * *
* Get the HSSFSheet object at the given index .
* @param index of the sheet number ( 0 - based physical & logical )
* @return HSSFSheet at the provided index
* /
public HSSFSheet getSheetAt ( int index )
{
2002-03-10 07:00:33 -05:00
return ( HSSFSheet ) sheets . get ( index ) ;
2002-01-30 21:22:28 -05:00
}
/ * *
* Get sheet with the given name
* @param name of the sheet
* @return HSSFSheet with the name provided or null if it does not exist
* /
public HSSFSheet getSheet ( String name )
{
HSSFSheet retval = null ;
for ( int k = 0 ; k < sheets . size ( ) ; k + + )
{
String sheetname = workbook . getSheetName ( k ) ;
if ( sheetname . equals ( name ) )
{
2002-03-10 07:00:33 -05:00
retval = ( HSSFSheet ) sheets . get ( k ) ;
2002-01-30 21:22:28 -05:00
}
}
return retval ;
}
/ * *
* removes sheet at the given index
* @param index of the sheet ( 0 - based )
* /
public void removeSheetAt ( int index )
{
sheets . remove ( index ) ;
workbook . removeSheet ( index ) ;
}
/ * *
* determine whether the Excel GUI will backup the workbook when saving .
*
* @param backupValue true to indicate a backup will be performed .
* /
public void setBackupFlag ( boolean backupValue )
{
BackupRecord backupRecord = workbook . getBackupRecord ( ) ;
2002-03-10 07:00:33 -05:00
backupRecord . setBackup ( backupValue ? ( short ) 1
: ( short ) 0 ) ;
2002-01-30 21:22:28 -05:00
}
/ * *
* determine whether the Excel GUI will backup the workbook when saving .
*
* @return the current setting for backups .
* /
public boolean getBackupFlag ( )
{
BackupRecord backupRecord = workbook . getBackupRecord ( ) ;
return ( backupRecord . getBackup ( ) = = 0 ) ? false
2002-03-10 07:00:33 -05:00
: true ;
2002-01-30 21:22:28 -05:00
}
2003-02-06 05:29:45 -05:00
/ * *
* 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 )
{
// 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 > = 0xFF ) throw new IllegalArgumentException ( " Invalid column range specification " ) ;
if ( endColumn < - 1 | | endColumn > = 0xFF ) throw new IllegalArgumentException ( " Invalid column range specification " ) ;
if ( startRow < - 1 | | startRow > 65535 ) throw new IllegalArgumentException ( " Invalid row range specification " ) ;
if ( endRow < - 1 | | endRow > 65535 ) 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 " ) ;
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 ;
boolean isNewRecord = false ;
NameRecord nameRecord ;
nameRecord = findExistingRowColHeaderNameRecord ( sheetIndex ) ;
if ( removingRange )
{
if ( nameRecord ! = null )
2004-08-23 04:52:54 -04:00
workbook . removeName ( findExistingRowColHeaderNameRecordIdx ( sheetIndex + 1 ) ) ;
2003-02-06 05:29:45 -05:00
return ;
}
if ( nameRecord = = null )
{
2004-08-23 04:52:54 -04:00
nameRecord = workbook . createBuiltInName ( NameRecord . BUILTIN_PRINT_TITLE , sheetIndex + 1 ) ;
2003-03-06 15:41:17 -05:00
//does a lot of the house keeping for builtin records, like setting lengths to zero etc
2003-02-06 05:29:45 -05:00
isNewRecord = true ;
}
2004-08-23 04:52:54 -04:00
2003-02-06 05:29:45 -05:00
short definitionTextLength = settingRowAndColumn ? ( short ) 0x001a : ( short ) 0x000b ;
nameRecord . setDefinitionTextLength ( definitionTextLength ) ;
2003-03-06 15:41:17 -05:00
2003-02-06 05:29:45 -05:00
Stack ptgs = new Stack ( ) ;
if ( settingRowAndColumn )
{
MemFuncPtg memFuncPtg = new MemFuncPtg ( ) ;
memFuncPtg . setLenRefSubexpression ( 23 ) ;
ptgs . add ( memFuncPtg ) ;
}
if ( startColumn > = 0 )
{
Area3DPtg area3DPtg1 = new Area3DPtg ( ) ;
area3DPtg1 . setExternSheetIndex ( externSheetIndex ) ;
area3DPtg1 . setFirstColumn ( ( short ) startColumn ) ;
area3DPtg1 . setLastColumn ( ( short ) endColumn ) ;
area3DPtg1 . setFirstRow ( ( short ) 0 ) ;
area3DPtg1 . setLastRow ( ( short ) 0xFFFF ) ;
ptgs . add ( area3DPtg1 ) ;
}
if ( startRow > = 0 )
{
Area3DPtg area3DPtg2 = new Area3DPtg ( ) ;
area3DPtg2 . setExternSheetIndex ( externSheetIndex ) ;
area3DPtg2 . setFirstColumn ( ( short ) 0 ) ;
area3DPtg2 . setLastColumn ( ( short ) 0x00FF ) ;
area3DPtg2 . setFirstRow ( ( short ) startRow ) ;
area3DPtg2 . setLastRow ( ( short ) endRow ) ;
ptgs . add ( area3DPtg2 ) ;
}
if ( settingRowAndColumn )
{
UnionPtg unionPtg = new UnionPtg ( ) ;
ptgs . add ( unionPtg ) ;
}
nameRecord . setNameDefinition ( ptgs ) ;
if ( isNewRecord )
{
HSSFName newName = new HSSFName ( workbook , nameRecord ) ;
names . add ( newName ) ;
}
HSSFPrintSetup printSetup = sheet . getPrintSetup ( ) ;
printSetup . setValidSettings ( false ) ;
WindowTwoRecord w2 = ( WindowTwoRecord ) sheet . getSheet ( ) . findFirstRecordBySid ( WindowTwoRecord . sid ) ;
w2 . setPaged ( true ) ;
}
private NameRecord findExistingRowColHeaderNameRecord ( int sheetIndex )
{
int index = findExistingRowColHeaderNameRecordIdx ( sheetIndex ) ;
if ( index = = - 1 )
return null ;
else
return ( NameRecord ) workbook . findNextRecordBySid ( NameRecord . sid , index ) ;
}
private int findExistingRowColHeaderNameRecordIdx ( int sheetIndex )
{
int index = 0 ;
NameRecord r = null ;
while ( ( r = ( NameRecord ) workbook . findNextRecordBySid ( NameRecord . sid , index ) ) ! = null )
{
2007-03-01 22:13:13 -05:00
int indexToSheet = r . getEqualsToIndexToSheet ( ) - 1 ;
if ( indexToSheet > - 1 ) { //ignore "GLOBAL" name records
int nameRecordSheetIndex = workbook . getSheetIndexFromExternSheetIndex ( indexToSheet ) ;
if ( isRowColHeaderRecord ( r ) & & nameRecordSheetIndex = = sheetIndex )
{
return index ;
}
}
2003-02-06 05:29:45 -05:00
index + + ;
}
return - 1 ;
}
private boolean isRowColHeaderRecord ( NameRecord r )
{
return r . getOptionFlag ( ) = = 0x20 & & ( " " + ( ( char ) 7 ) ) . equals ( r . getNameText ( ) ) ;
}
2002-01-30 21:22:28 -05:00
/ * *
* create a new Font and add it to the workbook ' s font table
* @return new font object
* /
public HSSFFont createFont ( )
{
2002-03-10 07:00:33 -05:00
FontRecord font = workbook . createNewFont ( ) ;
short fontindex = ( short ) ( getNumberOfFonts ( ) - 1 ) ;
2002-01-30 21:22:28 -05:00
if ( fontindex > 3 )
{
fontindex + + ; // THERE IS NO FOUR!!
}
2007-11-06 13:52:52 -05:00
if ( fontindex = = Short . MAX_VALUE ) {
throw new IllegalArgumentException ( " Maximum number of fonts was exceeded " ) ;
}
2002-01-30 21:22:28 -05:00
HSSFFont retval = new HSSFFont ( fontindex , font ) ;
return retval ;
}
2004-04-09 07:45:38 -04:00
/ * *
* Finds a font that matches the one with the supplied attributes
* /
public HSSFFont findFont ( short boldWeight , short color , short fontHeight ,
String name , boolean italic , boolean strikeout ,
short typeOffset , byte underline )
{
// System.out.println( boldWeight + ", " + color + ", " + fontHeight + ", " + name + ", " + italic + ", " + strikeout + ", " + typeOffset + ", " + underline );
for ( short i = 0 ; i < workbook . getNumberOfFontRecords ( ) ; i + + )
{
if ( i = = 4 )
continue ;
FontRecord font = workbook . getFontRecordAt ( i ) ;
HSSFFont hssfFont = new HSSFFont ( i , font ) ;
// System.out.println( hssfFont.getBoldweight() + ", " + hssfFont.getColor() + ", " + hssfFont.getFontHeight() + ", " + hssfFont.getFontName() + ", " + hssfFont.getItalic() + ", " + hssfFont.getStrikeout() + ", " + hssfFont.getTypeOffset() + ", " + hssfFont.getUnderline() );
if ( hssfFont . getBoldweight ( ) = = boldWeight
& & hssfFont . getColor ( ) = = color
& & hssfFont . getFontHeight ( ) = = fontHeight
& & hssfFont . getFontName ( ) . equals ( name )
& & hssfFont . getItalic ( ) = = italic
& & hssfFont . getStrikeout ( ) = = strikeout
& & hssfFont . getTypeOffset ( ) = = typeOffset
& & hssfFont . getUnderline ( ) = = underline )
{
// System.out.println( "Found font" );
return hssfFont ;
}
}
// System.out.println( "No font found" );
return null ;
}
2002-01-30 21:22:28 -05:00
/ * *
* get the number of fonts in the font table
* @return number of fonts
* /
public short getNumberOfFonts ( )
{
2002-03-10 07:00:33 -05:00
return ( short ) workbook . getNumberOfFontRecords ( ) ;
2002-01-30 21:22:28 -05:00
}
/ * *
* get the font at the given index number
2002-03-10 07:00:33 -05:00
* @param idx index number
2002-01-30 21:22:28 -05:00
* @return HSSFFont at the index
* /
public HSSFFont getFontAt ( short idx )
{
2002-03-10 07:00:33 -05:00
FontRecord font = workbook . getFontRecordAt ( idx ) ;
HSSFFont retval = new HSSFFont ( idx , font ) ;
2002-01-30 21:22:28 -05:00
return retval ;
}
/ * *
* create a new Cell style and add it to the workbook ' s style table
* @return the new Cell Style object
* /
public HSSFCellStyle createCellStyle ( )
{
2002-03-10 07:00:33 -05:00
ExtendedFormatRecord xfr = workbook . createCellXF ( ) ;
short index = ( short ) ( getNumCellStyles ( ) - 1 ) ;
HSSFCellStyle style = new HSSFCellStyle ( index , xfr ) ;
2002-01-30 21:22:28 -05:00
return style ;
}
/ * *
* get the number of styles the workbook contains
* @return count of cell styles
* /
public short getNumCellStyles ( )
{
2002-03-10 07:00:33 -05:00
return ( short ) workbook . getNumExFormats ( ) ;
2002-01-30 21:22:28 -05:00
}
/ * *
* get the cell style object at the given index
2002-03-10 07:00:33 -05:00
* @param idx index within the set of styles
2002-01-30 21:22:28 -05:00
* @return HSSFCellStyle object at the index
* /
public HSSFCellStyle getCellStyleAt ( short idx )
{
2002-03-10 07:00:33 -05:00
ExtendedFormatRecord xfr = workbook . getExFormatAt ( idx ) ;
HSSFCellStyle style = new HSSFCellStyle ( idx , xfr ) ;
2002-01-30 21:22:28 -05:00
return style ;
}
/ * *
* Method write - write out this workbook to an Outputstream . Constructs
* a new POI POIFSFileSystem , passes in the workbook binary representation and
* writes it out .
*
* @param stream - the java OutputStream you wish to write the XLS to
*
* @exception IOException if anything can ' t be written .
* @see org . apache . poi . poifs . filesystem . POIFSFileSystem
* /
public void write ( OutputStream stream )
2002-03-10 07:00:33 -05:00
throws IOException
2002-01-30 21:22:28 -05:00
{
2002-03-10 07:00:33 -05:00
byte [ ] bytes = getBytes ( ) ;
POIFSFileSystem fs = new POIFSFileSystem ( ) ;
2004-08-23 04:52:54 -04:00
2007-09-19 10:34:31 -04:00
// For tracking what we've written out, used if we're
// going to be preserving nodes
List excepts = new ArrayList ( 1 ) ;
// Write out the Workbook stream
2002-01-30 21:22:28 -05:00
fs . createDocument ( new ByteArrayInputStream ( bytes ) , " Workbook " ) ;
2007-09-19 10:34:31 -04:00
// Write out our HPFS properties, if we have them
writeProperties ( fs , excepts ) ;
2002-09-16 14:14:31 -04:00
2004-08-23 04:52:54 -04:00
if ( preserveNodes ) {
2007-08-23 13:40:24 -04:00
// Don't write out the old Workbook, we'll be doing our new one
2002-09-16 14:14:31 -04:00
excepts . add ( " Workbook " ) ;
2007-08-23 13:40:24 -04:00
// If the file had WORKBOOK instead of Workbook, we'll write it
// out correctly shortly, so don't include the old one
excepts . add ( " WORKBOOK " ) ;
// Copy over all the other nodes to our new poifs
2007-09-19 10:34:31 -04:00
copyNodes ( this . filesystem , fs , excepts ) ;
2002-09-16 14:14:31 -04:00
}
2002-01-30 21:22:28 -05:00
fs . writeFilesystem ( stream ) ;
2002-09-16 14:14:31 -04:00
//poifs.writeFilesystem(stream);
2002-01-30 21:22:28 -05:00
}
/ * *
* Method getBytes - get the bytes of just the HSSF portions of the XLS file .
* Use this to construct a POI POIFSFileSystem yourself .
*
*
* @return byte [ ] array containing the binary representation of this workbook and all contained
* sheets , rows , cells , etc .
*
* @see org . apache . poi . hssf . model . Workbook
* @see org . apache . poi . hssf . model . Sheet
* /
2002-03-10 07:00:33 -05:00
public byte [ ] getBytes ( )
2002-01-30 21:22:28 -05:00
{
2004-06-20 06:18:50 -04:00
if ( log . check ( POILogger . DEBUG ) )
log . log ( DEBUG , " HSSFWorkbook.getBytes() " ) ;
2004-08-23 04:52:54 -04:00
// before getting the workbook size we must tell the sheets that
// serialization is about to occur.
for ( int k = 0 ; k < sheets . size ( ) ; k + + )
( ( HSSFSheet ) sheets . get ( k ) ) . getSheet ( ) . preSerialize ( ) ;
2002-03-10 07:00:33 -05:00
int wbsize = workbook . getSize ( ) ;
2002-01-30 21:22:28 -05:00
// log.debug("REMOVEME: old sizing method "+workbook.serialize().length);
// ArrayList sheetbytes = new ArrayList(sheets.size());
int totalsize = wbsize ;
for ( int k = 0 ; k < sheets . size ( ) ; k + + )
{
workbook . setSheetBof ( k , totalsize ) ;
2002-03-10 07:00:33 -05:00
totalsize + = ( ( HSSFSheet ) sheets . get ( k ) ) . getSheet ( ) . getSize ( ) ;
2002-01-30 21:22:28 -05:00
}
2004-08-23 04:52:54 -04:00
2002-09-16 14:14:31 -04:00
/ * if ( totalsize < 4096 )
2002-01-30 21:22:28 -05:00
{
totalsize = 4096 ;
2002-09-16 14:14:31 -04:00
} * /
byte [ ] retval = new byte [ totalsize ] ;
int pos = workbook . serialize ( 0 , retval ) ;
2002-01-30 21:22:28 -05:00
// System.arraycopy(wb, 0, retval, 0, wb.length);
for ( int k = 0 ; k < sheets . size ( ) ; k + + )
{
// byte[] sb = (byte[])sheetbytes.get(k);
// System.arraycopy(sb, 0, retval, pos, sb.length);
2005-05-01 07:26:18 -04:00
int len = ( ( HSSFSheet ) sheets . get ( k ) ) . getSheet ( ) . serialize ( pos ,
retval ) ;
pos + = len ; // sb.length;
2002-01-30 21:22:28 -05:00
}
2002-09-16 14:14:31 -04:00
/ * for ( int k = pos ; k < totalsize ; k + + )
2002-01-30 21:22:28 -05:00
{
2002-09-16 14:14:31 -04:00
retval [ k ] = 0 ;
} * /
return retval ;
2002-01-30 21:22:28 -05:00
}
2005-08-18 03:06:44 -04:00
/ * * @deprecated Do not call this method from your applications . Use the methods
* available in the HSSFRow to add string HSSFCells
* /
2002-01-30 21:22:28 -05:00
public int addSSTString ( String string )
{
2005-08-18 03:06:44 -04:00
return workbook . addSSTString ( new UnicodeString ( string ) ) ;
2002-01-30 21:22:28 -05:00
}
2005-08-18 03:06:44 -04:00
/ * * @deprecated Do not call this method from your applications . Use the methods
* available in the HSSFRow to get string HSSFCells
* /
2002-01-30 21:22:28 -05:00
public String getSSTString ( int index )
{
2005-08-18 03:06:44 -04:00
return workbook . getSSTString ( index ) . getString ( ) ;
2002-01-30 21:22:28 -05:00
}
2007-10-15 06:34:40 -04:00
protected Workbook getWorkbook ( )
2002-01-30 21:22:28 -05:00
{
return workbook ;
}
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
/ * * gets the total number of named ranges in the workboko
* @return number of named ranges
2004-08-23 04:52:54 -04:00
* /
2002-04-23 18:24:41 -04:00
public int getNumberOfNames ( ) {
int result = names . size ( ) ;
return result ;
}
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
/ * * gets the Named range
* @param index position of the named range
* @return named range high level
2004-08-23 04:52:54 -04:00
* /
2002-04-23 18:24:41 -04:00
public HSSFName getNameAt ( int index ) {
HSSFName result = ( HSSFName ) names . get ( index ) ;
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
return result ;
}
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
/ * * gets the named range name
* @param index the named range index ( 0 based )
* @return named range name
2004-08-23 04:52:54 -04:00
* /
2002-04-23 18:24:41 -04:00
public String getNameName ( int index ) {
String result = getNameAt ( index ) . getNameName ( ) ;
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
return result ;
}
2004-08-23 04:52:54 -04:00
2003-03-06 15:41:17 -05:00
/ * *
* Sets the printarea for the sheet provided
* < p >
2003-03-07 16:52:37 -05:00
* i . e . Reference = $A$1 : $B$2
2003-03-06 15:41:17 -05:00
* @param sheetIndex Zero - based sheet index ( 0 Represents the first sheet to keep consistent with java )
2004-08-23 04:52:54 -04:00
* @param reference Valid name Reference for the Print Area
2003-03-06 15:41:17 -05:00
* /
public void setPrintArea ( int sheetIndex , String reference )
{
NameRecord name = workbook . getSpecificBuiltinRecord ( NameRecord . BUILTIN_PRINT_AREA , sheetIndex + 1 ) ;
2004-08-23 04:52:54 -04:00
2003-03-06 15:41:17 -05:00
if ( name = = null )
name = workbook . createBuiltInName ( NameRecord . BUILTIN_PRINT_AREA , sheetIndex + 1 ) ;
//adding one here because 0 indicates a global named region; doesnt make sense for print areas
2004-08-23 04:52:54 -04:00
2003-03-07 16:52:37 -05:00
short externSheetIndex = getWorkbook ( ) . checkExternSheet ( sheetIndex ) ;
2004-08-23 04:52:54 -04:00
name . setExternSheetNumber ( externSheetIndex ) ;
2003-03-07 16:52:37 -05:00
name . setAreaReference ( reference ) ;
2004-08-23 04:52:54 -04:00
2003-03-06 15:41:17 -05:00
}
2004-08-23 04:52:54 -04:00
2003-03-07 16:52:37 -05:00
/ * *
* For the Convenience of Java Programmers maintaining pointers .
2005-01-01 20:00:53 -05:00
* @see # setPrintArea ( int , String )
2003-03-07 16:52:37 -05:00
* @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 ) {
2004-08-23 04:52:54 -04:00
2008-02-15 07:04:42 -05:00
//using absolute references because they don't get copied and pasted anyway
2003-03-07 16:52:37 -05:00
CellReference cell = new CellReference ( startRow , startColumn , true , true ) ;
2008-02-15 07:04:42 -05:00
String reference = cell . formatAsString ( ) ;
2004-08-23 04:52:54 -04:00
2003-03-07 16:52:37 -05:00
cell = new CellReference ( endRow , endColumn , true , true ) ;
2008-02-15 07:04:42 -05:00
reference = reference + " : " + cell . formatAsString ( ) ;
2004-08-23 04:52:54 -04:00
setPrintArea ( sheetIndex , reference ) ;
2003-03-07 16:52:37 -05:00
}
2004-08-23 04:52:54 -04:00
2003-03-06 15:41:17 -05:00
/ * *
2003-03-07 16:52:37 -05:00
* Retrieves the reference for the printarea of the specified sheet , the sheet name is appended to the reference even if it was not specified .
2004-08-23 04:52:54 -04:00
* @param sheetIndex Zero - based sheet index ( 0 Represents the first sheet to keep consistent with java )
2003-03-06 15:41:17 -05:00
* @return String Null if no print area has been defined
2004-08-23 04:52:54 -04:00
* /
2003-03-06 15:41:17 -05:00
public String getPrintArea ( int sheetIndex )
{
2004-08-23 04:52:54 -04:00
NameRecord name = workbook . getSpecificBuiltinRecord ( NameRecord . BUILTIN_PRINT_AREA , sheetIndex + 1 ) ;
2003-03-06 15:41:17 -05:00
if ( name = = null ) return null ;
//adding one here because 0 indicates a global named region; doesnt make sense for print areas
2004-08-23 04:52:54 -04:00
2003-08-31 02:16:57 -04:00
return name . getAreaReference ( workbook ) ;
2004-08-23 04:52:54 -04:00
}
2003-03-07 16:52:37 -05:00
/ * *
* Delete the printarea for the sheet specified
* @param sheetIndex Zero - based sheet index ( 0 = First Sheet )
* /
public void removePrintArea ( int sheetIndex ) {
2004-08-23 04:52:54 -04:00
getWorkbook ( ) . removeBuiltinRecord ( NameRecord . BUILTIN_PRINT_AREA , sheetIndex + 1 ) ;
2003-03-07 16:52:37 -05:00
}
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
/ * * creates a new named range and add it to the model
* @return named range high level
2004-08-23 04:52:54 -04:00
* /
2002-04-23 18:24:41 -04:00
public HSSFName createName ( ) {
NameRecord nameRecord = workbook . createName ( ) ;
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
HSSFName newName = new HSSFName ( workbook , nameRecord ) ;
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
names . add ( newName ) ;
2004-08-23 04:52:54 -04:00
return newName ;
2002-04-23 18:24:41 -04:00
}
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
/ * * gets the named range index by his name
2006-07-27 10:15:11 -04:00
* < i > Note : < / i > Excel named ranges are case - insensitive and
* this method performs a case - insensitive search .
*
2002-04-23 18:24:41 -04:00
* @param name named range name
2004-08-23 04:52:54 -04:00
* @return named range index
* /
2002-04-23 18:24:41 -04:00
public int getNameIndex ( String name )
{
int retval = - 1 ;
for ( int k = 0 ; k < names . size ( ) ; k + + )
{
String nameName = getNameName ( k ) ;
2006-07-27 10:15:11 -04:00
if ( nameName . equalsIgnoreCase ( name ) )
2002-04-23 18:24:41 -04:00
{
retval = k ;
break ;
}
}
return retval ;
}
/ * * remove the named range by his index
* @param index named range index ( 0 based )
2004-08-23 04:52:54 -04:00
* /
2002-04-23 18:24:41 -04:00
public void removeName ( int index ) {
names . remove ( index ) ;
2004-08-23 04:52:54 -04:00
workbook . removeName ( index ) ;
2002-04-23 18:24:41 -04:00
}
2002-08-15 10:13:34 -04:00
2002-10-08 20:05:55 -04:00
/ * *
2003-07-25 09:39:08 -04:00
* Returns the instance of HSSFDataFormat for this workbook .
2002-08-15 10:13:34 -04:00
* @return the HSSFDataFormat object
* @see org . apache . poi . hssf . record . FormatRecord
* @see org . apache . poi . hssf . record . Record
* /
public HSSFDataFormat createDataFormat ( ) {
2003-07-25 09:39:08 -04:00
if ( formatter = = null )
formatter = new HSSFDataFormat ( workbook ) ;
return formatter ;
2002-08-15 10:13:34 -04:00
}
2004-08-23 04:52:54 -04:00
2002-04-23 18:24:41 -04:00
/ * * remove the named range by his name
* @param name named range name
2004-08-23 04:52:54 -04:00
* /
2002-04-23 18:24:41 -04:00
public void removeName ( String name ) {
int index = getNameIndex ( name ) ;
2004-08-23 04:52:54 -04:00
removeName ( index ) ;
2002-04-23 18:24:41 -04:00
}
2002-09-16 14:14:31 -04:00
2003-01-02 06:17:57 -05:00
public HSSFPalette getCustomPalette ( )
{
return new HSSFPalette ( workbook . getCustomPalette ( ) ) ;
}
2004-08-23 04:52:54 -04:00
/** Test only. Do not use */
2002-12-16 06:16:41 -05:00
public void insertChartRecord ( )
{
int loc = workbook . findFirstRecordLocBySid ( SSTRecord . sid ) ;
byte [ ] data = {
( byte ) 0x0F , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0xF0 , ( byte ) 0x52 ,
( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x00 ,
( byte ) 0x06 , ( byte ) 0xF0 , ( byte ) 0x18 , ( byte ) 0x00 , ( byte ) 0x00 ,
( byte ) 0x00 , ( byte ) 0x01 , ( byte ) 0x08 , ( byte ) 0x00 , ( byte ) 0x00 ,
( byte ) 0x02 , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x02 ,
( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x01 , ( byte ) 0x00 ,
( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x01 , ( byte ) 0x00 , ( byte ) 0x00 ,
( byte ) 0x00 , ( byte ) 0x03 , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x00 ,
( byte ) 0x33 , ( byte ) 0x00 , ( byte ) 0x0B , ( byte ) 0xF0 , ( byte ) 0x12 ,
( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0xBF , ( byte ) 0x00 ,
( byte ) 0x08 , ( byte ) 0x00 , ( byte ) 0x08 , ( byte ) 0x00 , ( byte ) 0x81 ,
( byte ) 0x01 , ( byte ) 0x09 , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x08 ,
( byte ) 0xC0 , ( byte ) 0x01 , ( byte ) 0x40 , ( byte ) 0x00 , ( byte ) 0x00 ,
( byte ) 0x08 , ( byte ) 0x40 , ( byte ) 0x00 , ( byte ) 0x1E , ( byte ) 0xF1 ,
( byte ) 0x10 , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x0D ,
( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x08 , ( byte ) 0x0C , ( byte ) 0x00 ,
( byte ) 0x00 , ( byte ) 0x08 , ( byte ) 0x17 , ( byte ) 0x00 , ( byte ) 0x00 ,
( byte ) 0x08 , ( byte ) 0xF7 , ( byte ) 0x00 , ( byte ) 0x00 , ( byte ) 0x10 ,
} ;
2005-08-18 03:06:44 -04:00
UnknownRecord r = new UnknownRecord ( ( short ) 0x00EB , data ) ;
2002-12-16 06:16:41 -05:00
workbook . getRecords ( ) . add ( loc , r ) ;
}
2005-05-01 07:26:18 -04:00
/ * *
* Spits out a list of all the drawing records in the workbook .
* /
public void dumpDrawingGroupRecords ( boolean fat )
{
DrawingGroupRecord r = ( DrawingGroupRecord ) workbook . findFirstRecordBySid ( DrawingGroupRecord . sid ) ;
r . decode ( ) ;
List escherRecords = r . getEscherRecords ( ) ;
PrintWriter w = new PrintWriter ( System . out ) ;
for ( Iterator iterator = escherRecords . iterator ( ) ; iterator . hasNext ( ) ; )
{
EscherRecord escherRecord = ( EscherRecord ) iterator . next ( ) ;
if ( fat )
System . out . println ( escherRecord . toString ( ) ) ;
else
escherRecord . display ( w , 0 ) ;
}
w . flush ( ) ;
}
2003-02-06 05:29:45 -05:00
2005-05-01 07:26:18 -04:00
/ * *
* Adds a picture to the workbook .
*
* @param pictureData The bytes of the picture
* @param format The format of the picture . One of < code > PICTURE_TYPE_ * < / code >
*
* @return the index to this picture ( 1 based ) .
* /
public int addPicture ( byte [ ] pictureData , int format )
{
byte [ ] uid = newUID ( ) ;
EscherBitmapBlip blipRecord = new EscherBitmapBlip ( ) ;
blipRecord . setRecordId ( ( short ) ( EscherBitmapBlip . RECORD_ID_START + format ) ) ;
2007-04-16 06:48:20 -04:00
switch ( format )
{
case PICTURE_TYPE_EMF :
blipRecord . setOptions ( HSSFPictureData . MSOBI_EMF ) ;
break ;
case PICTURE_TYPE_WMF :
blipRecord . setOptions ( HSSFPictureData . MSOBI_WMF ) ;
break ;
case PICTURE_TYPE_PICT :
blipRecord . setOptions ( HSSFPictureData . MSOBI_PICT ) ;
break ;
case PICTURE_TYPE_PNG :
blipRecord . setOptions ( HSSFPictureData . MSOBI_PNG ) ;
break ;
case HSSFWorkbook . PICTURE_TYPE_JPEG :
blipRecord . setOptions ( HSSFPictureData . MSOBI_JPEG ) ;
break ;
case HSSFWorkbook . PICTURE_TYPE_DIB :
blipRecord . setOptions ( HSSFPictureData . MSOBI_DIB ) ;
break ;
}
2005-05-01 07:26:18 -04:00
blipRecord . setUID ( uid ) ;
blipRecord . setMarker ( ( byte ) 0xFF ) ;
blipRecord . setPictureData ( pictureData ) ;
EscherBSERecord r = new EscherBSERecord ( ) ;
r . setRecordId ( EscherBSERecord . RECORD_ID ) ;
r . setOptions ( ( short ) ( 0x0002 | ( format < < 4 ) ) ) ;
r . setBlipTypeMacOS ( ( byte ) format ) ;
r . setBlipTypeWin32 ( ( byte ) format ) ;
r . setUid ( uid ) ;
r . setTag ( ( short ) 0xFF ) ;
r . setSize ( pictureData . length + 25 ) ;
r . setRef ( 1 ) ;
r . setOffset ( 0 ) ;
r . setBlipRecord ( blipRecord ) ;
return workbook . addBSERecord ( r ) ;
}
2003-02-06 05:29:45 -05:00
2007-04-16 06:48:20 -04:00
/ * *
* Gets all pictures from the Workbook .
*
* @return the list of pictures ( a list of { @link HSSFPictureData } objects . )
* /
public List getAllPictures ( )
{
2007-09-08 12:34:10 -04:00
// The drawing group record always exists at the top level, so we won't need to do this recursively.
2007-04-16 06:48:20 -04:00
List pictures = new ArrayList ( ) ;
Iterator recordIter = workbook . getRecords ( ) . iterator ( ) ;
while ( recordIter . hasNext ( ) )
{
Object obj = recordIter . next ( ) ;
if ( obj instanceof AbstractEscherHolderRecord )
{
( ( AbstractEscherHolderRecord ) obj ) . decode ( ) ;
List escherRecords = ( ( AbstractEscherHolderRecord ) obj ) . getEscherRecords ( ) ;
searchForPictures ( escherRecords , pictures ) ;
}
}
return pictures ;
}
/ * *
* Performs a recursive search for pictures in the given list of escher records .
*
* @param escherRecords the escher records .
* @param pictures the list to populate with the pictures .
* /
private void searchForPictures ( List escherRecords , List pictures )
{
Iterator recordIter = escherRecords . iterator ( ) ;
while ( recordIter . hasNext ( ) )
{
Object obj = recordIter . next ( ) ;
if ( obj instanceof EscherRecord )
{
EscherRecord escherRecord = ( EscherRecord ) obj ;
if ( escherRecord instanceof EscherBSERecord )
{
EscherBlipRecord blip = ( ( EscherBSERecord ) escherRecord ) . getBlipRecord ( ) ;
2007-08-26 11:26:29 -04:00
if ( blip ! = null )
2007-04-16 06:48:20 -04:00
{
// TODO: Some kind of structure.
2007-08-26 11:26:29 -04:00
pictures . add ( new HSSFPictureData ( blip ) ) ;
2007-04-16 06:48:20 -04:00
}
}
// Recursive call.
searchForPictures ( escherRecord . getChildRecords ( ) , pictures ) ;
}
}
}
2008-03-07 06:36:14 -05:00
/ * *
* Is the workbook protected with a password ( not encrypted ) ?
* /
public boolean isWriteProtected ( ) {
return this . workbook . isWriteProtected ( ) ;
}
2007-07-18 13:00:14 -04:00
/ * *
* protect a workbook with a password ( not encypted , just sets writeprotect
* flags and the password .
* @param password to set
* /
public void writeProtectWorkbook ( String password , String username ) {
this . workbook . writeProtectWorkbook ( password , username ) ;
}
/ * *
* removes the write protect flag
* /
public void unwriteProtectWorkbook ( ) {
this . workbook . unwriteProtectWorkbook ( ) ;
}
2007-09-08 12:34:10 -04:00
/ * *
* Gets all embedded OLE2 objects from the Workbook .
*
* @return the list of embedded objects ( a list of { @link HSSFObjectData } objects . )
* /
public List getAllEmbeddedObjects ( )
{
List objects = new ArrayList ( ) ;
for ( int i = 0 ; i < getNumberOfSheets ( ) ; i + + )
{
getAllEmbeddedObjects ( getSheetAt ( i ) . getSheet ( ) . getRecords ( ) , objects ) ;
}
return objects ;
}
/ * *
* Gets all embedded OLE2 objects from the Workbook .
*
* @param records the list of records to search .
* @param objects the list of embedded objects to populate .
* /
private void getAllEmbeddedObjects ( List records , List objects )
{
Iterator recordIter = records . iterator ( ) ;
while ( recordIter . hasNext ( ) )
{
Object obj = recordIter . next ( ) ;
if ( obj instanceof ObjRecord )
{
// TODO: More convenient way of determining if there is stored binary.
// TODO: Link to the data stored in the other stream.
Iterator subRecordIter = ( ( ObjRecord ) obj ) . getSubRecords ( ) . iterator ( ) ;
while ( subRecordIter . hasNext ( ) )
{
Object sub = subRecordIter . next ( ) ;
if ( sub instanceof EmbeddedObjectRefSubRecord )
{
2007-09-19 10:34:31 -04:00
objects . add ( new HSSFObjectData ( ( ObjRecord ) obj , filesystem ) ) ;
2007-09-08 12:34:10 -04:00
}
}
}
}
}
2005-05-01 07:26:18 -04:00
private byte [ ] newUID ( )
{
byte [ ] bytes = new byte [ 16 ] ;
return bytes ;
}
2002-01-30 21:22:28 -05:00
}