| |
| /* ==================================================================== |
| * The Apache Software License, Version 1.1 |
| * |
| * Copyright (c) 2003 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Apache" and "Apache Software Foundation" and |
| * "Apache POI" must not be used to endorse or promote products |
| * derived from this software without prior written permission. For |
| * written permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * "Apache POI", nor may "Apache" appear in their name, without |
| * prior written permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| |
| package org.apache.poi.hssf.model; |
| |
| import org.apache.poi.hssf.record.*; |
| import org.apache.poi.hssf.util.HSSFColor; |
| import org.apache.poi.hssf.util.SheetReferences; |
| import org.apache.poi.util.POILogFactory; |
| import org.apache.poi.util.POILogger; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| |
| /** |
| * Low level model implementation of a Workbook. Provides creational methods |
| * for settings and objects contained in the workbook object. |
| * <P> |
| * This file contains the low level binary records starting at the workbook's BOF and |
| * ending with the workbook's EOF. Use HSSFWorkbook for a high level representation. |
| * <P> |
| * The structures of the highlevel API use references to this to perform most of their |
| * operations. Its probably unwise to use these low level structures directly unless you |
| * really know what you're doing. I recommend you read the Microsoft Excel 97 Developer's |
| * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf |
| * before even attempting to use this. |
| * |
| * |
| * @author Shawn Laubach (slaubach at apache dot org) (Data Formats) |
| * @author Andrew C. Oliver (acoliver at apache dot org) |
| * @author Glen Stampoultzis (glens at apache.org) |
| * @author Sergei Kozello (sergeikozello at mail.ru) |
| * @author Luc Girardin (luc dot girardin at macrofocus dot com) |
| * @author Dan Sherman (dsherman at isisph.com) |
| * @author Brian Sanders (bsanders at risklabs dot com) - custom palette |
| * @see org.apache.poi.hssf.usermodel.HSSFWorkbook |
| * @version 1.0-pre |
| */ |
| |
| public class Workbook implements Model { |
| private static final int DEBUG = POILogger.DEBUG; |
| |
| // public static Workbook currentBook = null; |
| |
| /** |
| * constant used to set the "codepage" wherever "codepage" is set in records |
| * (which is duplciated in more than one record) |
| */ |
| |
| private final static short CODEPAGE = ( short ) 0x4b0; |
| |
| /** |
| * this contains the Worksheet record objects |
| */ |
| protected WorkbookRecordList records = new WorkbookRecordList(); |
| |
| /** |
| * this contains a reference to the SSTRecord so that new stings can be added |
| * to it. |
| */ |
| protected SSTRecord sst = null; |
| |
| /** |
| * Holds the Extern Sheet with references to bound sheets |
| */ |
| protected ExternSheetRecord externSheet= null; |
| |
| /** |
| * holds the "boundsheet" records (aka bundlesheet) so that they can have their |
| * reference to their "BOF" marker |
| */ |
| protected ArrayList boundsheets = new ArrayList(); |
| |
| protected ArrayList formats = new ArrayList(); |
| |
| protected ArrayList names = new ArrayList(); |
| |
| protected int numxfs = 0; // hold the number of extended format records |
| protected int numfonts = 0; // hold the number of font records |
| private short maxformatid = -1; // holds the max format id |
| private boolean uses1904datewindowing = false; // whether 1904 date windowing is being used |
| |
| private static POILogger log = POILogFactory.getLogger(Workbook.class); |
| |
| /** |
| * Creates new Workbook with no intitialization --useless right now |
| * @see #createWorkbook(List) |
| */ |
| public Workbook() { |
| } |
| |
| /** |
| * read support for low level |
| * API. Pass in an array of Record objects, A Workbook |
| * object is constructed and passed back with all of its initialization set |
| * to the passed in records and references to those records held. Unlike Sheet |
| * workbook does not use an offset (its assumed to be 0) since its first in a file. |
| * If you need an offset then construct a new array with a 0 offset or write your |
| * own ;-p. |
| * |
| * @param recs an array of Record objects |
| * @return Workbook object |
| */ |
| public static Workbook createWorkbook(List recs) { |
| log.log(DEBUG, "Workbook (readfile) created with reclen=", |
| new Integer(recs.size())); |
| Workbook retval = new Workbook(); |
| ArrayList records = new ArrayList(recs.size() / 3); |
| |
| for (int k = 0; k < recs.size(); k++) { |
| Record rec = ( Record ) recs.get(k); |
| |
| if (rec.getSid() == EOFRecord.sid) { |
| records.add(rec); |
| log.log(DEBUG, "found workbook eof record at " + k); |
| break; |
| } |
| switch (rec.getSid()) { |
| |
| case BoundSheetRecord.sid : |
| log.log(DEBUG, "found boundsheet record at " + k); |
| retval.boundsheets.add(rec); |
| retval.records.setBspos( k ); |
| break; |
| |
| case SSTRecord.sid : |
| log.log(DEBUG, "found sst record at " + k); |
| retval.sst = ( SSTRecord ) rec; |
| break; |
| |
| case FontRecord.sid : |
| log.log(DEBUG, "found font record at " + k); |
| retval.records.setFontpos( k ); |
| retval.numfonts++; |
| break; |
| |
| case ExtendedFormatRecord.sid : |
| log.log(DEBUG, "found XF record at " + k); |
| retval.records.setXfpos( k ); |
| retval.numxfs++; |
| break; |
| |
| case TabIdRecord.sid : |
| log.log(DEBUG, "found tabid record at " + k); |
| retval.records.setTabpos( k ); |
| break; |
| |
| case ProtectRecord.sid : |
| log.log(DEBUG, "found protect record at " + k); |
| retval.records.setProtpos( k ); |
| break; |
| |
| case BackupRecord.sid : |
| log.log(DEBUG, "found backup record at " + k); |
| retval.records.setBackuppos( k ); |
| break; |
| case ExternSheetRecord.sid : |
| log.log(DEBUG, "found extern sheet record at " + k); |
| retval.externSheet = ( ExternSheetRecord ) rec; |
| break; |
| case NameRecord.sid : |
| log.log(DEBUG, "found name record at " + k); |
| retval.names.add(rec); |
| // retval.records.namepos = k; |
| break; |
| case SupBookRecord.sid : |
| log.log(DEBUG, "found SupBook record at " + k); |
| // retval.records.supbookpos = k; |
| break; |
| case FormatRecord.sid : |
| log.log(DEBUG, "found format record at " + k); |
| retval.formats.add(rec); |
| retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode(); |
| break; |
| case DateWindow1904Record.sid : |
| log.log(DEBUG, "found datewindow1904 record at " + k); |
| retval.uses1904datewindowing = ((DateWindow1904Record)rec).getWindowing() == 1; |
| break; |
| case PaletteRecord.sid: |
| log.log(DEBUG, "found palette record at " + k); |
| retval.records.setPalettepos( k ); |
| default : |
| } |
| records.add(rec); |
| } |
| //What if we dont have any ranges and supbooks |
| // if (retval.records.supbookpos == 0) { |
| // retval.records.supbookpos = retval.records.bspos + 1; |
| // retval.records.namepos = retval.records.supbookpos + 1; |
| // } |
| |
| retval.records.setRecords(records); |
| log.log(DEBUG, "exit create workbook from existing file function"); |
| return retval; |
| } |
| |
| /** |
| * Creates an empty workbook object with three blank sheets and all the empty |
| * fields. Use this to create a workbook from scratch. |
| */ |
| public static Workbook createWorkbook() |
| { |
| log.log( DEBUG, "creating new workbook from scratch" ); |
| Workbook retval = new Workbook(); |
| ArrayList records = new ArrayList( 30 ); |
| ArrayList formats = new ArrayList( 8 ); |
| |
| records.add( retval.createBOF() ); |
| records.add( retval.createInterfaceHdr() ); |
| records.add( retval.createMMS() ); |
| records.add( retval.createInterfaceEnd() ); |
| records.add( retval.createWriteAccess() ); |
| records.add( retval.createCodepage() ); |
| records.add( retval.createDSF() ); |
| records.add( retval.createTabId() ); |
| retval.records.setTabpos( records.size() - 1 ); |
| records.add( retval.createFnGroupCount() ); |
| records.add( retval.createWindowProtect() ); |
| records.add( retval.createProtect() ); |
| retval.records.setProtpos( records.size() - 1 ); |
| records.add( retval.createPassword() ); |
| records.add( retval.createProtectionRev4() ); |
| records.add( retval.createPasswordRev4() ); |
| records.add( retval.createWindowOne() ); |
| records.add( retval.createBackup() ); |
| retval.records.setBackuppos( records.size() - 1 ); |
| records.add( retval.createHideObj() ); |
| records.add( retval.createDateWindow1904() ); |
| records.add( retval.createPrecision() ); |
| records.add( retval.createRefreshAll() ); |
| records.add( retval.createBookBool() ); |
| records.add( retval.createFont() ); |
| records.add( retval.createFont() ); |
| records.add( retval.createFont() ); |
| records.add( retval.createFont() ); |
| retval.records.setFontpos( records.size() - 1 ); // last font record postion |
| retval.numfonts = 4; |
| |
| // set up format records |
| for ( int i = 0; i <= 7; i++ ) |
| { |
| Record rec; |
| rec = retval.createFormat( i ); |
| retval.maxformatid = retval.maxformatid >= ( (FormatRecord) rec ).getIndexCode() ? retval.maxformatid : ( (FormatRecord) rec ).getIndexCode(); |
| formats.add( rec ); |
| records.add( rec ); |
| } |
| retval.formats = formats; |
| |
| for ( int k = 0; k < 21; k++ ) |
| { |
| records.add( retval.createExtendedFormat( k ) ); |
| retval.numxfs++; |
| } |
| retval.records.setXfpos( records.size() - 1 ); |
| for ( int k = 0; k < 6; k++ ) |
| { |
| records.add( retval.createStyle( k ) ); |
| } |
| retval.records.setPalettepos( records.size() ); |
| records.add( retval.createUseSelFS() ); |
| for ( int k = 0; k < 1; k++ ) |
| { // now just do 1 |
| BoundSheetRecord bsr = |
| (BoundSheetRecord) retval.createBoundSheet( k ); |
| |
| records.add( bsr ); |
| retval.boundsheets.add( bsr ); |
| retval.records.setBspos( records.size() - 1 ); |
| } |
| // retval.records.supbookpos = retval.records.bspos + 1; |
| // retval.records.namepos = retval.records.supbookpos + 2; |
| records.add( retval.createCountry() ); |
| retval.sst = (SSTRecord) retval.createSST(); |
| records.add( retval.sst ); |
| records.add( retval.createExtendedSST() ); |
| |
| records.add( retval.createEOF() ); |
| retval.records.setRecords(records); |
| log.log( DEBUG, "exit create new workbook from scratch" ); |
| return retval; |
| } |
| |
| |
| /**Retrieves the Builtin NameRecord that matches the name and index |
| * There shouldn't be too many names to make the sequential search too slow |
| * @param name byte representation of the builtin name to match |
| * @param sheetIndex Index to match |
| * @return null if no builtin NameRecord matches |
| */ |
| public NameRecord getSpecificBuiltinRecord(byte name, int sheetIndex) |
| { |
| Iterator iterator = names.iterator(); |
| while (iterator.hasNext()) { |
| NameRecord record = ( NameRecord ) iterator.next(); |
| |
| //print areas are one based |
| if (record.getBuiltInName() == name && record.getIndexToSheet() == sheetIndex) { |
| return record; |
| } |
| } |
| |
| return null; |
| |
| } |
| |
| /** |
| * Removes the specified Builtin NameRecord that matches the name and index |
| * @param name byte representation of the builtin to match |
| * @param sheetIndex zero-based sheet reference |
| */ |
| public void removeBuiltinRecord(byte name, int sheetIndex) { |
| //the name array is smaller so searching through it should be faster than |
| //using the findFirstXXXX methods |
| NameRecord record = getSpecificBuiltinRecord(name, sheetIndex); |
| if (record != null) { |
| names.remove(record); |
| } |
| |
| } |
| |
| public int getNumRecords() { |
| return records.size(); |
| } |
| |
| /** |
| * gets the font record at the given index in the font table. Remember |
| * "There is No Four" (someone at M$ must have gone to Rocky Horror one too |
| * many times) |
| * |
| * @param idx the index to look at (0 or greater but NOT 4) |
| * @return FontRecord located at the given index |
| */ |
| |
| public FontRecord getFontRecordAt(int idx) { |
| int index = idx; |
| |
| if (index > 4) { |
| index -= 1; // adjust for "There is no 4" |
| } |
| if (index > (numfonts - 1)) { |
| throw new ArrayIndexOutOfBoundsException( |
| "There are only " + numfonts |
| + " font records, you asked for " + idx); |
| } |
| FontRecord retval = |
| ( FontRecord ) records.get((records.getFontpos() - (numfonts - 1)) + index); |
| |
| return retval; |
| } |
| |
| /** |
| * creates a new font record and adds it to the "font table". This causes the |
| * boundsheets to move down one, extended formats to move down (so this function moves |
| * those pointers as well) |
| * |
| * @return FontRecord that was just created |
| */ |
| |
| public FontRecord createNewFont() { |
| FontRecord rec = ( FontRecord ) createFont(); |
| |
| records.add(records.getFontpos()+1, rec); |
| records.setFontpos( records.getFontpos() + 1 ); |
| numfonts++; |
| return rec; |
| } |
| |
| /** |
| * gets the number of font records |
| * |
| * @return number of font records in the "font table" |
| */ |
| |
| public int getNumberOfFontRecords() { |
| return numfonts; |
| } |
| |
| /** |
| * Sets the BOF for a given sheet |
| * |
| * @param sheetnum the number of the sheet to set the positing of the bof for |
| * @param pos the actual bof position |
| */ |
| |
| public void setSheetBof(int sheetnum, int pos) { |
| log.log(DEBUG, "setting bof for sheetnum =", new Integer(sheetnum), |
| " at pos=", new Integer(pos)); |
| checkSheets(sheetnum); |
| (( BoundSheetRecord ) boundsheets.get(sheetnum)) |
| .setPositionOfBof(pos); |
| } |
| |
| /** |
| * Returns the position of the backup record. |
| */ |
| |
| public BackupRecord getBackupRecord() { |
| return ( BackupRecord ) records.get(records.getBackuppos()); |
| } |
| |
| |
| /** |
| * sets the name for a given sheet. If the boundsheet record doesn't exist and |
| * its only one more than we have, go ahead and create it. If its > 1 more than |
| * we have, except |
| * |
| * @param sheetnum the sheet number (0 based) |
| * @param sheetname the name for the sheet |
| */ |
| |
| // for compatibility |
| public void setSheetName(int sheetnum, String sheetname ) { |
| setSheetName( sheetnum, sheetname, (byte)0 ); |
| } |
| |
| public void setSheetName(int sheetnum, String sheetname, short encoding ) { |
| checkSheets(sheetnum); |
| BoundSheetRecord sheet = (BoundSheetRecord)boundsheets.get( sheetnum ); |
| sheet.setSheetname(sheetname); |
| sheet.setSheetnameLength( (byte)sheetname.length() ); |
| sheet.setCompressedUnicodeFlag( (byte)encoding ); |
| } |
| |
| /** |
| * 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 ) { |
| int sheetNumber = getSheetIndex(sheetname); |
| //remove the sheet that needs to be reordered and place it in the spot we want |
| boundsheets.add(pos, boundsheets.remove(sheetNumber)); |
| } |
| |
| /** |
| * gets the name for a given sheet. |
| * |
| * @param sheetnum the sheet number (0 based) |
| * @return sheetname the name for the sheet |
| */ |
| |
| public String getSheetName(int sheetnum) { |
| return (( BoundSheetRecord ) boundsheets.get(sheetnum)) |
| .getSheetname(); |
| } |
| |
| /** |
| * get the sheet's index |
| * @param name sheet name |
| * @return sheet index or -1 if it was not found. |
| */ |
| |
| public int getSheetIndex(String name) { |
| int retval = -1; |
| |
| for (int k = 0; k < boundsheets.size(); k++) { |
| String sheet = getSheetName(k); |
| |
| if (sheet.equals(name)) { |
| retval = k; |
| break; |
| } |
| } |
| return retval; |
| } |
| |
| /** |
| * if we're trying to address one more sheet than we have, go ahead and add it! if we're |
| * trying to address >1 more than we have throw an exception! |
| */ |
| |
| private void checkSheets(int sheetnum) { |
| if ((boundsheets.size()) <= sheetnum) { // if we're short one add another.. |
| if ((boundsheets.size() + 1) <= sheetnum) { |
| throw new RuntimeException("Sheet number out of bounds!"); |
| } |
| BoundSheetRecord bsr = (BoundSheetRecord ) createBoundSheet(sheetnum); |
| |
| records.add(records.getBspos()+1, bsr); |
| records.setBspos( records.getBspos() + 1 ); |
| boundsheets.add(bsr); |
| fixTabIdRecord(); |
| } |
| } |
| |
| public void removeSheet(int sheetnum) { |
| if (boundsheets.size() > sheetnum) { |
| records.remove(records.getBspos() - (boundsheets.size() - 1) + sheetnum); |
| // records.bspos--; |
| boundsheets.remove(sheetnum); |
| fixTabIdRecord(); |
| } |
| } |
| |
| /** |
| * make the tabid record look like the current situation. |
| * |
| */ |
| private void fixTabIdRecord() { |
| TabIdRecord tir = ( TabIdRecord ) records.get(records.getTabpos()); |
| short[] tia = new short[ boundsheets.size() ]; |
| |
| for (short k = 0; k < tia.length; k++) { |
| tia[ k ] = k; |
| } |
| tir.setTabIdArray(tia); |
| } |
| |
| /** |
| * returns the number of boundsheet objects contained in this workbook. |
| * |
| * @return number of BoundSheet records |
| */ |
| |
| public int getNumSheets() { |
| log.log(DEBUG, "getNumSheets=", new Integer(boundsheets.size())); |
| return boundsheets.size(); |
| } |
| |
| /** |
| * get the number of ExtendedFormat records contained in this workbook. |
| * |
| * @return int count of ExtendedFormat records |
| */ |
| |
| public int getNumExFormats() { |
| log.log(DEBUG, "getXF=", new Integer(numxfs)); |
| return numxfs; |
| } |
| |
| /** |
| * gets the ExtendedFormatRecord at the given 0-based index |
| * |
| * @param index of the Extended format record (0-based) |
| * @return ExtendedFormatRecord at the given index |
| */ |
| |
| public ExtendedFormatRecord getExFormatAt(int index) { |
| int xfptr = records.getXfpos() - (numxfs - 1); |
| |
| xfptr += index; |
| ExtendedFormatRecord retval = |
| ( ExtendedFormatRecord ) records.get(xfptr); |
| |
| return retval; |
| } |
| |
| /** |
| * creates a new Cell-type Extneded Format Record and adds it to the end of |
| * ExtendedFormatRecords collection |
| * |
| * @return ExtendedFormatRecord that was created |
| */ |
| |
| public ExtendedFormatRecord createCellXF() { |
| ExtendedFormatRecord xf = createExtendedFormat(); |
| |
| records.add(records.getXfpos()+1, xf); |
| records.setXfpos( records.getXfpos() + 1 ); |
| numxfs++; |
| return xf; |
| } |
| |
| /** |
| * Adds a string to the SST table and returns its index (if its a duplicate |
| * just returns its index and update the counts) |
| * |
| * @param string the string to be added to the SSTRecord |
| * @param use16bits whether to use utf 16 or false for compressed unicode |
| * @return index of the string within the SSTRecord |
| */ |
| |
| public int addSSTString(String string, boolean use16bits) { |
| log.log(DEBUG, "insert to sst string='", string, "' and use16bits= ", |
| new Boolean(use16bits)); |
| if (sst == null) { |
| insertSST(); |
| } |
| return sst.addString(string, use16bits); |
| } |
| |
| /** |
| * Adds a string to the SST table and returns its index (if its a duplicate |
| * just returns its index and update the counts) ASSUMES compressed unicode |
| * (meaning 8bit) |
| * |
| * @param string the string to be added to the SSTRecord |
| * |
| * @return index of the string within the SSTRecord |
| */ |
| |
| public int addSSTString(String string) { |
| return addSSTString(string, false); |
| } |
| |
| /** |
| * given an index into the SST table, this function returns the corresponding String value |
| * @return String containing the SST String |
| */ |
| |
| public String getSSTString(int str) { |
| if (sst == null) { |
| insertSST(); |
| } |
| String retval = sst.getString(str); |
| |
| log.log(DEBUG, "Returning SST for index=", new Integer(str), |
| " String= ", retval); |
| return retval; |
| } |
| |
| /** |
| * use this function to add a Shared String Table to an existing sheet (say |
| * generated by a different java api) without an sst.... |
| * @see #createSST() |
| * @see org.apache.poi.hssf.record.SSTRecord |
| */ |
| |
| public void insertSST() { |
| log.log(DEBUG, "creating new SST via insertSST!"); |
| sst = ( SSTRecord ) createSST(); |
| records.add(records.size() - 1, createExtendedSST()); |
| records.add(records.size() - 2, sst); |
| } |
| |
| /** |
| * Serializes all records int the worksheet section into a big byte array. Use |
| * this to write the Workbook out. |
| * |
| * @return byte array containing the HSSF-only portions of the POIFS file. |
| */ |
| |
| public byte [] serialize() { |
| log.log(DEBUG, "Serializing Workbook!"); |
| byte[] retval = null; |
| |
| // ArrayList bytes = new ArrayList(records.size()); |
| int arraysize = getSize(); |
| int pos = 0; |
| |
| // for (int k = 0; k < records.size(); k++) |
| // { |
| // bytes.add((( Record ) records.get(k)).serialize()); |
| // } |
| // for (int k = 0; k < bytes.size(); k++) |
| // { |
| // arraysize += (( byte [] ) bytes.get(k)).length; |
| // } |
| retval = new byte[ arraysize ]; |
| for (int k = 0; k < records.size(); k++) { |
| |
| // byte[] rec = (( byte [] ) bytes.get(k)); |
| // System.arraycopy(rec, 0, retval, pos, rec.length); |
| Record record = records.get(k); |
| // Let's skip RECALCID records, as they are only use for optimization |
| if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) { |
| pos += record.serialize(pos, retval); // rec.length; |
| } |
| } |
| log.log(DEBUG, "Exiting serialize workbook"); |
| return retval; |
| } |
| |
| /** |
| * Serializes all records int the worksheet section into a big byte array. Use |
| * this to write the Workbook out. |
| * @param offset of the data to be written |
| * @param data array of bytes to write this to |
| */ |
| |
| public int serialize(int offset, byte [] data) { |
| log.log(DEBUG, "Serializing Workbook with offsets"); |
| |
| // ArrayList bytes = new ArrayList(records.size()); |
| // int arraysize = getSize(); // 0; |
| int pos = 0; |
| |
| // for (int k = 0; k < records.size(); k++) |
| // { |
| // bytes.add((( Record ) records.get(k)).serialize()); |
| // |
| // } |
| // for (int k = 0; k < bytes.size(); k++) |
| // { |
| // arraysize += (( byte [] ) bytes.get(k)).length; |
| // } |
| for (int k = 0; k < records.size(); k++) { |
| |
| // byte[] rec = (( byte [] ) bytes.get(k)); |
| // System.arraycopy(rec, 0, data, offset + pos, rec.length); |
| Record record = records.get(k); |
| // Let's skip RECALCID records, as they are only use for optimization |
| if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) { |
| pos += record.serialize(pos + offset, data); // rec.length; |
| } |
| } |
| log.log(DEBUG, "Exiting serialize workbook"); |
| return pos; |
| } |
| |
| public int getSize() { |
| int retval = 0; |
| |
| for (int k = 0; k < records.size(); k++) { |
| Record record = records.get(k); |
| // Let's skip RECALCID records, as they are only use for optimization |
| if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) { |
| retval += record.getRecordSize(); |
| } |
| } |
| return retval; |
| } |
| |
| /** |
| * creates the BOF record |
| * @see org.apache.poi.hssf.record.BOFRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a BOFRecord |
| */ |
| |
| protected Record createBOF() { |
| BOFRecord retval = new BOFRecord(); |
| |
| retval.setVersion(( short ) 0x600); |
| retval.setType(( short ) 5); |
| retval.setBuild(( short ) 0x10d3); |
| |
| // retval.setBuild((short)0x0dbb); |
| retval.setBuildYear(( short ) 1996); |
| retval.setHistoryBitMask(0x41); // was c1 before verify |
| retval.setRequiredVersion(0x6); |
| return retval; |
| } |
| |
| /** |
| * creates the InterfaceHdr record |
| * @see org.apache.poi.hssf.record.InterfaceHdrRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a InterfaceHdrRecord |
| */ |
| |
| protected Record createInterfaceHdr() { |
| InterfaceHdrRecord retval = new InterfaceHdrRecord(); |
| |
| retval.setCodepage(CODEPAGE); |
| return retval; |
| } |
| |
| /** |
| * creates an MMS record |
| * @see org.apache.poi.hssf.record.MMSRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a MMSRecord |
| */ |
| |
| protected Record createMMS() { |
| MMSRecord retval = new MMSRecord(); |
| |
| retval.setAddMenuCount(( byte ) 0); |
| retval.setDelMenuCount(( byte ) 0); |
| return retval; |
| } |
| |
| /** |
| * creates the InterfaceEnd record |
| * @see org.apache.poi.hssf.record.InterfaceEndRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a InterfaceEndRecord |
| */ |
| |
| protected Record createInterfaceEnd() { |
| return new InterfaceEndRecord(); |
| } |
| |
| /** |
| * creates the WriteAccess record containing the logged in user's name |
| * @see org.apache.poi.hssf.record.WriteAccessRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a WriteAccessRecord |
| */ |
| |
| protected Record createWriteAccess() { |
| WriteAccessRecord retval = new WriteAccessRecord(); |
| |
| retval.setUsername(System.getProperty("user.name")); |
| return retval; |
| } |
| |
| /** |
| * creates the Codepage record containing the constant stored in CODEPAGE |
| * @see org.apache.poi.hssf.record.CodepageRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a CodepageRecord |
| */ |
| |
| protected Record createCodepage() { |
| CodepageRecord retval = new CodepageRecord(); |
| |
| retval.setCodepage(CODEPAGE); |
| return retval; |
| } |
| |
| /** |
| * creates the DSF record containing a 0 since HSSF can't even create Dual Stream Files |
| * @see org.apache.poi.hssf.record.DSFRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a DSFRecord |
| */ |
| |
| protected Record createDSF() { |
| DSFRecord retval = new DSFRecord(); |
| |
| retval.setDsf( |
| ( short ) 0); // we don't even support double stream files |
| return retval; |
| } |
| |
| /** |
| * creates the TabId record containing an array of 0,1,2. This release of HSSF |
| * always has the default three sheets, no less, no more. |
| * @see org.apache.poi.hssf.record.TabIdRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a TabIdRecord |
| */ |
| |
| protected Record createTabId() { |
| TabIdRecord retval = new TabIdRecord(); |
| short[] tabidarray = { |
| 0 |
| }; |
| |
| retval.setTabIdArray(tabidarray); |
| return retval; |
| } |
| |
| /** |
| * creates the FnGroupCount record containing the Magic number constant of 14. |
| * @see org.apache.poi.hssf.record.FnGroupCountRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a FnGroupCountRecord |
| */ |
| |
| protected Record createFnGroupCount() { |
| FnGroupCountRecord retval = new FnGroupCountRecord(); |
| |
| retval.setCount(( short ) 14); |
| return retval; |
| } |
| |
| /** |
| * creates the WindowProtect record with protect set to false. |
| * @see org.apache.poi.hssf.record.WindowProtectRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a WindowProtectRecord |
| */ |
| |
| protected Record createWindowProtect() { |
| WindowProtectRecord retval = new WindowProtectRecord(); |
| |
| retval.setProtect( |
| false); // by default even when we support it we won't |
| return retval; // want it to be protected |
| } |
| |
| /** |
| * creates the Protect record with protect set to false. |
| * @see org.apache.poi.hssf.record.ProtectRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a ProtectRecord |
| */ |
| |
| protected Record createProtect() { |
| ProtectRecord retval = new ProtectRecord(); |
| |
| retval.setProtect( |
| false); // by default even when we support it we won't |
| return retval; // want it to be protected |
| } |
| |
| /** |
| * creates the Password record with password set to 0. |
| * @see org.apache.poi.hssf.record.PasswordRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a PasswordRecord |
| */ |
| |
| protected Record createPassword() { |
| PasswordRecord retval = new PasswordRecord(); |
| |
| retval.setPassword(( short ) 0); // no password by default! |
| return retval; |
| } |
| |
| /** |
| * creates the ProtectionRev4 record with protect set to false. |
| * @see org.apache.poi.hssf.record.ProtectionRev4Record |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a ProtectionRev4Record |
| */ |
| |
| protected Record createProtectionRev4() { |
| ProtectionRev4Record retval = new ProtectionRev4Record(); |
| |
| retval.setProtect(false); |
| return retval; |
| } |
| |
| /** |
| * creates the PasswordRev4 record with password set to 0. |
| * @see org.apache.poi.hssf.record.PasswordRev4Record |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a PasswordRev4Record |
| */ |
| |
| protected Record createPasswordRev4() { |
| PasswordRev4Record retval = new PasswordRev4Record(); |
| |
| retval.setPassword(( short ) 0); // no password by default! |
| return retval; |
| } |
| |
| /** |
| * creates the WindowOne record with the following magic values: <P> |
| * horizontal hold - 0x168 <P> |
| * vertical hold - 0x10e <P> |
| * width - 0x3a5c <P> |
| * height - 0x23be <P> |
| * options - 0x38 <P> |
| * selected tab - 0 <P> |
| * displayed tab - 0 <P> |
| * num selected tab- 0 <P> |
| * tab width ratio - 0x258 <P> |
| * @see org.apache.poi.hssf.record.WindowOneRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a WindowOneRecord |
| */ |
| |
| protected Record createWindowOne() { |
| WindowOneRecord retval = new WindowOneRecord(); |
| |
| retval.setHorizontalHold(( short ) 0x168); |
| retval.setVerticalHold(( short ) 0x10e); |
| retval.setWidth(( short ) 0x3a5c); |
| retval.setHeight(( short ) 0x23be); |
| retval.setOptions(( short ) 0x38); |
| retval.setSelectedTab(( short ) 0x0); |
| retval.setDisplayedTab(( short ) 0x0); |
| retval.setNumSelectedTabs(( short ) 1); |
| retval.setTabWidthRatio(( short ) 0x258); |
| return retval; |
| } |
| |
| /** |
| * creates the Backup record with backup set to 0. (loose the data, who cares) |
| * @see org.apache.poi.hssf.record.BackupRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a BackupRecord |
| */ |
| |
| protected Record createBackup() { |
| BackupRecord retval = new BackupRecord(); |
| |
| retval.setBackup( |
| ( short ) 0); // by default DONT save backups of files...just loose data |
| return retval; |
| } |
| |
| /** |
| * creates the HideObj record with hide object set to 0. (don't hide) |
| * @see org.apache.poi.hssf.record.HideObjRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a HideObjRecord |
| */ |
| |
| protected Record createHideObj() { |
| HideObjRecord retval = new HideObjRecord(); |
| |
| retval.setHideObj(( short ) 0); // by default set hide object off |
| return retval; |
| } |
| |
| /** |
| * creates the DateWindow1904 record with windowing set to 0. (don't window) |
| * @see org.apache.poi.hssf.record.DateWindow1904Record |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a DateWindow1904Record |
| */ |
| |
| protected Record createDateWindow1904() { |
| DateWindow1904Record retval = new DateWindow1904Record(); |
| |
| retval.setWindowing( |
| ( short ) 0); // don't EVER use 1904 date windowing...tick tock.. |
| return retval; |
| } |
| |
| /** |
| * creates the Precision record with precision set to true. (full precision) |
| * @see org.apache.poi.hssf.record.PrecisionRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a PrecisionRecord |
| */ |
| |
| protected Record createPrecision() { |
| PrecisionRecord retval = new PrecisionRecord(); |
| |
| retval.setFullPrecision( |
| true); // always use real numbers in calculations! |
| return retval; |
| } |
| |
| /** |
| * creates the RefreshAll record with refreshAll set to true. (refresh all calcs) |
| * @see org.apache.poi.hssf.record.RefreshAllRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a RefreshAllRecord |
| */ |
| |
| protected Record createRefreshAll() { |
| RefreshAllRecord retval = new RefreshAllRecord(); |
| |
| retval.setRefreshAll(false); |
| return retval; |
| } |
| |
| /** |
| * creates the BookBool record with saveLinkValues set to 0. (don't save link values) |
| * @see org.apache.poi.hssf.record.BookBoolRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a BookBoolRecord |
| */ |
| |
| protected Record createBookBool() { |
| BookBoolRecord retval = new BookBoolRecord(); |
| |
| retval.setSaveLinkValues(( short ) 0); |
| return retval; |
| } |
| |
| /** |
| * creates a Font record with the following magic values: <P> |
| * fontheight = 0xc8<P> |
| * attributes = 0x0<P> |
| * color palette index = 0x7fff<P> |
| * bold weight = 0x190<P> |
| * Font Name Length = 5 <P> |
| * Font Name = Arial <P> |
| * |
| * @see org.apache.poi.hssf.record.FontRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a FontRecord |
| */ |
| |
| protected Record createFont() { |
| FontRecord retval = new FontRecord(); |
| |
| retval.setFontHeight(( short ) 0xc8); |
| retval.setAttributes(( short ) 0x0); |
| retval.setColorPaletteIndex(( short ) 0x7fff); |
| retval.setBoldWeight(( short ) 0x190); |
| retval.setFontNameLength(( byte ) 5); |
| retval.setFontName("Arial"); |
| return retval; |
| } |
| |
| /** |
| * Creates a FormatRecord object |
| * @param id the number of the format record to create (meaning its position in |
| * a file as M$ Excel would create it.) |
| * @return record containing a FormatRecord |
| * @see org.apache.poi.hssf.record.FormatRecord |
| * @see org.apache.poi.hssf.record.Record |
| */ |
| |
| protected Record createFormat(int id) { // we'll need multiple editions for |
| FormatRecord retval = new FormatRecord(); // the differnt formats |
| |
| switch (id) { |
| |
| case 0 : |
| retval.setIndexCode(( short ) 5); |
| retval.setFormatStringLength(( byte ) 0x17); |
| retval.setFormatString("\"$\"#,##0_);\\(\"$\"#,##0\\)"); |
| break; |
| |
| case 1 : |
| retval.setIndexCode(( short ) 6); |
| retval.setFormatStringLength(( byte ) 0x1c); |
| retval.setFormatString("\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)"); |
| break; |
| |
| case 2 : |
| retval.setIndexCode(( short ) 7); |
| retval.setFormatStringLength(( byte ) 0x1d); |
| retval.setFormatString("\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)"); |
| break; |
| |
| case 3 : |
| retval.setIndexCode(( short ) 8); |
| retval.setFormatStringLength(( byte ) 0x22); |
| retval.setFormatString( |
| "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)"); |
| break; |
| |
| case 4 : |
| retval.setIndexCode(( short ) 0x2a); |
| retval.setFormatStringLength(( byte ) 0x32); |
| retval.setFormatString( |
| "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)"); |
| break; |
| |
| case 5 : |
| retval.setIndexCode(( short ) 0x29); |
| retval.setFormatStringLength(( byte ) 0x29); |
| retval.setFormatString( |
| "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)"); |
| break; |
| |
| case 6 : |
| retval.setIndexCode(( short ) 0x2c); |
| retval.setFormatStringLength(( byte ) 0x3a); |
| retval.setFormatString( |
| "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)"); |
| break; |
| |
| case 7 : |
| retval.setIndexCode(( short ) 0x2b); |
| retval.setFormatStringLength(( byte ) 0x31); |
| retval.setFormatString( |
| "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)"); |
| break; |
| } |
| return retval; |
| } |
| |
| /** |
| * Creates an ExtendedFormatRecord object |
| * @param id the number of the extended format record to create (meaning its position in |
| * a file as MS Excel would create it.) |
| * |
| * @return record containing an ExtendedFormatRecord |
| * @see org.apache.poi.hssf.record.ExtendedFormatRecord |
| * @see org.apache.poi.hssf.record.Record |
| */ |
| |
| protected Record createExtendedFormat(int id) { // we'll need multiple editions |
| ExtendedFormatRecord retval = new ExtendedFormatRecord(); |
| |
| switch (id) { |
| |
| case 0 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 1 : |
| retval.setFontIndex(( short ) 1); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 2 : |
| retval.setFontIndex(( short ) 1); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 3 : |
| retval.setFontIndex(( short ) 2); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 4 : |
| retval.setFontIndex(( short ) 2); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 5 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 6 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 7 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 8 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 9 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 10 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 11 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 12 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 13 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 14 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff400); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| // cell records |
| case 15 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0); |
| retval.setCellOptions(( short ) 0x1); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0x0); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| // style |
| case 16 : |
| retval.setFontIndex(( short ) 1); |
| retval.setFormatIndex(( short ) 0x2b); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff800); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 17 : |
| retval.setFontIndex(( short ) 1); |
| retval.setFormatIndex(( short ) 0x29); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff800); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 18 : |
| retval.setFontIndex(( short ) 1); |
| retval.setFormatIndex(( short ) 0x2c); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff800); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 19 : |
| retval.setFontIndex(( short ) 1); |
| retval.setFormatIndex(( short ) 0x2a); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff800); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 20 : |
| retval.setFontIndex(( short ) 1); |
| retval.setFormatIndex(( short ) 0x9); |
| retval.setCellOptions(( short ) 0xfffffff5); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0xfffff800); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| // unused from this point down |
| case 21 : |
| retval.setFontIndex(( short ) 5); |
| retval.setFormatIndex(( short ) 0x0); |
| retval.setCellOptions(( short ) 0x1); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0x800); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 22 : |
| retval.setFontIndex(( short ) 6); |
| retval.setFormatIndex(( short ) 0x0); |
| retval.setCellOptions(( short ) 0x1); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0x5c00); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 23 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0x31); |
| retval.setCellOptions(( short ) 0x1); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0x5c00); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 24 : |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0x8); |
| retval.setCellOptions(( short ) 0x1); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0x5c00); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| |
| case 25 : |
| retval.setFontIndex(( short ) 6); |
| retval.setFormatIndex(( short ) 0x8); |
| retval.setCellOptions(( short ) 0x1); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0x5c00); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| break; |
| } |
| return retval; |
| } |
| |
| /** |
| * creates an default cell type ExtendedFormatRecord object. |
| * @return ExtendedFormatRecord with intial defaults (cell-type) |
| */ |
| |
| protected ExtendedFormatRecord createExtendedFormat() { |
| ExtendedFormatRecord retval = new ExtendedFormatRecord(); |
| |
| retval.setFontIndex(( short ) 0); |
| retval.setFormatIndex(( short ) 0x0); |
| retval.setCellOptions(( short ) 0x1); |
| retval.setAlignmentOptions(( short ) 0x20); |
| retval.setIndentionOptions(( short ) 0); |
| retval.setBorderOptions(( short ) 0); |
| retval.setPaletteOptions(( short ) 0); |
| retval.setAdtlPaletteOptions(( short ) 0); |
| retval.setFillPaletteOptions(( short ) 0x20c0); |
| retval.setTopBorderPaletteIdx(HSSFColor.BLACK.index); |
| retval.setBottomBorderPaletteIdx(HSSFColor.BLACK.index); |
| retval.setLeftBorderPaletteIdx(HSSFColor.BLACK.index); |
| retval.setRightBorderPaletteIdx(HSSFColor.BLACK.index); |
| return retval; |
| } |
| |
| /** |
| * Creates a StyleRecord object |
| * @param id the number of the style record to create (meaning its position in |
| * a file as MS Excel would create it. |
| * @return record containing a StyleRecord |
| * @see org.apache.poi.hssf.record.StyleRecord |
| * @see org.apache.poi.hssf.record.Record |
| */ |
| |
| protected Record createStyle(int id) { // we'll need multiple editions |
| StyleRecord retval = new StyleRecord(); |
| |
| switch (id) { |
| |
| case 0 : |
| retval.setIndex(( short ) 0xffff8010); |
| retval.setBuiltin(( byte ) 3); |
| retval.setOutlineStyleLevel(( byte ) 0xffffffff); |
| break; |
| |
| case 1 : |
| retval.setIndex(( short ) 0xffff8011); |
| retval.setBuiltin(( byte ) 6); |
| retval.setOutlineStyleLevel(( byte ) 0xffffffff); |
| break; |
| |
| case 2 : |
| retval.setIndex(( short ) 0xffff8012); |
| retval.setBuiltin(( byte ) 4); |
| retval.setOutlineStyleLevel(( byte ) 0xffffffff); |
| break; |
| |
| case 3 : |
| retval.setIndex(( short ) 0xffff8013); |
| retval.setBuiltin(( byte ) 7); |
| retval.setOutlineStyleLevel(( byte ) 0xffffffff); |
| break; |
| |
| case 4 : |
| retval.setIndex(( short ) 0xffff8000); |
| retval.setBuiltin(( byte ) 0); |
| retval.setOutlineStyleLevel(( byte ) 0xffffffff); |
| break; |
| |
| case 5 : |
| retval.setIndex(( short ) 0xffff8014); |
| retval.setBuiltin(( byte ) 5); |
| retval.setOutlineStyleLevel(( byte ) 0xffffffff); |
| break; |
| } |
| return retval; |
| } |
| |
| /** |
| * Creates a palette record initialized to the default palette |
| * @return a PaletteRecord instance populated with the default colors |
| * @see org.apache.poi.hssf.record.PaletteRecord |
| */ |
| protected PaletteRecord createPalette() |
| { |
| return new PaletteRecord(PaletteRecord.sid); |
| } |
| |
| /** |
| * Creates the UseSelFS object with the use natural language flag set to 0 (false) |
| * @return record containing a UseSelFSRecord |
| * @see org.apache.poi.hssf.record.UseSelFSRecord |
| * @see org.apache.poi.hssf.record.Record |
| */ |
| |
| protected Record createUseSelFS() { |
| UseSelFSRecord retval = new UseSelFSRecord(); |
| |
| retval.setFlag(( short ) 0); |
| return retval; |
| } |
| |
| /** |
| * create a "bound sheet" or "bundlesheet" (depending who you ask) record |
| * Always sets the sheet's bof to 0. You'll need to set that yourself. |
| * @param id either sheet 0,1 or 2. |
| * @return record containing a BoundSheetRecord |
| * @see org.apache.poi.hssf.record.BoundSheetRecord |
| * @see org.apache.poi.hssf.record.Record |
| */ |
| |
| protected Record createBoundSheet(int id) { // 1,2,3 sheets |
| BoundSheetRecord retval = new BoundSheetRecord(); |
| |
| switch (id) { |
| |
| case 0 : |
| retval.setPositionOfBof(0x0); // should be set later |
| retval.setOptionFlags(( short ) 0); |
| retval.setSheetnameLength(( byte ) 0x6); |
| retval.setCompressedUnicodeFlag(( byte ) 0); |
| retval.setSheetname("Sheet1"); |
| break; |
| |
| case 1 : |
| retval.setPositionOfBof(0x0); // should be set later |
| retval.setOptionFlags(( short ) 0); |
| retval.setSheetnameLength(( byte ) 0x6); |
| retval.setCompressedUnicodeFlag(( byte ) 0); |
| retval.setSheetname("Sheet2"); |
| break; |
| |
| case 2 : |
| retval.setPositionOfBof(0x0); // should be set later |
| retval.setOptionFlags(( short ) 0); |
| retval.setSheetnameLength(( byte ) 0x6); |
| retval.setCompressedUnicodeFlag(( byte ) 0); |
| retval.setSheetname("Sheet3"); |
| break; |
| } |
| return retval; |
| } |
| |
| /** |
| * Creates the Country record with the default country set to 1 |
| * and current country set to 7 in case of russian locale ("ru_RU") and 1 otherwise |
| * @return record containing a CountryRecord |
| * @see org.apache.poi.hssf.record.CountryRecord |
| * @see org.apache.poi.hssf.record.Record |
| */ |
| |
| protected Record createCountry() { // what a novel idea, create your own! |
| CountryRecord retval = new CountryRecord(); |
| |
| retval.setDefaultCountry(( short ) 1); |
| |
| // from Russia with love ;) |
| if ( Locale.getDefault().toString().equals( "ru_RU" ) ) { |
| retval.setCurrentCountry(( short ) 7); |
| } |
| else { |
| retval.setCurrentCountry(( short ) 1); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * Creates the SST record with no strings and the unique/num string set to 0 |
| * @return record containing a SSTRecord |
| * @see org.apache.poi.hssf.record.SSTRecord |
| * @see org.apache.poi.hssf.record.Record |
| */ |
| |
| protected Record createSST() { |
| return new SSTRecord(); |
| } |
| |
| /** |
| * Creates the ExtendedSST record with numstrings per bucket set to 0x8. HSSF |
| * doesn't yet know what to do with this thing, but we create it with nothing in |
| * it hardly just to make Excel happy and our sheets look like Excel's |
| * |
| * @return record containing an ExtSSTRecord |
| * @see org.apache.poi.hssf.record.ExtSSTRecord |
| * @see org.apache.poi.hssf.record.Record |
| */ |
| |
| protected Record createExtendedSST() { |
| ExtSSTRecord retval = new ExtSSTRecord(); |
| |
| retval.setNumStringsPerBucket(( short ) 0x8); |
| return retval; |
| } |
| |
| /** |
| * creates the EOF record |
| * @see org.apache.poi.hssf.record.EOFRecord |
| * @see org.apache.poi.hssf.record.Record |
| * @return record containing a EOFRecord |
| */ |
| |
| protected Record createEOF() { |
| return new EOFRecord(); |
| } |
| |
| public SheetReferences getSheetReferences() { |
| SheetReferences refs = new SheetReferences(); |
| |
| if (externSheet != null) { |
| for (int k = 0; k < externSheet.getNumOfREFStructures(); k++) { |
| String sheetName = findSheetNameFromExternSheet((short)k); |
| refs.addSheetReference(sheetName, k); |
| } |
| } |
| return refs; |
| } |
| |
| /** finds the sheet name by his extern sheet index |
| * @param num extern sheet index |
| * @return sheet name |
| */ |
| public String findSheetNameFromExternSheet(short num){ |
| String result; |
| |
| short indexToSheet = externSheet.getREFRecordAt(num).getIndexToFirstSupBook(); |
| result = getSheetName(indexToSheet); |
| |
| return result; |
| } |
| |
| /** |
| * Finds the sheet index for a particular external sheet number. |
| * @param externSheetNumber The external sheet number to convert |
| * @return The index to the sheet found. |
| */ |
| public int getSheetIndexFromExternSheetIndex(int externSheetNumber) |
| { |
| if (externSheetNumber >= externSheet.getNumOfREFStructures()) |
| return -1; |
| else |
| return externSheet.getREFRecordAt(externSheetNumber).getIndexToFirstSupBook(); |
| } |
| |
| /** returns the extern sheet number for specific sheet number , |
| * if this sheet doesn't exist in extern sheet , add it |
| * @param sheetNumber sheet number |
| * @return index to extern sheet |
| */ |
| public short checkExternSheet(int sheetNumber){ |
| |
| int i = 0; |
| boolean flag = false; |
| short result = 0; |
| |
| if (externSheet == null) { |
| externSheet = createExternSheet(); |
| } |
| |
| //Trying to find reference to this sheet |
| while (i < externSheet.getNumOfREFStructures() && !flag){ |
| ExternSheetSubRecord record = externSheet.getREFRecordAt(i); |
| |
| if (record.getIndexToFirstSupBook() == sheetNumber && |
| record.getIndexToLastSupBook() == sheetNumber){ |
| flag = true; |
| result = (short) i; |
| } |
| |
| ++i; |
| } |
| |
| //We Havent found reference to this sheet |
| if (!flag) { |
| result = addSheetIndexToExternSheet((short) sheetNumber); |
| } |
| |
| return result; |
| } |
| |
| private short addSheetIndexToExternSheet(short sheetNumber){ |
| short result; |
| |
| ExternSheetSubRecord record = new ExternSheetSubRecord(); |
| record.setIndexToFirstSupBook(sheetNumber); |
| record.setIndexToLastSupBook(sheetNumber); |
| externSheet.addREFRecord(record); |
| externSheet.setNumOfREFStructures((short)(externSheet.getNumOfREFStructures() + 1)); |
| result = (short)(externSheet.getNumOfREFStructures() - 1); |
| |
| return result; |
| } |
| |
| |
| |
| /** gets the total number of names |
| * @return number of names |
| */ |
| public int getNumNames(){ |
| int result = names.size(); |
| |
| return result; |
| } |
| |
| /** gets the name record |
| * @param index name index |
| * @return name record |
| */ |
| public NameRecord getNameRecord(int index){ |
| NameRecord result = (NameRecord) names.get(index); |
| |
| return result; |
| |
| } |
| |
| /** creates new name |
| * @return new name record |
| */ |
| public NameRecord createName(){ |
| |
| NameRecord name = new NameRecord(); |
| |
| // Not the most efficient way but the other way was causing too many bugs |
| int idx = findFirstRecordLocBySid(ExternSheetRecord.sid); |
| if (idx == -1) idx = findFirstRecordLocBySid(SupBookRecord.sid); |
| if (idx == -1) idx = findFirstRecordLocBySid(CountryRecord.sid); |
| |
| records.add(idx+names.size()+1, name); |
| names.add(name); |
| |
| return name; |
| } |
| |
| |
| /** creates new name |
| * @return new name record |
| */ |
| public NameRecord addName(NameRecord name) |
| { |
| // Not the most efficient way but the other way was causing too many bugs |
| int idx = findFirstRecordLocBySid(ExternSheetRecord.sid); |
| if (idx == -1) idx = findFirstRecordLocBySid(SupBookRecord.sid); |
| if (idx == -1) idx = findFirstRecordLocBySid(CountryRecord.sid); |
| records.add(idx+names.size()+1, name); |
| names.add(name); |
| |
| return name; |
| } |
| |
| /**Generates a NameRecord to represent a built-in region |
| * @return a new NameRecord unless the index is invalid |
| */ |
| public NameRecord createBuiltInName(byte builtInName, int index) |
| { |
| if (index == -1 || index+1 > (int)Short.MAX_VALUE) |
| throw new IllegalArgumentException("Index is not valid ["+index+"]"); |
| |
| NameRecord name = new NameRecord(builtInName, (short)(index)); |
| |
| addName(name); |
| |
| return name; |
| } |
| |
| |
| /** removes the name |
| * @param namenum name index |
| */ |
| public void removeName(int namenum){ |
| if (names.size() > namenum) { |
| int idx = findFirstRecordLocBySid(NameRecord.sid); |
| records.remove(idx + namenum); |
| names.remove(namenum); |
| } |
| |
| } |
| |
| /** creates a new extern sheet record |
| * @return the new extern sheet record |
| */ |
| protected ExternSheetRecord createExternSheet(){ |
| ExternSheetRecord externSheet = new ExternSheetRecord(); |
| |
| int idx = findFirstRecordLocBySid(CountryRecord.sid); |
| |
| records.add(idx+1, externSheet); |
| // records.add(records.supbookpos + 1 , rec); |
| |
| //We also adds the supBook for internal reference |
| SupBookRecord supbook = new SupBookRecord(); |
| |
| supbook.setNumberOfSheets((short)getNumSheets()); |
| //supbook.setFlag(); |
| |
| records.add(idx+1, supbook); |
| // records.add(records.supbookpos + 1 , supbook); |
| |
| return externSheet; |
| } |
| |
| /** |
| * Returns a format index that matches the passed in format. It does not tie into HSSFDataFormat. |
| * @param format the format string |
| * @param createIfNotFound creates a new format if format not found |
| * @return the format id of a format that matches or -1 if none found and createIfNotFound |
| */ |
| public short getFormat(String format, boolean createIfNotFound) { |
| Iterator iterator; |
| for (iterator = formats.iterator(); iterator.hasNext();) { |
| FormatRecord r = (FormatRecord)iterator.next(); |
| if (r.getFormatString().equals(format)) { |
| return r.getIndexCode(); |
| } |
| } |
| |
| if (createIfNotFound) { |
| return createFormat(format); |
| } |
| |
| return -1; |
| } |
| |
| /** |
| * Returns the list of FormatRecords in the workbook. |
| * @return ArrayList of FormatRecords in the notebook |
| */ |
| public ArrayList getFormats() { |
| return formats; |
| } |
| |
| /** |
| * Creates a FormatRecord, inserts it, and returns the index code. |
| * @param format the format string |
| * @return the index code of the format record. |
| * @see org.apache.poi.hssf.record.FormatRecord |
| * @see org.apache.poi.hssf.record.Record |
| */ |
| public short createFormat( String format ) |
| { |
| // ++xfpos; //These are to ensure that positions are updated properly |
| // ++palettepos; |
| // ++bspos; |
| FormatRecord rec = new FormatRecord(); |
| maxformatid = maxformatid >= (short) 0xa4 ? (short) ( maxformatid + 1 ) : (short) 0xa4; //Starting value from M$ empiracle study. |
| rec.setIndexCode( maxformatid ); |
| rec.setFormatStringLength( (byte) format.length() ); |
| rec.setFormatString( format ); |
| |
| int pos = 0; |
| while ( pos < records.size() && records.get( pos ).getSid() != FormatRecord.sid ) |
| pos++; |
| pos += formats.size(); |
| formats.add( rec ); |
| records.add( pos, rec ); |
| return maxformatid; |
| } |
| |
| |
| /** |
| * Returns the first occurance of a record matching a particular sid. |
| */ |
| public Record findFirstRecordBySid(short sid) { |
| for (Iterator iterator = records.iterator(); iterator.hasNext(); ) { |
| Record record = ( Record ) iterator.next(); |
| |
| if (record.getSid() == sid) { |
| return record; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the index of a record matching a particular sid. |
| * @param sid The sid of the record to match |
| * @return The index of -1 if no match made. |
| */ |
| public int findFirstRecordLocBySid(short sid) { |
| int index = 0; |
| for (Iterator iterator = records.iterator(); iterator.hasNext(); ) { |
| Record record = ( Record ) iterator.next(); |
| |
| if (record.getSid() == sid) { |
| return index; |
| } |
| index ++; |
| } |
| return -1; |
| } |
| |
| /** |
| * Returns the next occurance of a record matching a particular sid. |
| */ |
| public Record findNextRecordBySid(short sid, int pos) { |
| int matches = 0; |
| for (Iterator iterator = records.iterator(); iterator.hasNext(); ) { |
| Record record = ( Record ) iterator.next(); |
| |
| if (record.getSid() == sid) { |
| if (matches++ == pos) |
| return record; |
| } |
| } |
| return null; |
| } |
| |
| public List getRecords() |
| { |
| return records.getRecords(); |
| } |
| |
| // public void insertChartRecords( List chartRecords ) |
| // { |
| // backuppos += chartRecords.size(); |
| // fontpos += chartRecords.size(); |
| // palettepos += chartRecords.size(); |
| // bspos += chartRecords.size(); |
| // xfpos += chartRecords.size(); |
| // |
| // records.addAll(protpos, chartRecords); |
| // } |
| |
| /** |
| * Whether date windowing is based on 1/2/1904 or 1/1/1900. |
| * Some versions of Excel (Mac) can save workbooks using 1904 date windowing. |
| * |
| * @return true if using 1904 date windowing |
| */ |
| public boolean isUsing1904DateWindowing() { |
| return uses1904datewindowing; |
| } |
| |
| /** |
| * Returns the custom palette in use for this workbook; if a custom palette record |
| * does not exist, then it is created. |
| */ |
| public PaletteRecord getCustomPalette() |
| { |
| PaletteRecord palette; |
| Record rec = records.get(records.getPalettepos()); |
| if (rec instanceof PaletteRecord) |
| { |
| palette = (PaletteRecord) rec; |
| } |
| else |
| { |
| palette = createPalette(); |
| records.add(records.getPalettepos(), palette); |
| } |
| return palette; |
| } |
| |
| |
| } |
| |