package org.apache.poi.hssf.record;
-import java.util.Iterator;
+import java.util.ArrayList;
import java.util.List;
-import java.util.Stack;
import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.record.formula.Area3DPtg;
*/
public final class NameRecord extends Record {
public final static short sid = 0x0018;
- /**Included for completeness sake, not implemented
- */
- public final static byte BUILTIN_CONSOLIDATE_AREA = (byte)1;
-
- /**Included for completeness sake, not implemented
- */
- public final static byte BUILTIN_AUTO_OPEN = (byte)2;
-
- /**Included for completeness sake, not implemented
- */
- public final static byte BUILTIN_AUTO_CLOSE = (byte)3;
-
- /**Included for completeness sake, not implemented
- */
- public final static byte BUILTIN_DATABASE = (byte)4;
-
- /**Included for completeness sake, not implemented
- */
- public final static byte BUILTIN_CRITERIA = (byte)5;
-
- public final static byte BUILTIN_PRINT_AREA = (byte)6;
- public final static byte BUILTIN_PRINT_TITLE = (byte)7;
-
- /**Included for completeness sake, not implemented
- */
- public final static byte BUILTIN_RECORDER = (byte)8;
-
- /**Included for completeness sake, not implemented
- */
- public final static byte BUILTIN_DATA_FORM = (byte)9;
-
- /**Included for completeness sake, not implemented
- */
-
- public final static byte BUILTIN_AUTO_ACTIVATE = (byte)10;
-
- /**Included for completeness sake, not implemented
- */
+ /**Included for completeness sake, not implemented */
+ public final static byte BUILTIN_CONSOLIDATE_AREA = 1;
+ /**Included for completeness sake, not implemented */
+ public final static byte BUILTIN_AUTO_OPEN = 2;
+ /**Included for completeness sake, not implemented */
+ public final static byte BUILTIN_AUTO_CLOSE = 3;
+ /**Included for completeness sake, not implemented */
+ public final static byte BUILTIN_DATABASE = 4;
+ /**Included for completeness sake, not implemented */
+ public final static byte BUILTIN_CRITERIA = 5;
+
+ public final static byte BUILTIN_PRINT_AREA = 6;
+ public final static byte BUILTIN_PRINT_TITLE = 7;
+
+ /**Included for completeness sake, not implemented */
+ public final static byte BUILTIN_RECORDER = 8;
+ /**Included for completeness sake, not implemented */
+ public final static byte BUILTIN_DATA_FORM = 9;
+ /**Included for completeness sake, not implemented */
+ public final static byte BUILTIN_AUTO_ACTIVATE = 10;
+ /**Included for completeness sake, not implemented */
+ public final static byte BUILTIN_AUTO_DEACTIVATE = 11;
+ /**Included for completeness sake, not implemented */
+ public final static byte BUILTIN_SHEET_TITLE = 12;
+
+ public final static byte BUILTIN_FILTER_DB = 13;
- public final static byte BUILTIN_AUTO_DEACTIVATE = (byte)11;
-
- /**Included for completeness sake, not implemented
- */
- public final static byte BUILTIN_SHEET_TITLE = (byte)12;
-
private static final class Option {
public static final int OPT_HIDDEN_NAME = 0x0001;
public static final int OPT_FUNCTION_NAME = 0x0002;
public static final int OPT_BUILTIN = 0x0020;
public static final int OPT_BINDATA = 0x1000;
}
-
+
private short field_1_option_flag;
private byte field_2_keyboard_shortcut;
- private byte field_3_length_name_text;
- private short field_4_length_name_definition;
private short field_5_index_to_sheet; // unused: see field_6
/** the one based sheet number. Zero if this is a global name */
private int field_6_sheetNumber;
- private byte field_7_length_custom_menu;
- private byte field_8_length_description_text;
- private byte field_9_length_help_topic_text;
- private byte field_10_length_status_bar_text;
- private byte field_11_compressed_unicode_flag; // not documented
- private byte field_12_builtIn_name;
+ private boolean field_11_nameIsMultibyte;
+ private byte field_12_built_in_code;
private String field_12_name_text;
- private Stack field_13_name_definition;
+ private Ptg[] field_13_name_definition;
private String field_14_custom_menu_text;
private String field_15_description_text;
private String field_16_help_topic_text;
/** Creates new NameRecord */
public NameRecord() {
- field_13_name_definition = new Stack();
+ field_13_name_definition = Ptg.EMPTY_PTG_ARRAY;
- field_12_name_text = new String();
- field_14_custom_menu_text = new String();
- field_15_description_text = new String();
- field_16_help_topic_text = new String();
- field_17_status_bar_text = new String();
+ field_12_name_text = "";
+ field_14_custom_menu_text = "";
+ field_15_description_text = "";
+ field_16_help_topic_text = "";
+ field_17_status_bar_text = "";
}
/**
*/
public NameRecord(byte builtin, int sheetNumber)
{
- this();
- this.field_12_builtIn_name = builtin;
- this.setOptionFlag((short)(this.field_1_option_flag | Option.OPT_BUILTIN));
- this.setNameTextLength((byte)1);
+ this();
+ field_12_built_in_code = builtin;
+ setOptionFlag((short)(field_1_option_flag | Option.OPT_BUILTIN));
field_6_sheetNumber = sheetNumber; //the extern sheets are set through references
-
- //clearing these because they are not used with builtin records
- this.setCustomMenuLength((byte)0);
- this.setDescriptionTextLength((byte)0);
- this.setHelpTopicLength((byte)0);
- this.setStatusBarLength((byte)0);
-
-
}
/** sets the option flag for the named range
field_2_keyboard_shortcut = shortcut;
}
- /** sets the name of the named range length
- * @param length name length
- */
- public void setNameTextLength(byte length){
- field_3_length_name_text = length;
- }
-
- /** sets the definition (reference - formula) length
- * @param length defenition length
- */
- public void setDefinitionTextLength(short length){
- field_4_length_name_definition = length;
- }
-
- /** sets the index number to the extern sheet (thats is what writen in documentation
- * but as i saw , it works differently)
- * @param index extern sheet index
- */
- public void setUnused(short index){
- field_5_index_to_sheet = index;
-
- // field_6_equals_to_index_to_sheet is equal to field_5_index_to_sheet
-// field_6_equals_to_index_to_sheet = index;
- }
-
/**
* For named ranges, and built-in names
- * @return the 1-based sheet number. Zero if this is a global name
+ * @return the 1-based sheet number. Zero if this is a global name
*/
public int getSheetNumber()
{
}
- /** sets the custom menu length
- * @param length custom menu length
- */
- public void setCustomMenuLength(byte length){
- field_7_length_custom_menu = length;
- }
-
- /** sets the length of named range description
- * @param length description length
- */
- public void setDescriptionTextLength(byte length){
- field_8_length_description_text = length;
- }
-
- /** sets the help topic length
- * @param length help topic length
- */
- public void setHelpTopicLength(byte length){
- field_9_length_help_topic_text = length;
- }
-
- /** sets the length of the status bar text
- * @param length status bar text length
- */
- public void setStatusBarLength(byte length){
- field_10_length_status_bar_text = length;
- }
-
- /** sets the compressed unicode flag
- * @param flag unicode flag
- */
- public void setCompressedUnicodeFlag(byte flag) {
- field_11_compressed_unicode_flag = flag;
- }
-
/** sets the name of the named range
* @param name named range name
*/
public void setNameText(String name){
field_12_name_text = name;
- setCompressedUnicodeFlag(
- StringUtil.hasMultibyte(name) ? (byte)1 : (byte)0
- );
+ field_11_nameIsMultibyte = StringUtil.hasMultibyte(name);
}
/** sets the custom menu text
return field_2_keyboard_shortcut ;
}
- /**
+ /**
* gets the name length, in characters
* @return name length
*/
- public byte getNameTextLength(){
- return field_3_length_name_text;
- }
-
- /**
- * gets the name length, in bytes
- * @return raw name length
- */
- public byte getRawNameTextLength(){
- if( (field_11_compressed_unicode_flag & 0x01) == 1 ) {
- return (byte)(2 * field_3_length_name_text);
+ private int getNameTextLength(){
+ if (isBuiltInName()) {
+ return 1;
}
- return field_3_length_name_text;
- }
-
- /** get the definition length
- * @return definition length
- */
- public short getDefinitionLength(){
- return field_4_length_name_definition;
- }
-
- /** gets the index to extern sheet
- * @return index to extern sheet
- */
- public short getUnused(){
- return field_5_index_to_sheet;
- }
-
- /** gets the custom menu length
- * @return custom menu length
- */
- public byte getCustomMenuLength(){
- return field_7_length_custom_menu;
- }
-
- /** gets the description text length
- * @return description text length
- */
- public byte getDescriptionTextLength(){
- return field_8_length_description_text;
- }
-
- /** gets the help topic length
- * @return help topic length
- */
- public byte getHelpTopicLength(){
- return field_9_length_help_topic_text;
- }
-
- /** get the status bar text length
- * @return satus bar length
- */
- public byte getStatusBarLength(){
- return field_10_length_status_bar_text;
- }
-
- /** gets the name compressed Unicode flag
- * @return compressed unicode flag
- */
- public byte getCompressedUnicodeFlag() {
- return field_11_compressed_unicode_flag;
+ return field_12_name_text.length();
}
public boolean isHiddenName() {
return (field_1_option_flag & Option.OPT_HIDDEN_NAME) != 0;
}
+ public void setHidden(boolean b) {
+ if (b) {
+ field_1_option_flag |= Option.OPT_HIDDEN_NAME;
+ } else {
+ field_1_option_flag &= (~Option.OPT_HIDDEN_NAME);
+ }
+ }
/**
* @return true if name is a function
*/
*/
public boolean isBuiltInName()
{
- return ((this.field_1_option_flag & Option.OPT_BUILTIN) != 0);
+ return ((field_1_option_flag & Option.OPT_BUILTIN) != 0);
}
*/
public String getNameText(){
- return this.isBuiltInName() ? this.translateBuiltInName(this.getBuiltInName()) : field_12_name_text;
+ return isBuiltInName() ? translateBuiltInName(getBuiltInName()) : field_12_name_text;
}
/** Gets the Built In Name
*/
public byte getBuiltInName()
{
- return this.field_12_builtIn_name;
+ return field_12_built_in_code;
}
/** gets the definition, reference (Formula)
- * @return definition -- can be null if we cant parse ptgs
+ * @return the name formula. never <code>null</code>
*/
- public List getNameDefinition() {
- return field_13_name_definition;
+ public Ptg[] getNameDefinition() {
+ return (Ptg[]) field_13_name_definition.clone();
}
- public void setNameDefinition(Stack nameDefinition) {
- field_13_name_definition = nameDefinition;
+ public void setNameDefinition(Ptg[] ptgs) {
+ field_13_name_definition = (Ptg[]) ptgs.clone();
}
/** get the custom menu text
throw new RecordFormatException("NOT A valid Name RECORD");
}
}
-
+
+
/**
* called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a
* @param data byte array containing instance data
* @return number of bytes written
*/
- public int serialize( int offset, byte[] data )
- {
- LittleEndian.putShort( data, 0 + offset, sid );
- short size = (short)( 15 + getTextsLength() + getNameDefinitionSize());
- LittleEndian.putShort( data, 2 + offset, size );
- // size defined below
- LittleEndian.putShort( data, 4 + offset, getOptionFlag() );
- data[6 + offset] = getKeyboardShortcut();
- data[7 + offset] = getNameTextLength();
- LittleEndian.putShort( data, 8 + offset, getDefinitionLength() );
- LittleEndian.putShort( data, 10 + offset, getUnused() );
- LittleEndian.putUShort( data, 12 + offset, field_6_sheetNumber);
- data[14 + offset] = getCustomMenuLength();
- data[15 + offset] = getDescriptionTextLength();
- data[16 + offset] = getHelpTopicLength();
- data[17 + offset] = getStatusBarLength();
- data[18 + offset] = getCompressedUnicodeFlag();
-
- int start_of_name_definition = 19 + field_3_length_name_text;
-
- if (this.isBuiltInName()) {
- //can send the builtin name directly in
- data [19 + offset] = this.getBuiltInName();
- } else if ((this.getCompressedUnicodeFlag() & 0x01) == 1) {
- StringUtil.putUnicodeLE( getNameText(), data, 19 + offset );
- start_of_name_definition = 19 + (2 * field_3_length_name_text);
- } else {
- StringUtil.putCompressedUnicode( getNameText(), data, 19 + offset );
- }
-
-
- Ptg.serializePtgStack(field_13_name_definition, data, start_of_name_definition + offset );
-
+ public int serialize( int offset, byte[] data ) {
- int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition;
- StringUtil.putCompressedUnicode( getCustomMenuText(), data, start_of_custom_menu_text + offset );
-
- int start_of_description_text = start_of_custom_menu_text + field_7_length_custom_menu;
- StringUtil.putCompressedUnicode( getDescriptionText(), data, start_of_description_text + offset );
-
- int start_of_help_topic_text = start_of_description_text + field_8_length_description_text;
- StringUtil.putCompressedUnicode( getHelpTopicText(), data, start_of_help_topic_text + offset );
-
- int start_of_status_bar_text = start_of_help_topic_text + field_9_length_help_topic_text;
- StringUtil.putCompressedUnicode( getStatusBarText(), data, start_of_status_bar_text + offset );
-
- return getRecordSize();
- /* } */
- }
-
- /**
- * Gets the length of all texts, in bytes
- * @return total length
- */
- public int getTextsLength(){
- int result;
-
- result = getRawNameTextLength() + getDescriptionTextLength() +
- getHelpTopicLength() + getStatusBarLength();
-
- return result;
- }
-
- private int getNameDefinitionSize() {
- int result = 0;
- List list = field_13_name_definition;
+ int field_7_length_custom_menu = field_14_custom_menu_text.length();
+ int field_8_length_description_text = field_15_description_text.length();
+ int field_9_length_help_topic_text = field_16_help_topic_text.length();
+ int field_10_length_status_bar_text = field_17_status_bar_text.length();
+ int rawNameSize = getNameRawSize();
- for (int k = 0; k < list.size(); k++)
- {
- Ptg ptg = ( Ptg ) list.get(k);
-
- result += ptg.getSize();
+ int formulaTotalSize = Ptg.getEncodedSize(field_13_name_definition);
+ int dataSize = 15 // 4 shorts + 7 bytes
+ + rawNameSize
+ + field_7_length_custom_menu
+ + field_8_length_description_text
+ + field_9_length_help_topic_text
+ + field_10_length_status_bar_text
+ + formulaTotalSize;
+
+ LittleEndian.putShort(data, 0 + offset, sid);
+ LittleEndian.putUShort(data, 2 + offset, dataSize);
+ // size defined below
+ LittleEndian.putShort(data, 4 + offset, getOptionFlag());
+ LittleEndian.putByte(data, 6 + offset, getKeyboardShortcut());
+ LittleEndian.putByte(data, 7 + offset, getNameTextLength());
+ // Note -
+ LittleEndian.putUShort(data, 8 + offset, Ptg.getEncodedSizeWithoutArrayData(field_13_name_definition));
+ LittleEndian.putUShort(data, 10 + offset, field_5_index_to_sheet);
+ LittleEndian.putUShort(data, 12 + offset, field_6_sheetNumber);
+ LittleEndian.putByte(data, 14 + offset, field_7_length_custom_menu);
+ LittleEndian.putByte(data, 15 + offset, field_8_length_description_text);
+ LittleEndian.putByte(data, 16 + offset, field_9_length_help_topic_text);
+ LittleEndian.putByte(data, 17 + offset, field_10_length_status_bar_text);
+ LittleEndian.putByte(data, 18 + offset, field_11_nameIsMultibyte ? 1 : 0);
+ int pos = 19 + offset;
+
+ if (isBuiltInName()) {
+ //can send the builtin name directly in
+ LittleEndian.putByte(data, pos, field_12_built_in_code);
+ } else {
+ String nameText = field_12_name_text;
+ if (field_11_nameIsMultibyte) {
+ StringUtil.putUnicodeLE(nameText, data, pos);
+ } else {
+ StringUtil.putCompressedUnicode(nameText, data, pos);
+ }
}
- return result;
+ pos += rawNameSize;
+
+ Ptg.serializePtgs(field_13_name_definition, data, pos);
+ pos += formulaTotalSize;
+
+ StringUtil.putCompressedUnicode( getCustomMenuText(), data, pos);
+ pos += field_7_length_custom_menu;
+ StringUtil.putCompressedUnicode( getDescriptionText(), data, pos);
+ pos += field_8_length_description_text;
+ StringUtil.putCompressedUnicode( getHelpTopicText(), data, pos);
+ pos += field_9_length_help_topic_text;
+ StringUtil.putCompressedUnicode( getStatusBarText(), data, pos);
+
+ return 4 + dataSize;
+ }
+ private int getNameRawSize() {
+ if (isBuiltInName()) {
+ return 1;
+ }
+ int nChars = field_12_name_text.length();
+ if(field_11_nameIsMultibyte) {
+ return 2 * nChars;
+ }
+ return nChars;
}
/** returns the record size
*/
public int getRecordSize(){
- int result;
-
- result = 19 + getTextsLength() + getNameDefinitionSize();
-
-
- return result;
+ return 4 // sid + size
+ + 15 // 4 shorts + 7 bytes
+ + getNameRawSize()
+ + field_14_custom_menu_text.length()
+ + field_15_description_text.length()
+ + field_16_help_topic_text.length()
+ + field_17_status_bar_text.length()
+ + Ptg.getEncodedSize(field_13_name_definition);
}
/** gets the extern sheet number
* @return extern sheet index
*/
public short getExternSheetNumber(){
- if (field_13_name_definition == null || field_13_name_definition.isEmpty()) return 0;
- Ptg ptg = (Ptg) field_13_name_definition.peek();
- short result = 0;
+ if (field_13_name_definition.length < 1) {
+ return 0;
+ }
+ Ptg ptg = field_13_name_definition[0];
if (ptg.getClass() == Area3DPtg.class){
- result = ((Area3DPtg) ptg).getExternSheetIndex();
+ return ((Area3DPtg) ptg).getExternSheetIndex();
- } else if (ptg.getClass() == Ref3DPtg.class){
- result = ((Ref3DPtg) ptg).getExternSheetIndex();
}
-
- return result;
+ if (ptg.getClass() == Ref3DPtg.class){
+ return ((Ref3DPtg) ptg).getExternSheetIndex();
+ }
+ return 0;
}
/** sets the extern sheet number
public void setExternSheetNumber(short externSheetNumber){
Ptg ptg;
- if (field_13_name_definition == null || field_13_name_definition.isEmpty()){
- field_13_name_definition = new Stack();
+ if (field_13_name_definition.length < 1){
ptg = createNewPtg();
+ field_13_name_definition = new Ptg[] {
+ ptg,
+ };
} else {
- ptg = (Ptg) field_13_name_definition.peek();
+ ptg = field_13_name_definition[0];
}
if (ptg.getClass() == Area3DPtg.class){
}
- private Ptg createNewPtg(){
- Ptg ptg = new Area3DPtg("A1", 0); // TODO - change to not be partially initialised
- field_13_name_definition.push(ptg);
-
- return ptg;
+ private static Ptg createNewPtg(){
+ return new Area3DPtg("A1", 0); // TODO - change to not be partially initialised
}
/** gets the reference , the area only (range)
//Trying to find if what ptg do we need
RangeAddress ra = new RangeAddress(ref);
Ptg oldPtg;
- Ptg ptg;
- if (field_13_name_definition==null ||field_13_name_definition.isEmpty()){
- field_13_name_definition = new Stack();
+ if (field_13_name_definition.length < 1){
oldPtg = createNewPtg();
} else {
//Trying to find extern sheet index
- oldPtg = (Ptg) field_13_name_definition.pop();
+ oldPtg = field_13_name_definition[0];
}
-
+ List temp = new ArrayList();
short externSheetIndex = 0;
if (oldPtg.getClass() == Area3DPtg.class){
if (ra.hasRange()) {
// Is it contiguous or not?
- AreaReference[] refs =
- AreaReference.generateContiguous(ref);
- this.setDefinitionTextLength((short)0);
+ AreaReference[] refs = AreaReference.generateContiguous(ref);
- // Add the area reference(s)
+ // Add the area reference(s)
for(int i=0; i<refs.length; i++) {
- ptg = new Area3DPtg(refs[i].formatAsString(), externSheetIndex);
- field_13_name_definition.push(ptg);
- this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) );
+ Ptg ptg = new Area3DPtg(refs[i].formatAsString(), externSheetIndex);
+ temp.add(ptg);
}
// And then a union if we had more than one area
if(refs.length > 1) {
- ptg = UnionPtg.instance;
- field_13_name_definition.push(ptg);
- this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) );
+ Ptg ptg = UnionPtg.instance;
+ temp.add(ptg);
}
} else {
- ptg = new Ref3DPtg();
+ Ptg ptg = new Ref3DPtg();
((Ref3DPtg) ptg).setExternSheetIndex(externSheetIndex);
((Ref3DPtg) ptg).setArea(ref);
- field_13_name_definition.push(ptg);
- this.setDefinitionTextLength((short)ptg.getSize());
+ temp.add(ptg);
}
+ Ptg[] ptgs = new Ptg[temp.size()];
+ temp.toArray(ptgs);
+ field_13_name_definition = ptgs;
}
/**
* @param in the RecordInputstream to read the record from
*/
protected void fillFields(RecordInputStream in) {
- field_1_option_flag = in.readShort();
- field_2_keyboard_shortcut = in.readByte();
- field_3_length_name_text = in.readByte();
- field_4_length_name_definition = in.readShort();
- field_5_index_to_sheet = in.readShort();
- field_6_sheetNumber = in.readUShort();
- field_7_length_custom_menu = in.readByte();
- field_8_length_description_text = in.readByte();
- field_9_length_help_topic_text = in.readByte();
- field_10_length_status_bar_text = in.readByte();
-
- //store the name in byte form if it's a builtin name
- field_11_compressed_unicode_flag= in.readByte();
- if (this.isBuiltInName()) {
- field_12_builtIn_name = in.readByte();
- } else {
- if (field_11_compressed_unicode_flag == 1) {
- field_12_name_text = in.readUnicodeLEString(field_3_length_name_text);
- } else {
- field_12_name_text = in.readCompressedUnicode(field_3_length_name_text);
- }
+ field_1_option_flag = in.readShort();
+ field_2_keyboard_shortcut = in.readByte();
+ int field_3_length_name_text = in.readByte();
+ int field_4_length_name_definition = in.readShort();
+ field_5_index_to_sheet = in.readShort();
+ field_6_sheetNumber = in.readUShort();
+ int field_7_length_custom_menu = in.readUByte();
+ int field_8_length_description_text = in.readUByte();
+ int field_9_length_help_topic_text = in.readUByte();
+ int field_10_length_status_bar_text = in.readUByte();
+
+ //store the name in byte form if it's a built-in name
+ field_11_nameIsMultibyte = (in.readByte() != 0);
+ if (isBuiltInName()) {
+ field_12_built_in_code = in.readByte();
+ } else {
+ if (field_11_nameIsMultibyte) {
+ field_12_name_text = in.readUnicodeLEString(field_3_length_name_text);
+ } else {
+ field_12_name_text = in.readCompressedUnicode(field_3_length_name_text);
+ }
}
-
- field_13_name_definition = Ptg.createParsedExpressionTokens(field_4_length_name_definition, in);
-
+
+ field_13_name_definition = Ptg.readTokens(field_4_length_name_definition, in);
+
//Who says that this can only ever be compressed unicode???
- field_14_custom_menu_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_7_length_custom_menu));
-
- field_15_description_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_8_length_description_text));
-
- field_16_help_topic_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_9_length_help_topic_text));
-
- field_17_status_bar_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_10_length_status_bar_text));
- /*} */
+ field_14_custom_menu_text = in.readCompressedUnicode(field_7_length_custom_menu);
+ field_15_description_text = in.readCompressedUnicode(field_8_length_description_text);
+ field_16_help_topic_text = in.readCompressedUnicode(field_9_length_help_topic_text);
+ field_17_status_bar_text = in.readCompressedUnicode(field_10_length_status_bar_text);
}
/**
return sid;
}
/*
- 20 00
- 00
- 01
+ 20 00
+ 00
+ 01
1A 00 // sz = 0x1A = 26
- 00 00
- 01 00
- 00
- 00
- 00
- 00
+ 00 00
+ 01 00
+ 00
+ 00
+ 00
+ 00
00 // unicode flag
07 // name
-
+
29 17 00 3B 00 00 00 00 FF FF 00 00 02 00 3B 00 //{ 26
00 07 00 07 00 00 00 FF 00 10 // }
-
-
-
- 20 00
- 00
- 01
+
+
+
+ 20 00
+ 00
+ 01
0B 00 // sz = 0xB = 11
- 00 00
- 01 00
- 00
- 00
- 00
- 00
+ 00 00
+ 01 00
+ 00
+ 00
+ 00
+ 00
00 // unicode flag
07 // name
-
+
3B 00 00 07 00 07 00 00 00 FF 00 // { 11 }
*/
/*
- 18, 00,
- 1B, 00,
-
- 20, 00,
- 00,
- 01,
- 0B, 00,
- 00,
- 00,
- 00,
- 00,
- 00,
- 07,
- 3B 00 00 07 00 07 00 00 00 FF 00 ]
+ 18, 00,
+ 1B, 00,
+
+ 20, 00,
+ 00,
+ 01,
+ 0B, 00,
+ 00,
+ 00,
+ 00,
+ 00,
+ 00,
+ 07,
+ 3B 00 00 07 00 07 00 00 00 FF 00 ]
*/
- /**
- * @see Object#toString()
- */
public String toString() {
- StringBuffer buffer = new StringBuffer();
-
- buffer.append("[NAME]\n");
- buffer.append(" .option flags = ").append( HexDump.toHex( field_1_option_flag ) )
- .append("\n");
- buffer.append(" .keyboard shortcut = ").append( HexDump.toHex( field_2_keyboard_shortcut ) )
- .append("\n");
- buffer.append(" .length of the name = ").append( field_3_length_name_text )
- .append("\n");
- buffer.append(" .size of the formula data = ").append( field_4_length_name_definition )
- .append("\n");
- buffer.append(" .unused = ").append( field_5_index_to_sheet )
- .append("\n");
- buffer.append(" .index to sheet (1-based, 0=Global) = ").append( field_6_sheetNumber )
- .append("\n");
- buffer.append(" .Length of menu text (character count) = ").append( field_7_length_custom_menu )
- .append("\n");
- buffer.append(" .Length of description text (character count) = ").append( field_8_length_description_text )
- .append("\n");
- buffer.append(" .Length of help topic text (character count) = ").append( field_9_length_help_topic_text )
- .append("\n");
- buffer.append(" .Length of status bar text (character count) = ").append( field_10_length_status_bar_text )
- .append("\n");
- buffer.append(" .Name (Unicode flag) = ").append( field_11_compressed_unicode_flag )
- .append("\n");
- buffer.append(" .Name (Unicode text) = ").append( getNameText() )
- .append("\n");
-
- buffer.append(" .Parts (" + field_13_name_definition.size() +"):")
- .append("\n");
- Iterator it = field_13_name_definition.iterator();
- while(it.hasNext()) {
- Ptg ptg = (Ptg)it.next();
- buffer.append(" " + ptg.toString()).append("\n");
+ StringBuffer sb = new StringBuffer();
+
+ sb.append("[NAME]\n");
+ sb.append(" .option flags = ").append(HexDump.shortToHex(field_1_option_flag)).append("\n");
+ sb.append(" .keyboard shortcut = ").append(HexDump.byteToHex(field_2_keyboard_shortcut)).append("\n");
+ sb.append(" .length of the name = ").append(getNameTextLength()).append("\n");
+ sb.append(" .unused = ").append( field_5_index_to_sheet ).append("\n");
+ sb.append(" .index to sheet (1-based, 0=Global) = ").append( field_6_sheetNumber ).append("\n");
+ sb.append(" .Menu text length = ").append(field_14_custom_menu_text.length()).append("\n");
+ sb.append(" .Description text length= ").append(field_15_description_text.length()).append("\n");
+ sb.append(" .Help topic text length = ").append(field_16_help_topic_text.length()).append("\n");
+ sb.append(" .Status bar text length = ").append(field_17_status_bar_text.length()).append("\n");
+ sb.append(" .NameIsMultibyte = ").append(field_11_nameIsMultibyte).append("\n");
+ sb.append(" .Name (Unicode text) = ").append( getNameText() ).append("\n");
+ sb.append(" .Formula (nTokens=").append(field_13_name_definition.length).append("):") .append("\n");
+ for (int i = 0; i < field_13_name_definition.length; i++) {
+ Ptg ptg = field_13_name_definition[i];
+ sb.append(" " + ptg.toString()).append(ptg.getRVAType()).append("\n");
}
-
- buffer.append(" .Menu text (Unicode string without length field) = ").append( field_14_custom_menu_text )
- .append("\n");
- buffer.append(" .Description text (Unicode string without length field) = ").append( field_15_description_text )
- .append("\n");
- buffer.append(" .Help topic text (Unicode string without length field) = ").append( field_16_help_topic_text )
- .append("\n");
- buffer.append(" .Status bar text (Unicode string without length field) = ").append( field_17_status_bar_text )
- .append("\n");
- buffer.append("[/NAME]\n");
-
- return buffer.toString();
+
+ sb.append(" .Menu text = ").append(field_14_custom_menu_text).append("\n");
+ sb.append(" .Description text= ").append(field_15_description_text).append("\n");
+ sb.append(" .Help topic text = ").append(field_16_help_topic_text).append("\n");
+ sb.append(" .Status bar text = ").append(field_17_status_bar_text).append("\n");
+ sb.append("[/NAME]\n");
+
+ return sb.toString();
}
/**Creates a human readable name for built in types
* @return Unknown if the built-in name cannot be translated
*/
- protected String translateBuiltInName(byte name)
+ private static String translateBuiltInName(byte name)
{
switch (name)
{
case NameRecord.BUILTIN_CONSOLIDATE_AREA : return "Consolidate_Area";
case NameRecord.BUILTIN_CRITERIA : return "Criteria";
case NameRecord.BUILTIN_DATABASE : return "Database";
- case NameRecord.BUILTIN_DATA_FORM : return "Data_Form";
+ case NameRecord.BUILTIN_DATA_FORM : return "Data_Form";
case NameRecord.BUILTIN_PRINT_AREA : return "Print_Area";
case NameRecord.BUILTIN_PRINT_TITLE : return "Print_Titles";
case NameRecord.BUILTIN_RECORDER : return "Recorder";
case NameRecord.BUILTIN_SHEET_TITLE : return "Sheet_Title";
-
+ case NameRecord.BUILTIN_FILTER_DB : return "_FilterDatabase";
+
}
-
+
return "Unknown";
}
}
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
-import java.util.Stack;
import org.apache.poi.POIDocument;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.hssf.record.formula.Area3DPtg;
import org.apache.poi.hssf.record.formula.MemFuncPtg;
import org.apache.poi.hssf.record.formula.NameXPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.Ref3DPtg;
import org.apache.poi.hssf.record.formula.UnionPtg;
import org.apache.poi.hssf.usermodel.HSSFRow.MissingCellPolicy;
import org.apache.poi.hssf.util.CellReference;
* @return HSSFSheet representing the cloned sheet.
*/
- public HSSFSheet cloneSheet(int sheetNum) {
- validateSheetIndex(sheetNum);
- HSSFSheet srcSheet = (HSSFSheet) _sheets.get(sheetNum);
- String srcName = workbook.getSheetName(sheetNum);
+ public HSSFSheet cloneSheet(int sheetIndex) {
+ validateSheetIndex(sheetIndex);
+ HSSFSheet srcSheet = (HSSFSheet) _sheets.get(sheetIndex);
+ String srcName = workbook.getSheetName(sheetIndex);
HSSFSheet clonedSheet = srcSheet.cloneSheet(this);
clonedSheet.setSelected(false);
clonedSheet.setActive(false);
+ String name = getUniqueSheetName(srcName);
+ int newSheetIndex = _sheets.size();
_sheets.add(clonedSheet);
- int i = 1;
+ workbook.setSheetName(newSheetIndex, name);
+
+ // Check this sheet has an autofilter, (which has a built-in NameRecord at workbook level)
+ int filterDbNameIndex = findExistingBuiltinNameRecordIdx(sheetIndex, NameRecord.BUILTIN_FILTER_DB);
+ if (filterDbNameIndex >=0) {
+ NameRecord origNameRecord = workbook.getNameRecord(filterDbNameIndex);
+ // copy original formula but adjust 3D refs to the new external sheet index
+ int newExtSheetIx = getExternalSheetIndex(newSheetIndex);
+ Ptg[] ptgs = origNameRecord.getNameDefinition();
+ for (int i=0; i< ptgs.length; i++) {
+ Ptg ptg = ptgs[i];
+ ptg = ptg.copy();
+
+ if (ptg instanceof Area3DPtg) {
+ Area3DPtg a3p = (Area3DPtg) ptg;
+ a3p.setExternSheetIndex(newExtSheetIx);
+ } else if (ptg instanceof Ref3DPtg) {
+ Ref3DPtg r3p = (Ref3DPtg) ptg;
+ r3p.setExternSheetIndex(newExtSheetIx);
+ }
+ ptgs[i] = ptg;
+ }
+ NameRecord newNameRecord = workbook.createBuiltInName(NameRecord.BUILTIN_FILTER_DB, newSheetIndex+1);
+ newNameRecord.setNameDefinition(ptgs);
+ newNameRecord.setHidden(true);
+ HSSFName newName = new HSSFName(this, newNameRecord);
+ names.add(newName);
+ // TODO - when an Autofilter is present, there are some DrawingRecords which also need adjusting
+ // In particular, some IDs of some EscherSpRecords need changing. See bug 45720
+ }
+ // TODO - maybe same logic required for other/all built-in name records
+
+ return clonedSheet;
+ }
+
+ private String getUniqueSheetName(String srcName) {
+ int uniqueIndex = 2;
+ String baseName = srcName;
+ int bracketPos = srcName.lastIndexOf('(');
+ if (bracketPos > 0 && srcName.endsWith(")")) {
+ String suffix = srcName.substring(bracketPos + 1, srcName.length() - ")".length());
+ try {
+ uniqueIndex = Integer.parseInt(suffix.trim());
+ uniqueIndex++;
+ baseName=srcName.substring(0, bracketPos).trim();
+ } catch (NumberFormatException e) {
+ // contents of brackets not numeric
+ }
+ }
while (true) {
// Try and find the next sheet name that is unique
- String name = srcName;
- String index = Integer.toString(i++);
- if (name.length() + index.length() + 2 < 31) {
- name = name + "(" + index + ")";
+ String index = Integer.toString(uniqueIndex++);
+ String name;
+ if (baseName.length() + index.length() + 2 < 31) {
+ name = baseName + " (" + index + ")";
} else {
- name = name.substring(0, 31 - index.length() - 2) + "(" + index + ")";
+ name = baseName.substring(0, 31 - index.length() - 2) + "(" + index + ")";
}
//If the sheet name is unique, then set it otherwise move on to the next number.
if (workbook.getSheetIndex(name) == -1) {
- workbook.setSheetName(_sheets.size()-1, name);
- break;
+ return name;
}
}
- return clonedSheet;
}
/**
boolean removingRange =
startColumn == -1 && endColumn == -1 && startRow == -1 && endRow == -1;
- int rowColHeaderNameIndex = findExistingRowColHeaderNameRecordIdx(sheetIndex);
+ int rowColHeaderNameIndex = findExistingBuiltinNameRecordIdx(sheetIndex, NameRecord.BUILTIN_PRINT_TITLE);
if (removingRange) {
if (rowColHeaderNameIndex >= 0) {
workbook.removeName(rowColHeaderNameIndex);
isNewRecord = false;
}
- short definitionTextLength = settingRowAndColumn ? (short)0x001a : (short)0x000b;
- nameRecord.setDefinitionTextLength(definitionTextLength); // TODO - remove
-
- Stack ptgs = new Stack();
+ List temp = new ArrayList();
if (settingRowAndColumn) {
final int exprsSize = 2 * 11 + 1; // 2 * Area3DPtg.SIZE + UnionPtg.SIZE
- ptgs.add(new MemFuncPtg(exprsSize));
+ temp.add(new MemFuncPtg(exprsSize));
}
if (startColumn >= 0) {
Area3DPtg colArea = new Area3DPtg(0, MAX_ROW, startColumn, endColumn,
false, false, false, false, externSheetIndex);
- ptgs.add(colArea);
+ temp.add(colArea);
}
if (startRow >= 0) {
Area3DPtg rowArea = new Area3DPtg(startRow, endRow, 0, MAX_COLUMN,
false, false, false, false, externSheetIndex);
- ptgs.add(rowArea);
+ temp.add(rowArea);
}
- if (settingRowAndColumn)
- {
- ptgs.add(UnionPtg.instance);
+ if (settingRowAndColumn) {
+ temp.add(UnionPtg.instance);
}
+ Ptg[] ptgs = new Ptg[temp.size()];
+ temp.toArray(ptgs);
nameRecord.setNameDefinition(ptgs);
if (isNewRecord)
}
- private int findExistingRowColHeaderNameRecordIdx(int sheetIndex) {
+ private int findExistingBuiltinNameRecordIdx(int sheetIndex, byte builtinCode) {
for(int defNameIndex =0; defNameIndex<names.size(); defNameIndex++) {
NameRecord r = workbook.getNameRecord(defNameIndex);
if (r == null) {
throw new RuntimeException("Unable to find all defined names to iterate over");
}
- if (!isRowColHeaderRecord( r )) {
+ if (!r.isBuiltInName() || r.getBuiltInName() != builtinCode) {
continue;
}
if(r.getSheetNumber() == 0) {
return -1;
}
- private static boolean isRowColHeaderRecord(NameRecord r) {
- return r.isBuiltInName() && r.getBuiltInName() == NameRecord.BUILTIN_PRINT_TITLE;
- }
-
/**
* create a new Font and add it to the workbook's font table
* @return new font object