/* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ package org.apache.poi.hssf.model; import java.security.AccessControlException; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.poi.ddf.EscherBSERecord; import org.apache.poi.ddf.EscherBoolProperty; import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherDgRecord; import org.apache.poi.ddf.EscherDggRecord; import org.apache.poi.ddf.EscherOptRecord; import org.apache.poi.ddf.EscherProperties; import org.apache.poi.ddf.EscherRGBProperty; import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherSimpleProperty; import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.ddf.EscherSplitMenuColorsRecord; import org.apache.poi.hssf.extractor.OldExcelExtractor; import org.apache.poi.hssf.record.BOFRecord; import org.apache.poi.hssf.record.BackupRecord; import org.apache.poi.hssf.record.BookBoolRecord; import org.apache.poi.hssf.record.BoundSheetRecord; import org.apache.poi.hssf.record.CodepageRecord; import org.apache.poi.hssf.record.CountryRecord; import org.apache.poi.hssf.record.DSFRecord; import org.apache.poi.hssf.record.DateWindow1904Record; import org.apache.poi.hssf.record.DrawingGroupRecord; import org.apache.poi.hssf.record.EOFRecord; import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.ExtSSTRecord; import org.apache.poi.hssf.record.ExtendedFormatRecord; import org.apache.poi.hssf.record.ExternSheetRecord; import org.apache.poi.hssf.record.FileSharingRecord; import org.apache.poi.hssf.record.FnGroupCountRecord; import org.apache.poi.hssf.record.FontRecord; import org.apache.poi.hssf.record.FormatRecord; import org.apache.poi.hssf.record.HideObjRecord; import org.apache.poi.hssf.record.HyperlinkRecord; import org.apache.poi.hssf.record.InterfaceEndRecord; import org.apache.poi.hssf.record.InterfaceHdrRecord; import org.apache.poi.hssf.record.MMSRecord; import org.apache.poi.hssf.record.NameCommentRecord; import org.apache.poi.hssf.record.NameRecord; import org.apache.poi.hssf.record.PaletteRecord; import org.apache.poi.hssf.record.PasswordRecord; import org.apache.poi.hssf.record.PasswordRev4Record; import org.apache.poi.hssf.record.PrecisionRecord; import org.apache.poi.hssf.record.ProtectRecord; import org.apache.poi.hssf.record.ProtectionRev4Record; import org.apache.poi.hssf.record.RecalcIdRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.RefreshAllRecord; import org.apache.poi.hssf.record.SSTRecord; import org.apache.poi.hssf.record.StyleRecord; import org.apache.poi.hssf.record.SupBookRecord; import org.apache.poi.hssf.record.TabIdRecord; import org.apache.poi.hssf.record.UseSelFSRecord; import org.apache.poi.hssf.record.WindowOneRecord; import org.apache.poi.hssf.record.WindowProtectRecord; import org.apache.poi.hssf.record.WriteAccessRecord; import org.apache.poi.hssf.record.WriteProtectRecord; import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.poifs.crypt.CryptoFunctions; import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName; import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet; import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheetRange; import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.ss.formula.ptg.Area3DPtg; import org.apache.poi.ss.formula.ptg.NameXPtg; import org.apache.poi.ss.formula.ptg.OperandPtg; import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.Ref3DPtg; import org.apache.poi.ss.formula.udf.UDFFinder; import org.apache.poi.ss.usermodel.BuiltinFormats; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.util.Internal; import org.apache.poi.util.LocaleUtil; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; /** * Low level model implementation of a Workbook. Provides creational methods * for settings and objects contained in the workbook object. *
* 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. *
* 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.
*
* @see org.apache.poi.hssf.usermodel.HSSFWorkbook
*/
@Internal
public final class InternalWorkbook {
/**
* Excel silently truncates long sheet names to 31 chars.
* This constant is used to ensure uniqueness in the first 31 chars
*/
private static final int MAX_SENSITIVE_SHEET_NAME_LEN = 31;
/**
* Normally, the Workbook will be in a POIFS Stream called
* "Workbook". However, some weird XLS generators use "WORKBOOK"
* or "BOOK".
*/
public static final String[] WORKBOOK_DIR_ENTRY_NAMES = {
"Workbook", // as per BIFF8 spec
"WORKBOOK", // Typically from third party programs
"BOOK", // Typically odd Crystal Reports exports
};
/**
* Name of older (pre-Excel 97) Workbook streams, which
* aren't supported by HSSFWorkbook, only by
* {@link OldExcelExtractor}
*/
public static final String OLD_WORKBOOK_DIR_ENTRY_NAME = "Book";
private static final POILogger log = POILogFactory.getLogger(InternalWorkbook.class);
private static final int DEBUG = POILogger.DEBUG;
/**
* constant used to set the "codepage" wherever "codepage" is set in records
* (which is duplicated in more than one record)
*/
private final static short CODEPAGE = 0x04B0;
/**
* this contains the Worksheet record objects
*/
private final WorkbookRecordList records;
/**
* this contains a reference to the SSTRecord so that new stings can be added
* to it.
*/
protected SSTRecord sst;
private LinkTable linkTable; // optionally occurs if there are references in the document. (4.10.3)
/**
* holds the "boundsheet" records (aka bundlesheet) so that they can have their
* reference to their "BOF" marker
*/
private final List
* horizontal hold - 0x168
* vertical hold - 0x10e
* width - 0x3a5c
* height - 0x23be
* options - 0x38
* selected tab - 0
* displayed tab - 0
* num selected tab- 0
* tab width ratio - 0x258
*/
private static WindowOneRecord 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.setActiveSheetIndex( 0x0);
retval.setFirstVisibleTab(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)
*/
private static BackupRecord 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)
*/
private static HideObjRecord 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)
*/
private static DateWindow1904Record 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)
*/
private static PrecisionRecord createPrecision() {
PrecisionRecord retval = new PrecisionRecord();
retval.setFullPrecision(true); // always use real numbers in calculations!
return retval;
}
/**
* @return a new RefreshAll record with refreshAll set to false. (do not refresh all calcs)
*/
private static RefreshAllRecord createRefreshAll() {
return new RefreshAllRecord(false);
}
/**
* creates the BookBool record with saveLinkValues set to 0. (don't save link values)
*/
private static BookBoolRecord createBookBool() {
BookBoolRecord retval = new BookBoolRecord();
retval.setSaveLinkValues(( short ) 0);
return retval;
}
/**
* creates a Font record with the following magic values:
* fontheight = 0xc8
* attributes = 0x0
* color palette index = 0x7fff
* bold weight = 0x190
* Font Name Length = 5
* Font Name = Arial
*/
private static FontRecord createFont() {
FontRecord retval = new FontRecord();
retval.setFontHeight(( short ) 0xc8);
retval.setAttributes(( short ) 0x0);
retval.setColorPaletteIndex(( short ) 0x7fff);
retval.setBoldWeight(( short ) 0x190);
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.)
*/
private static FormatRecord createFormat(int id) {
// we'll need multiple editions for
// the different formats
switch (id) {
case 0: return new FormatRecord(5, BuiltinFormats.getBuiltinFormat(5));
case 1: return new FormatRecord(6, BuiltinFormats.getBuiltinFormat(6));
case 2: return new FormatRecord(7, BuiltinFormats.getBuiltinFormat(7));
case 3: return new FormatRecord(8, BuiltinFormats.getBuiltinFormat(8));
case 4: return new FormatRecord(0x2a, BuiltinFormats.getBuiltinFormat(0x2a));
case 5: return new FormatRecord(0x29, BuiltinFormats.getBuiltinFormat(0x29));
case 6: return new FormatRecord(0x2c, BuiltinFormats.getBuiltinFormat(0x2c));
case 7: return new FormatRecord(0x2b, BuiltinFormats.getBuiltinFormat(0x2b));
}
throw new IllegalArgumentException("Unexpected id " + id);
}
/**
* 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.)
*/
private static ExtendedFormatRecord 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)
*/
private static 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.
*/
private static StyleRecord createStyle(int id) { // we'll need multiple editions
StyleRecord retval = new StyleRecord();
switch (id) {
case 0 :
retval.setXFIndex(0x010);
retval.setBuiltinStyle(3);
retval.setOutlineStyleLevel(( byte ) 0xffffffff);
break;
case 1 :
retval.setXFIndex(0x011);
retval.setBuiltinStyle(6);
retval.setOutlineStyleLevel(( byte ) 0xffffffff);
break;
case 2 :
retval.setXFIndex(0x012);
retval.setBuiltinStyle(4);
retval.setOutlineStyleLevel(( byte ) 0xffffffff);
break;
case 3 :
retval.setXFIndex(0x013);
retval.setBuiltinStyle(7);
retval.setOutlineStyleLevel(( byte ) 0xffffffff);
break;
case 4 :
retval.setXFIndex(0x000);
retval.setBuiltinStyle(0);
retval.setOutlineStyleLevel(( byte ) 0xffffffff);
break;
case 5 :
retval.setXFIndex(0x014);
retval.setBuiltinStyle(5);
retval.setOutlineStyleLevel(( byte ) 0xffffffff);
break;
}
return retval;
}
/**
* Creates a palette record initialized to the default palette
*/
private static PaletteRecord createPalette() {
return new PaletteRecord();
}
/**
* @return a new UseSelFS object with the use natural language flag set to 0 (false)
*/
private static UseSelFSRecord createUseSelFS() {
return new UseSelFSRecord(false);
}
/**
* 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
*/
private static BoundSheetRecord createBoundSheet(int id) {
return new BoundSheetRecord("Sheet" + (id+1));
}
/**
* 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
*/
private static CountryRecord createCountry() {
CountryRecord retval = new CountryRecord();
retval.setDefaultCountry(( short ) 1);
// from Russia with love ;)
if ( LocaleUtil.getUserLocale().toString().equals( "ru_RU" ) ) {
retval.setCurrentCountry(( short ) 7);
}
else {
retval.setCurrentCountry(( short ) 1);
}
return retval;
}
/**
* 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
*/
private static ExtSSTRecord createExtendedSST() {
ExtSSTRecord retval = new ExtSSTRecord();
retval.setNumStringsPerBucket(( short ) 0x8);
return retval;
}
/**
* lazy initialization
* Note - creating the link table causes creation of 1 EXTERNALBOOK and 1 EXTERNALSHEET record
*/
private LinkTable getOrCreateLinkTable() {
if(linkTable == null) {
linkTable = new LinkTable((short) getNumSheets(), records);
}
return linkTable;
}
public int linkExternalWorkbook(String name, Workbook externalWorkbook) {
return getOrCreateLinkTable().linkExternalWorkbook(name, externalWorkbook);
}
/**
* Finds the first sheet name by his extern sheet index
* @param externSheetIndex extern sheet index
* @return first sheet name.
*/
public String findSheetFirstNameFromExternSheet(int externSheetIndex){
int indexToSheet = linkTable.getFirstInternalSheetIndexForExtIndex(externSheetIndex);
return findSheetNameFromIndex(indexToSheet);
}
public String findSheetLastNameFromExternSheet(int externSheetIndex){
int indexToSheet = linkTable.getLastInternalSheetIndexForExtIndex(externSheetIndex);
return findSheetNameFromIndex(indexToSheet);
}
private String findSheetNameFromIndex(int internalSheetIndex) {
if (internalSheetIndex < 0) {
// TODO - what does '-1' mean here?
//error check, bail out gracefully!
return "";
}
if (internalSheetIndex >= boundsheets.size()) {
// Not sure if this can ever happen (See bug 45798)
return ""; // Seems to be what excel would do in this case
}
return getSheetName(internalSheetIndex);
}
public ExternalSheet getExternalSheet(int externSheetIndex) {
String[] extNames = linkTable.getExternalBookAndSheetName(externSheetIndex);
if (extNames == null) {
return null;
}
if (extNames.length == 2) {
return new ExternalSheet(extNames[0], extNames[1]);
} else {
return new ExternalSheetRange(extNames[0], extNames[1], extNames[2]);
}
}
public ExternalName getExternalName(int externSheetIndex, int externNameIndex) {
String nameName = linkTable.resolveNameXText(externSheetIndex, externNameIndex, this);
if(nameName == null) {
return null;
}
int ix = linkTable.resolveNameXIx(externSheetIndex, externNameIndex);
return new ExternalName(nameName, externNameIndex, ix);
}
/**
* Finds the (first) 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 getFirstSheetIndexFromExternSheetIndex(int externSheetNumber)
{
return linkTable.getFirstInternalSheetIndexForExtIndex(externSheetNumber);
}
/**
* Finds the last sheet index for a particular external sheet number,
* which may be the same as the first (except for multi-sheet references)
* @param externSheetNumber The external sheet number to convert
* @return The index to the sheet found.
*/
public int getLastSheetIndexFromExternSheetIndex(int externSheetNumber)
{
return linkTable.getLastInternalSheetIndexForExtIndex(externSheetNumber);
}
/**
* Returns the extern sheet number for specific sheet number.
* If this sheet doesn't exist in extern sheet, add it
* @param sheetNumber local sheet number
* @return index to extern sheet
*/
public short checkExternSheet(int sheetNumber){
return (short)getOrCreateLinkTable().checkExternSheet(sheetNumber);
}
/**
* Returns the extern sheet number for specific range of sheets.
* If this sheet range doesn't exist in extern sheet, add it
* @param firstSheetNumber first local sheet number
* @param lastSheetNumber last local sheet number
* @return index to extern sheet
*/
public short checkExternSheet(int firstSheetNumber, int lastSheetNumber){
return (short)getOrCreateLinkTable().checkExternSheet(firstSheetNumber, lastSheetNumber);
}
public int getExternalSheetIndex(String workbookName, String sheetName) {
return getOrCreateLinkTable().getExternalSheetIndex(workbookName, sheetName, sheetName);
}
public int getExternalSheetIndex(String workbookName, String firstSheetName, String lastSheetName) {
return getOrCreateLinkTable().getExternalSheetIndex(workbookName, firstSheetName, lastSheetName);
}
/** gets the total number of names
* @return number of names
*/
public int getNumNames(){
if(linkTable == null) {
return 0;
}
return linkTable.getNumNames();
}
/** gets the name record
* @param index name index
* @return name record
*/
public NameRecord getNameRecord(int index){
return linkTable.getNameRecord(index);
}
/** gets the name comment record
* @param nameRecord name record who's comment is required.
* @return name comment record or null
if there isn't one for the given name.
*/
public NameCommentRecord getNameCommentRecord(final NameRecord nameRecord){
return commentRecords.get(nameRecord.getNameText());
}
/** creates new name
* @return new name record
*/
public NameRecord createName(){
return addName(new NameRecord());
}
/** creates new name
* @return new name record
*/
public NameRecord addName(NameRecord name)
{
LinkTable linkTable = getOrCreateLinkTable();
linkTable.addName(name);
return name;
}
/**
* Generates a NameRecord to represent a built-in region
* @return a new NameRecord
*/
public NameRecord createBuiltInName(byte builtInName, int sheetNumber) {
if (sheetNumber < 0 || sheetNumber+1 > Short.MAX_VALUE) {
throw new IllegalArgumentException("Sheet number ["+sheetNumber+"]is not valid ");
}
NameRecord name = new NameRecord(builtInName, sheetNumber);
if(linkTable.nameAlreadyExists(name)) {
throw new RuntimeException("Builtin (" + builtInName
+ ") already exists for sheet (" + sheetNumber + ")");
}
addName(name);
return name;
}
/** removes the name
* @param nameIndex name index
*/
public void removeName(int nameIndex){
if (linkTable.getNumNames() > nameIndex) {
int idx = findFirstRecordLocBySid(NameRecord.sid);
records.remove(idx + nameIndex);
linkTable.removeName(nameIndex);
}
}
/**
* If a {@link NameCommentRecord} is added or the name it references
* is renamed, then this will update the lookup cache for it.
*/
public void updateNameCommentRecordCache(final NameCommentRecord commentRecord) {
if(commentRecords.containsValue(commentRecord)) {
for(Entry