mirror of https://github.com/apache/poi.git
Initial work on bug 45720 - copy 'FilterDatabase' named record when cloning sheets. Some clean-up in NameRecord.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@691740 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a1a888f7f7
commit
df610f03ef
|
@ -17,9 +17,8 @@
|
||||||
|
|
||||||
package org.apache.poi.hssf.record;
|
package org.apache.poi.hssf.record;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
import org.apache.poi.hssf.model.FormulaParser;
|
import org.apache.poi.hssf.model.FormulaParser;
|
||||||
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
||||||
|
@ -44,50 +43,32 @@ import org.apache.poi.util.StringUtil;
|
||||||
*/
|
*/
|
||||||
public final class NameRecord extends Record {
|
public final class NameRecord extends Record {
|
||||||
public final static short sid = 0x0018;
|
public final static short sid = 0x0018;
|
||||||
/**Included for completeness sake, not implemented
|
/**Included for completeness sake, not implemented */
|
||||||
*/
|
public final static byte BUILTIN_CONSOLIDATE_AREA = 1;
|
||||||
public final static byte BUILTIN_CONSOLIDATE_AREA = (byte)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;
|
||||||
|
|
||||||
/**Included for completeness sake, not implemented
|
public final static byte BUILTIN_PRINT_AREA = 6;
|
||||||
*/
|
public final static byte BUILTIN_PRINT_TITLE = 7;
|
||||||
public final static byte BUILTIN_AUTO_OPEN = (byte)2;
|
|
||||||
|
|
||||||
/**Included for completeness sake, not implemented
|
/**Included for completeness sake, not implemented */
|
||||||
*/
|
public final static byte BUILTIN_RECORDER = 8;
|
||||||
public final static byte BUILTIN_AUTO_CLOSE = (byte)3;
|
/**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;
|
||||||
|
|
||||||
/**Included for completeness sake, not implemented
|
public final static byte BUILTIN_FILTER_DB = 13;
|
||||||
*/
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
|
|
||||||
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 {
|
private static final class Option {
|
||||||
public static final int OPT_HIDDEN_NAME = 0x0001;
|
public static final int OPT_HIDDEN_NAME = 0x0001;
|
||||||
|
@ -101,19 +82,13 @@ public final class NameRecord extends Record {
|
||||||
|
|
||||||
private short field_1_option_flag;
|
private short field_1_option_flag;
|
||||||
private byte field_2_keyboard_shortcut;
|
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
|
private short field_5_index_to_sheet; // unused: see field_6
|
||||||
/** the one based sheet number. Zero if this is a global name */
|
/** the one based sheet number. Zero if this is a global name */
|
||||||
private int field_6_sheetNumber;
|
private int field_6_sheetNumber;
|
||||||
private byte field_7_length_custom_menu;
|
private boolean field_11_nameIsMultibyte;
|
||||||
private byte field_8_length_description_text;
|
private byte field_12_built_in_code;
|
||||||
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 String field_12_name_text;
|
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_14_custom_menu_text;
|
||||||
private String field_15_description_text;
|
private String field_15_description_text;
|
||||||
private String field_16_help_topic_text;
|
private String field_16_help_topic_text;
|
||||||
|
@ -122,13 +97,13 @@ public final class NameRecord extends Record {
|
||||||
|
|
||||||
/** Creates new NameRecord */
|
/** Creates new NameRecord */
|
||||||
public NameRecord() {
|
public NameRecord() {
|
||||||
field_13_name_definition = new Stack();
|
field_13_name_definition = Ptg.EMPTY_PTG_ARRAY;
|
||||||
|
|
||||||
field_12_name_text = new String();
|
field_12_name_text = "";
|
||||||
field_14_custom_menu_text = new String();
|
field_14_custom_menu_text = "";
|
||||||
field_15_description_text = new String();
|
field_15_description_text = "";
|
||||||
field_16_help_topic_text = new String();
|
field_16_help_topic_text = "";
|
||||||
field_17_status_bar_text = new String();
|
field_17_status_bar_text = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,18 +122,9 @@ public final class NameRecord extends Record {
|
||||||
public NameRecord(byte builtin, int sheetNumber)
|
public NameRecord(byte builtin, int sheetNumber)
|
||||||
{
|
{
|
||||||
this();
|
this();
|
||||||
this.field_12_builtIn_name = builtin;
|
field_12_built_in_code = builtin;
|
||||||
this.setOptionFlag((short)(this.field_1_option_flag | Option.OPT_BUILTIN));
|
setOptionFlag((short)(field_1_option_flag | Option.OPT_BUILTIN));
|
||||||
this.setNameTextLength((byte)1);
|
|
||||||
field_6_sheetNumber = sheetNumber; //the extern sheets are set through references
|
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
|
/** sets the option flag for the named range
|
||||||
|
@ -176,31 +142,6 @@ public final class NameRecord extends Record {
|
||||||
field_2_keyboard_shortcut = shortcut;
|
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
|
* 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
|
||||||
|
@ -226,49 +167,12 @@ public final class NameRecord extends Record {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** 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
|
/** sets the name of the named range
|
||||||
* @param name named range name
|
* @param name named range name
|
||||||
*/
|
*/
|
||||||
public void setNameText(String name){
|
public void setNameText(String name){
|
||||||
field_12_name_text = name;
|
field_12_name_text = name;
|
||||||
setCompressedUnicodeFlag(
|
field_11_nameIsMultibyte = StringUtil.hasMultibyte(name);
|
||||||
StringUtil.hasMultibyte(name) ? (byte)1 : (byte)0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** sets the custom menu text
|
/** sets the custom menu text
|
||||||
|
@ -317,68 +221,11 @@ public final class NameRecord extends Record {
|
||||||
* gets the name length, in characters
|
* gets the name length, in characters
|
||||||
* @return name length
|
* @return name length
|
||||||
*/
|
*/
|
||||||
public byte getNameTextLength(){
|
private int getNameTextLength(){
|
||||||
return field_3_length_name_text;
|
if (isBuiltInName()) {
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
return field_12_name_text.length();
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -388,6 +235,13 @@ public final class NameRecord extends Record {
|
||||||
public boolean isHiddenName() {
|
public boolean isHiddenName() {
|
||||||
return (field_1_option_flag & Option.OPT_HIDDEN_NAME) != 0;
|
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
|
* @return true if name is a function
|
||||||
*/
|
*/
|
||||||
|
@ -419,7 +273,7 @@ public final class NameRecord extends Record {
|
||||||
*/
|
*/
|
||||||
public boolean isBuiltInName()
|
public boolean isBuiltInName()
|
||||||
{
|
{
|
||||||
return ((this.field_1_option_flag & Option.OPT_BUILTIN) != 0);
|
return ((field_1_option_flag & Option.OPT_BUILTIN) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -428,7 +282,7 @@ public final class NameRecord extends Record {
|
||||||
*/
|
*/
|
||||||
public String getNameText(){
|
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
|
/** Gets the Built In Name
|
||||||
|
@ -436,19 +290,19 @@ public final class NameRecord extends Record {
|
||||||
*/
|
*/
|
||||||
public byte getBuiltInName()
|
public byte getBuiltInName()
|
||||||
{
|
{
|
||||||
return this.field_12_builtIn_name;
|
return field_12_built_in_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** gets the definition, reference (Formula)
|
/** 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() {
|
public Ptg[] getNameDefinition() {
|
||||||
return field_13_name_definition;
|
return (Ptg[]) field_13_name_definition.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNameDefinition(Stack nameDefinition) {
|
public void setNameDefinition(Ptg[] ptgs) {
|
||||||
field_13_name_definition = nameDefinition;
|
field_13_name_definition = (Ptg[]) ptgs.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** get the custom menu text
|
/** get the custom menu text
|
||||||
|
@ -491,6 +345,7 @@ public final class NameRecord extends Record {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called by the class that is responsible for writing this sucker.
|
* called by the class that is responsible for writing this sucker.
|
||||||
* Subclasses should implement this so that their data is passed back in a
|
* Subclasses should implement this so that their data is passed back in a
|
||||||
|
@ -498,109 +353,107 @@ public final class NameRecord extends Record {
|
||||||
* @param data byte array containing instance data
|
* @param data byte array containing instance data
|
||||||
* @return number of bytes written
|
* @return number of bytes written
|
||||||
*/
|
*/
|
||||||
public int serialize( int offset, byte[] data )
|
public int serialize( int offset, byte[] data ) {
|
||||||
{
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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.putShort(data, 0 + offset, sid);
|
||||||
short size = (short)( 15 + getTextsLength() + getNameDefinitionSize());
|
LittleEndian.putUShort(data, 2 + offset, dataSize);
|
||||||
LittleEndian.putShort( data, 2 + offset, size );
|
|
||||||
// size defined below
|
// size defined below
|
||||||
LittleEndian.putShort(data, 4 + offset, getOptionFlag());
|
LittleEndian.putShort(data, 4 + offset, getOptionFlag());
|
||||||
data[6 + offset] = getKeyboardShortcut();
|
LittleEndian.putByte(data, 6 + offset, getKeyboardShortcut());
|
||||||
data[7 + offset] = getNameTextLength();
|
LittleEndian.putByte(data, 7 + offset, getNameTextLength());
|
||||||
LittleEndian.putShort( data, 8 + offset, getDefinitionLength() );
|
// Note -
|
||||||
LittleEndian.putShort( data, 10 + offset, getUnused() );
|
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.putUShort(data, 12 + offset, field_6_sheetNumber);
|
||||||
data[14 + offset] = getCustomMenuLength();
|
LittleEndian.putByte(data, 14 + offset, field_7_length_custom_menu);
|
||||||
data[15 + offset] = getDescriptionTextLength();
|
LittleEndian.putByte(data, 15 + offset, field_8_length_description_text);
|
||||||
data[16 + offset] = getHelpTopicLength();
|
LittleEndian.putByte(data, 16 + offset, field_9_length_help_topic_text);
|
||||||
data[17 + offset] = getStatusBarLength();
|
LittleEndian.putByte(data, 17 + offset, field_10_length_status_bar_text);
|
||||||
data[18 + offset] = getCompressedUnicodeFlag();
|
LittleEndian.putByte(data, 18 + offset, field_11_nameIsMultibyte ? 1 : 0);
|
||||||
|
int pos = 19 + offset;
|
||||||
|
|
||||||
int start_of_name_definition = 19 + field_3_length_name_text;
|
if (isBuiltInName()) {
|
||||||
|
|
||||||
if (this.isBuiltInName()) {
|
|
||||||
//can send the builtin name directly in
|
//can send the builtin name directly in
|
||||||
data [19 + offset] = this.getBuiltInName();
|
LittleEndian.putByte(data, pos, field_12_built_in_code);
|
||||||
} else if ((this.getCompressedUnicodeFlag() & 0x01) == 1) {
|
|
||||||
StringUtil.putUnicodeLE( getNameText(), data, 19 + offset );
|
|
||||||
start_of_name_definition = 19 + (2 * field_3_length_name_text);
|
|
||||||
} else {
|
} else {
|
||||||
StringUtil.putCompressedUnicode( getNameText(), data, 19 + offset );
|
String nameText = field_12_name_text;
|
||||||
|
if (field_11_nameIsMultibyte) {
|
||||||
|
StringUtil.putUnicodeLE(nameText, data, pos);
|
||||||
|
} else {
|
||||||
|
StringUtil.putCompressedUnicode(nameText, data, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Ptg.serializePtgStack(field_13_name_definition, data, start_of_name_definition + offset );
|
|
||||||
|
|
||||||
|
|
||||||
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();
|
|
||||||
/* } */
|
|
||||||
}
|
}
|
||||||
|
pos += rawNameSize;
|
||||||
|
|
||||||
/**
|
Ptg.serializePtgs(field_13_name_definition, data, pos);
|
||||||
* Gets the length of all texts, in bytes
|
pos += formulaTotalSize;
|
||||||
* @return total length
|
|
||||||
*/
|
|
||||||
public int getTextsLength(){
|
|
||||||
int result;
|
|
||||||
|
|
||||||
result = getRawNameTextLength() + getDescriptionTextLength() +
|
StringUtil.putCompressedUnicode( getCustomMenuText(), data, pos);
|
||||||
getHelpTopicLength() + getStatusBarLength();
|
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 result;
|
return 4 + dataSize;
|
||||||
}
|
}
|
||||||
|
private int getNameRawSize() {
|
||||||
private int getNameDefinitionSize() {
|
if (isBuiltInName()) {
|
||||||
int result = 0;
|
return 1;
|
||||||
List list = field_13_name_definition;
|
|
||||||
|
|
||||||
for (int k = 0; k < list.size(); k++)
|
|
||||||
{
|
|
||||||
Ptg ptg = ( Ptg ) list.get(k);
|
|
||||||
|
|
||||||
result += ptg.getSize();
|
|
||||||
}
|
}
|
||||||
return result;
|
int nChars = field_12_name_text.length();
|
||||||
|
if(field_11_nameIsMultibyte) {
|
||||||
|
return 2 * nChars;
|
||||||
|
}
|
||||||
|
return nChars;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** returns the record size
|
/** returns the record size
|
||||||
*/
|
*/
|
||||||
public int getRecordSize(){
|
public int getRecordSize(){
|
||||||
int result;
|
return 4 // sid + size
|
||||||
|
+ 15 // 4 shorts + 7 bytes
|
||||||
result = 19 + getTextsLength() + getNameDefinitionSize();
|
+ getNameRawSize()
|
||||||
|
+ field_14_custom_menu_text.length()
|
||||||
|
+ field_15_description_text.length()
|
||||||
return result;
|
+ field_16_help_topic_text.length()
|
||||||
|
+ field_17_status_bar_text.length()
|
||||||
|
+ Ptg.getEncodedSize(field_13_name_definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** gets the extern sheet number
|
/** gets the extern sheet number
|
||||||
* @return extern sheet index
|
* @return extern sheet index
|
||||||
*/
|
*/
|
||||||
public short getExternSheetNumber(){
|
public short getExternSheetNumber(){
|
||||||
if (field_13_name_definition == null || field_13_name_definition.isEmpty()) return 0;
|
if (field_13_name_definition.length < 1) {
|
||||||
Ptg ptg = (Ptg) field_13_name_definition.peek();
|
return 0;
|
||||||
short result = 0;
|
}
|
||||||
|
Ptg ptg = field_13_name_definition[0];
|
||||||
|
|
||||||
if (ptg.getClass() == Area3DPtg.class){
|
if (ptg.getClass() == Area3DPtg.class){
|
||||||
result = ((Area3DPtg) ptg).getExternSheetIndex();
|
return ((Area3DPtg) ptg).getExternSheetIndex();
|
||||||
|
|
||||||
} else if (ptg.getClass() == Ref3DPtg.class){
|
|
||||||
result = ((Ref3DPtg) ptg).getExternSheetIndex();
|
|
||||||
}
|
}
|
||||||
|
if (ptg.getClass() == Ref3DPtg.class){
|
||||||
return result;
|
return ((Ref3DPtg) ptg).getExternSheetIndex();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** sets the extern sheet number
|
/** sets the extern sheet number
|
||||||
|
@ -609,11 +462,13 @@ public final class NameRecord extends Record {
|
||||||
public void setExternSheetNumber(short externSheetNumber){
|
public void setExternSheetNumber(short externSheetNumber){
|
||||||
Ptg ptg;
|
Ptg ptg;
|
||||||
|
|
||||||
if (field_13_name_definition == null || field_13_name_definition.isEmpty()){
|
if (field_13_name_definition.length < 1){
|
||||||
field_13_name_definition = new Stack();
|
|
||||||
ptg = createNewPtg();
|
ptg = createNewPtg();
|
||||||
|
field_13_name_definition = new Ptg[] {
|
||||||
|
ptg,
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
ptg = (Ptg) field_13_name_definition.peek();
|
ptg = field_13_name_definition[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptg.getClass() == Area3DPtg.class){
|
if (ptg.getClass() == Area3DPtg.class){
|
||||||
|
@ -625,11 +480,8 @@ public final class NameRecord extends Record {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Ptg createNewPtg(){
|
private static Ptg createNewPtg(){
|
||||||
Ptg ptg = new Area3DPtg("A1", 0); // TODO - change to not be partially initialised
|
return new Area3DPtg("A1", 0); // TODO - change to not be partially initialised
|
||||||
field_13_name_definition.push(ptg);
|
|
||||||
|
|
||||||
return ptg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** gets the reference , the area only (range)
|
/** gets the reference , the area only (range)
|
||||||
|
@ -646,16 +498,14 @@ public final class NameRecord extends Record {
|
||||||
//Trying to find if what ptg do we need
|
//Trying to find if what ptg do we need
|
||||||
RangeAddress ra = new RangeAddress(ref);
|
RangeAddress ra = new RangeAddress(ref);
|
||||||
Ptg oldPtg;
|
Ptg oldPtg;
|
||||||
Ptg ptg;
|
|
||||||
|
|
||||||
if (field_13_name_definition==null ||field_13_name_definition.isEmpty()){
|
if (field_13_name_definition.length < 1){
|
||||||
field_13_name_definition = new Stack();
|
|
||||||
oldPtg = createNewPtg();
|
oldPtg = createNewPtg();
|
||||||
} else {
|
} else {
|
||||||
//Trying to find extern sheet index
|
//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;
|
short externSheetIndex = 0;
|
||||||
|
|
||||||
if (oldPtg.getClass() == Area3DPtg.class){
|
if (oldPtg.getClass() == Area3DPtg.class){
|
||||||
|
@ -667,29 +517,27 @@ public final class NameRecord extends Record {
|
||||||
|
|
||||||
if (ra.hasRange()) {
|
if (ra.hasRange()) {
|
||||||
// Is it contiguous or not?
|
// Is it contiguous or not?
|
||||||
AreaReference[] refs =
|
AreaReference[] refs = AreaReference.generateContiguous(ref);
|
||||||
AreaReference.generateContiguous(ref);
|
|
||||||
this.setDefinitionTextLength((short)0);
|
|
||||||
|
|
||||||
// Add the area reference(s)
|
// Add the area reference(s)
|
||||||
for(int i=0; i<refs.length; i++) {
|
for(int i=0; i<refs.length; i++) {
|
||||||
ptg = new Area3DPtg(refs[i].formatAsString(), externSheetIndex);
|
Ptg ptg = new Area3DPtg(refs[i].formatAsString(), externSheetIndex);
|
||||||
field_13_name_definition.push(ptg);
|
temp.add(ptg);
|
||||||
this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) );
|
|
||||||
}
|
}
|
||||||
// And then a union if we had more than one area
|
// And then a union if we had more than one area
|
||||||
if(refs.length > 1) {
|
if(refs.length > 1) {
|
||||||
ptg = UnionPtg.instance;
|
Ptg ptg = UnionPtg.instance;
|
||||||
field_13_name_definition.push(ptg);
|
temp.add(ptg);
|
||||||
this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) );
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ptg = new Ref3DPtg();
|
Ptg ptg = new Ref3DPtg();
|
||||||
((Ref3DPtg) ptg).setExternSheetIndex(externSheetIndex);
|
((Ref3DPtg) ptg).setExternSheetIndex(externSheetIndex);
|
||||||
((Ref3DPtg) ptg).setArea(ref);
|
((Ref3DPtg) ptg).setArea(ref);
|
||||||
field_13_name_definition.push(ptg);
|
temp.add(ptg);
|
||||||
this.setDefinitionTextLength((short)ptg.getSize());
|
|
||||||
}
|
}
|
||||||
|
Ptg[] ptgs = new Ptg[temp.size()];
|
||||||
|
temp.toArray(ptgs);
|
||||||
|
field_13_name_definition = ptgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -701,38 +549,34 @@ public final class NameRecord extends Record {
|
||||||
protected void fillFields(RecordInputStream in) {
|
protected void fillFields(RecordInputStream in) {
|
||||||
field_1_option_flag = in.readShort();
|
field_1_option_flag = in.readShort();
|
||||||
field_2_keyboard_shortcut = in.readByte();
|
field_2_keyboard_shortcut = in.readByte();
|
||||||
field_3_length_name_text = in.readByte();
|
int field_3_length_name_text = in.readByte();
|
||||||
field_4_length_name_definition = in.readShort();
|
int field_4_length_name_definition = in.readShort();
|
||||||
field_5_index_to_sheet = in.readShort();
|
field_5_index_to_sheet = in.readShort();
|
||||||
field_6_sheetNumber = in.readUShort();
|
field_6_sheetNumber = in.readUShort();
|
||||||
field_7_length_custom_menu = in.readByte();
|
int field_7_length_custom_menu = in.readUByte();
|
||||||
field_8_length_description_text = in.readByte();
|
int field_8_length_description_text = in.readUByte();
|
||||||
field_9_length_help_topic_text = in.readByte();
|
int field_9_length_help_topic_text = in.readUByte();
|
||||||
field_10_length_status_bar_text = in.readByte();
|
int field_10_length_status_bar_text = in.readUByte();
|
||||||
|
|
||||||
//store the name in byte form if it's a builtin name
|
//store the name in byte form if it's a built-in name
|
||||||
field_11_compressed_unicode_flag= in.readByte();
|
field_11_nameIsMultibyte = (in.readByte() != 0);
|
||||||
if (this.isBuiltInName()) {
|
if (isBuiltInName()) {
|
||||||
field_12_builtIn_name = in.readByte();
|
field_12_built_in_code = in.readByte();
|
||||||
} else {
|
} else {
|
||||||
if (field_11_compressed_unicode_flag == 1) {
|
if (field_11_nameIsMultibyte) {
|
||||||
field_12_name_text = in.readUnicodeLEString(field_3_length_name_text);
|
field_12_name_text = in.readUnicodeLEString(field_3_length_name_text);
|
||||||
} else {
|
} else {
|
||||||
field_12_name_text = in.readCompressedUnicode(field_3_length_name_text);
|
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???
|
//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_14_custom_menu_text = in.readCompressedUnicode(field_7_length_custom_menu);
|
||||||
|
field_15_description_text = in.readCompressedUnicode(field_8_length_description_text);
|
||||||
field_15_description_text = in.readCompressedUnicode(LittleEndian.ubyteToInt(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);
|
||||||
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));
|
|
||||||
/*} */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -792,63 +636,40 @@ public final class NameRecord extends Record {
|
||||||
3B 00 00 07 00 07 00 00 00 FF 00 ]
|
3B 00 00 07 00 07 00 00 00 FF 00 ]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @see Object#toString()
|
|
||||||
*/
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
buffer.append("[NAME]\n");
|
sb.append("[NAME]\n");
|
||||||
buffer.append(" .option flags = ").append( HexDump.toHex( field_1_option_flag ) )
|
sb.append(" .option flags = ").append(HexDump.shortToHex(field_1_option_flag)).append("\n");
|
||||||
.append("\n");
|
sb.append(" .keyboard shortcut = ").append(HexDump.byteToHex(field_2_keyboard_shortcut)).append("\n");
|
||||||
buffer.append(" .keyboard shortcut = ").append( HexDump.toHex( field_2_keyboard_shortcut ) )
|
sb.append(" .length of the name = ").append(getNameTextLength()).append("\n");
|
||||||
.append("\n");
|
sb.append(" .unused = ").append( field_5_index_to_sheet ).append("\n");
|
||||||
buffer.append(" .length of the name = ").append( field_3_length_name_text )
|
sb.append(" .index to sheet (1-based, 0=Global) = ").append( field_6_sheetNumber ).append("\n");
|
||||||
.append("\n");
|
sb.append(" .Menu text length = ").append(field_14_custom_menu_text.length()).append("\n");
|
||||||
buffer.append(" .size of the formula data = ").append( field_4_length_name_definition )
|
sb.append(" .Description text length= ").append(field_15_description_text.length()).append("\n");
|
||||||
.append("\n");
|
sb.append(" .Help topic text length = ").append(field_16_help_topic_text.length()).append("\n");
|
||||||
buffer.append(" .unused = ").append( field_5_index_to_sheet )
|
sb.append(" .Status bar text length = ").append(field_17_status_bar_text.length()).append("\n");
|
||||||
.append("\n");
|
sb.append(" .NameIsMultibyte = ").append(field_11_nameIsMultibyte).append("\n");
|
||||||
buffer.append(" .index to sheet (1-based, 0=Global) = ").append( field_6_sheetNumber )
|
sb.append(" .Name (Unicode text) = ").append( getNameText() ).append("\n");
|
||||||
.append("\n");
|
sb.append(" .Formula (nTokens=").append(field_13_name_definition.length).append("):") .append("\n");
|
||||||
buffer.append(" .Length of menu text (character count) = ").append( field_7_length_custom_menu )
|
for (int i = 0; i < field_13_name_definition.length; i++) {
|
||||||
.append("\n");
|
Ptg ptg = field_13_name_definition[i];
|
||||||
buffer.append(" .Length of description text (character count) = ").append( field_8_length_description_text )
|
sb.append(" " + ptg.toString()).append(ptg.getRVAType()).append("\n");
|
||||||
.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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.append(" .Menu text (Unicode string without length field) = ").append( field_14_custom_menu_text )
|
sb.append(" .Menu text = ").append(field_14_custom_menu_text).append("\n");
|
||||||
.append("\n");
|
sb.append(" .Description text= ").append(field_15_description_text).append("\n");
|
||||||
buffer.append(" .Description text (Unicode string without length field) = ").append( field_15_description_text )
|
sb.append(" .Help topic text = ").append(field_16_help_topic_text).append("\n");
|
||||||
.append("\n");
|
sb.append(" .Status bar text = ").append(field_17_status_bar_text).append("\n");
|
||||||
buffer.append(" .Help topic text (Unicode string without length field) = ").append( field_16_help_topic_text )
|
sb.append("[/NAME]\n");
|
||||||
.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();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Creates a human readable name for built in types
|
/**Creates a human readable name for built in types
|
||||||
* @return Unknown if the built-in name cannot be translated
|
* @return Unknown if the built-in name cannot be translated
|
||||||
*/
|
*/
|
||||||
protected String translateBuiltInName(byte name)
|
private static String translateBuiltInName(byte name)
|
||||||
{
|
{
|
||||||
switch (name)
|
switch (name)
|
||||||
{
|
{
|
||||||
|
@ -864,6 +685,7 @@ public final class NameRecord extends Record {
|
||||||
case NameRecord.BUILTIN_PRINT_TITLE : return "Print_Titles";
|
case NameRecord.BUILTIN_PRINT_TITLE : return "Print_Titles";
|
||||||
case NameRecord.BUILTIN_RECORDER : return "Recorder";
|
case NameRecord.BUILTIN_RECORDER : return "Recorder";
|
||||||
case NameRecord.BUILTIN_SHEET_TITLE : return "Sheet_Title";
|
case NameRecord.BUILTIN_SHEET_TITLE : return "Sheet_Title";
|
||||||
|
case NameRecord.BUILTIN_FILTER_DB : return "_FilterDatabase";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ public final class Ref3DPtg extends OperandPtg {
|
||||||
private static final BitField colRelative = BitFieldFactory.getInstance(0x4000);
|
private static final BitField colRelative = BitFieldFactory.getInstance(0x4000);
|
||||||
|
|
||||||
private final static int SIZE = 7; // 6 + 1 for Ptg
|
private final static int SIZE = 7; // 6 + 1 for Ptg
|
||||||
private short field_1_index_extern_sheet;
|
private int field_1_index_extern_sheet;
|
||||||
/** The row index - zero based unsigned 16 bit value */
|
/** The row index - zero based unsigned 16 bit value */
|
||||||
private int field_2_row;
|
private int field_2_row;
|
||||||
/** Field 2
|
/** Field 2
|
||||||
|
@ -93,10 +93,10 @@ public final class Ref3DPtg extends OperandPtg {
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getExternSheetIndex(){
|
public short getExternSheetIndex(){
|
||||||
return field_1_index_extern_sheet;
|
return (short)field_1_index_extern_sheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setExternSheetIndex(short index){
|
public void setExternSheetIndex(int index){
|
||||||
field_1_index_extern_sheet = index;
|
field_1_index_extern_sheet = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,6 @@ public final class HSSFName {
|
||||||
*/
|
*/
|
||||||
public void setNameName(String nameName){
|
public void setNameName(String nameName){
|
||||||
_definedNameRec.setNameText(nameName);
|
_definedNameRec.setNameText(nameName);
|
||||||
_definedNameRec.setNameTextLength((byte)nameName.length());
|
|
||||||
Workbook wb = _book.getWorkbook();
|
Workbook wb = _book.getWorkbook();
|
||||||
|
|
||||||
//Check to ensure no other names have the same case-insensitive name
|
//Check to ensure no other names have the same case-insensitive name
|
||||||
|
|
|
@ -27,7 +27,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
import org.apache.poi.POIDocument;
|
import org.apache.poi.POIDocument;
|
||||||
import org.apache.poi.ddf.EscherBSERecord;
|
import org.apache.poi.ddf.EscherBSERecord;
|
||||||
|
@ -55,6 +54,8 @@ import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
|
||||||
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
||||||
import org.apache.poi.hssf.record.formula.MemFuncPtg;
|
import org.apache.poi.hssf.record.formula.MemFuncPtg;
|
||||||
import org.apache.poi.hssf.record.formula.NameXPtg;
|
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.record.formula.UnionPtg;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFRow.MissingCellPolicy;
|
import org.apache.poi.hssf.usermodel.HSSFRow.MissingCellPolicy;
|
||||||
import org.apache.poi.hssf.util.CellReference;
|
import org.apache.poi.hssf.util.CellReference;
|
||||||
|
@ -666,33 +667,81 @@ public class HSSFWorkbook extends POIDocument
|
||||||
* @return HSSFSheet representing the cloned sheet.
|
* @return HSSFSheet representing the cloned sheet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public HSSFSheet cloneSheet(int sheetNum) {
|
public HSSFSheet cloneSheet(int sheetIndex) {
|
||||||
validateSheetIndex(sheetNum);
|
validateSheetIndex(sheetIndex);
|
||||||
HSSFSheet srcSheet = (HSSFSheet) _sheets.get(sheetNum);
|
HSSFSheet srcSheet = (HSSFSheet) _sheets.get(sheetIndex);
|
||||||
String srcName = workbook.getSheetName(sheetNum);
|
String srcName = workbook.getSheetName(sheetIndex);
|
||||||
HSSFSheet clonedSheet = srcSheet.cloneSheet(this);
|
HSSFSheet clonedSheet = srcSheet.cloneSheet(this);
|
||||||
clonedSheet.setSelected(false);
|
clonedSheet.setSelected(false);
|
||||||
clonedSheet.setActive(false);
|
clonedSheet.setActive(false);
|
||||||
|
|
||||||
|
String name = getUniqueSheetName(srcName);
|
||||||
|
int newSheetIndex = _sheets.size();
|
||||||
_sheets.add(clonedSheet);
|
_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) {
|
while (true) {
|
||||||
// Try and find the next sheet name that is unique
|
// Try and find the next sheet name that is unique
|
||||||
String name = srcName;
|
String index = Integer.toString(uniqueIndex++);
|
||||||
String index = Integer.toString(i++);
|
String name;
|
||||||
if (name.length() + index.length() + 2 < 31) {
|
if (baseName.length() + index.length() + 2 < 31) {
|
||||||
name = name + "(" + index + ")";
|
name = baseName + " (" + index + ")";
|
||||||
} else {
|
} 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 the sheet name is unique, then set it otherwise move on to the next number.
|
||||||
if (workbook.getSheetIndex(name) == -1) {
|
if (workbook.getSheetIndex(name) == -1) {
|
||||||
workbook.setSheetName(_sheets.size()-1, name);
|
return name;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return clonedSheet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -901,7 +950,7 @@ public class HSSFWorkbook extends POIDocument
|
||||||
boolean removingRange =
|
boolean removingRange =
|
||||||
startColumn == -1 && endColumn == -1 && startRow == -1 && endRow == -1;
|
startColumn == -1 && endColumn == -1 && startRow == -1 && endRow == -1;
|
||||||
|
|
||||||
int rowColHeaderNameIndex = findExistingRowColHeaderNameRecordIdx(sheetIndex);
|
int rowColHeaderNameIndex = findExistingBuiltinNameRecordIdx(sheetIndex, NameRecord.BUILTIN_PRINT_TITLE);
|
||||||
if (removingRange) {
|
if (removingRange) {
|
||||||
if (rowColHeaderNameIndex >= 0) {
|
if (rowColHeaderNameIndex >= 0) {
|
||||||
workbook.removeName(rowColHeaderNameIndex);
|
workbook.removeName(rowColHeaderNameIndex);
|
||||||
|
@ -919,29 +968,27 @@ public class HSSFWorkbook extends POIDocument
|
||||||
isNewRecord = false;
|
isNewRecord = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
short definitionTextLength = settingRowAndColumn ? (short)0x001a : (short)0x000b;
|
List temp = new ArrayList();
|
||||||
nameRecord.setDefinitionTextLength(definitionTextLength); // TODO - remove
|
|
||||||
|
|
||||||
Stack ptgs = new Stack();
|
|
||||||
|
|
||||||
if (settingRowAndColumn) {
|
if (settingRowAndColumn) {
|
||||||
final int exprsSize = 2 * 11 + 1; // 2 * Area3DPtg.SIZE + UnionPtg.SIZE
|
final int exprsSize = 2 * 11 + 1; // 2 * Area3DPtg.SIZE + UnionPtg.SIZE
|
||||||
ptgs.add(new MemFuncPtg(exprsSize));
|
temp.add(new MemFuncPtg(exprsSize));
|
||||||
}
|
}
|
||||||
if (startColumn >= 0) {
|
if (startColumn >= 0) {
|
||||||
Area3DPtg colArea = new Area3DPtg(0, MAX_ROW, startColumn, endColumn,
|
Area3DPtg colArea = new Area3DPtg(0, MAX_ROW, startColumn, endColumn,
|
||||||
false, false, false, false, externSheetIndex);
|
false, false, false, false, externSheetIndex);
|
||||||
ptgs.add(colArea);
|
temp.add(colArea);
|
||||||
}
|
}
|
||||||
if (startRow >= 0) {
|
if (startRow >= 0) {
|
||||||
Area3DPtg rowArea = new Area3DPtg(startRow, endRow, 0, MAX_COLUMN,
|
Area3DPtg rowArea = new Area3DPtg(startRow, endRow, 0, MAX_COLUMN,
|
||||||
false, false, false, false, externSheetIndex);
|
false, false, false, false, externSheetIndex);
|
||||||
ptgs.add(rowArea);
|
temp.add(rowArea);
|
||||||
}
|
}
|
||||||
if (settingRowAndColumn)
|
if (settingRowAndColumn) {
|
||||||
{
|
temp.add(UnionPtg.instance);
|
||||||
ptgs.add(UnionPtg.instance);
|
|
||||||
}
|
}
|
||||||
|
Ptg[] ptgs = new Ptg[temp.size()];
|
||||||
|
temp.toArray(ptgs);
|
||||||
nameRecord.setNameDefinition(ptgs);
|
nameRecord.setNameDefinition(ptgs);
|
||||||
|
|
||||||
if (isNewRecord)
|
if (isNewRecord)
|
||||||
|
@ -957,13 +1004,13 @@ public class HSSFWorkbook extends POIDocument
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private int findExistingRowColHeaderNameRecordIdx(int sheetIndex) {
|
private int findExistingBuiltinNameRecordIdx(int sheetIndex, byte builtinCode) {
|
||||||
for(int defNameIndex =0; defNameIndex<names.size(); defNameIndex++) {
|
for(int defNameIndex =0; defNameIndex<names.size(); defNameIndex++) {
|
||||||
NameRecord r = workbook.getNameRecord(defNameIndex);
|
NameRecord r = workbook.getNameRecord(defNameIndex);
|
||||||
if (r == null) {
|
if (r == null) {
|
||||||
throw new RuntimeException("Unable to find all defined names to iterate over");
|
throw new RuntimeException("Unable to find all defined names to iterate over");
|
||||||
}
|
}
|
||||||
if (!isRowColHeaderRecord( r )) {
|
if (!r.isBuiltInName() || r.getBuiltInName() != builtinCode) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(r.getSheetNumber() == 0) {
|
if(r.getSheetNumber() == 0) {
|
||||||
|
@ -979,10 +1026,6 @@ public class HSSFWorkbook extends POIDocument
|
||||||
return -1;
|
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
|
* create a new Font and add it to the workbook's font table
|
||||||
* @return new font object
|
* @return new font object
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
|
||||||
import org.apache.poi.hssf.record.NameRecord;
|
import org.apache.poi.hssf.record.NameRecord;
|
||||||
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
|
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
|
||||||
import org.apache.poi.hssf.record.formula.DeletedArea3DPtg;
|
import org.apache.poi.hssf.record.formula.DeletedArea3DPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.Ptg;
|
||||||
import org.apache.poi.hssf.util.CellRangeAddress;
|
import org.apache.poi.hssf.util.CellRangeAddress;
|
||||||
import org.apache.poi.util.TempFile;
|
import org.apache.poi.util.TempFile;
|
||||||
|
|
||||||
|
@ -1018,9 +1019,9 @@ public final class TestBugs extends TestCase {
|
||||||
NameRecord r = w.getNameRecord(i);
|
NameRecord r = w.getNameRecord(i);
|
||||||
assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
|
assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
|
||||||
|
|
||||||
List nd = r.getNameDefinition();
|
Ptg[] nd = r.getNameDefinition();
|
||||||
assertEquals(1, nd.size());
|
assertEquals(1, nd.length);
|
||||||
assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
|
assertTrue(nd[0] instanceof DeletedArea3DPtg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1036,9 +1037,9 @@ public final class TestBugs extends TestCase {
|
||||||
NameRecord r = w.getNameRecord(i);
|
NameRecord r = w.getNameRecord(i);
|
||||||
assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
|
assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
|
||||||
|
|
||||||
List nd = r.getNameDefinition();
|
Ptg[] nd = r.getNameDefinition();
|
||||||
assertEquals(1, nd.size());
|
assertEquals(1, nd.length);
|
||||||
assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
|
assertTrue(nd[0] instanceof DeletedArea3DPtg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1053,9 +1054,9 @@ public final class TestBugs extends TestCase {
|
||||||
NameRecord r = w.getNameRecord(i);
|
NameRecord r = w.getNameRecord(i);
|
||||||
assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
|
assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
|
||||||
|
|
||||||
List nd = r.getNameDefinition();
|
Ptg[] nd = r.getNameDefinition();
|
||||||
assertEquals(1, nd.size());
|
assertEquals(1, nd.length);
|
||||||
assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
|
assertTrue(nd[0] instanceof DeletedArea3DPtg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,8 +223,16 @@ public final class TestHSSFSheet extends TestCase {
|
||||||
workbook.cloneSheet(0);
|
workbook.cloneSheet(0);
|
||||||
|
|
||||||
assertNotNull(workbook.getSheet("Test Clone"));
|
assertNotNull(workbook.getSheet("Test Clone"));
|
||||||
assertNotNull(workbook.getSheet("Test Clone(1)"));
|
|
||||||
assertNotNull(workbook.getSheet("Test Clone (2)"));
|
assertNotNull(workbook.getSheet("Test Clone (2)"));
|
||||||
|
assertEquals("Test Clone (3)", workbook.getSheetName(2));
|
||||||
|
assertNotNull(workbook.getSheet("Test Clone (3)"));
|
||||||
|
|
||||||
|
workbook.removeSheetAt(0);
|
||||||
|
workbook.removeSheetAt(0);
|
||||||
|
workbook.removeSheetAt(0);
|
||||||
|
workbook.createSheet("abc ( 123)");
|
||||||
|
workbook.cloneSheet(0);
|
||||||
|
assertEquals("abc (124)", workbook.getSheetName(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -429,9 +429,9 @@ public final class TestHSSFWorkbook extends TestCase {
|
||||||
assertEquals("On2", nr.getNameText());
|
assertEquals("On2", nr.getNameText());
|
||||||
assertEquals(0, nr.getSheetNumber());
|
assertEquals(0, nr.getSheetNumber());
|
||||||
assertEquals(1, nr.getExternSheetNumber());
|
assertEquals(1, nr.getExternSheetNumber());
|
||||||
assertEquals(1, nr.getNameDefinition().size());
|
assertEquals(1, nr.getNameDefinition().length);
|
||||||
|
|
||||||
ptg = (Area3DPtg)nr.getNameDefinition().get(0);
|
ptg = (Area3DPtg)nr.getNameDefinition()[0];
|
||||||
assertEquals(1, ptg.getExternSheetIndex());
|
assertEquals(1, ptg.getExternSheetIndex());
|
||||||
assertEquals(0, ptg.getFirstColumn());
|
assertEquals(0, ptg.getFirstColumn());
|
||||||
assertEquals(0, ptg.getFirstRow());
|
assertEquals(0, ptg.getFirstRow());
|
||||||
|
@ -452,9 +452,9 @@ public final class TestHSSFWorkbook extends TestCase {
|
||||||
assertEquals("OnOne", nr.getNameText());
|
assertEquals("OnOne", nr.getNameText());
|
||||||
assertEquals(0, nr.getSheetNumber());
|
assertEquals(0, nr.getSheetNumber());
|
||||||
assertEquals(0, nr.getExternSheetNumber());
|
assertEquals(0, nr.getExternSheetNumber());
|
||||||
assertEquals(1, nr.getNameDefinition().size());
|
assertEquals(1, nr.getNameDefinition().length);
|
||||||
|
|
||||||
ptg = (Area3DPtg)nr.getNameDefinition().get(0);
|
ptg = (Area3DPtg)nr.getNameDefinition()[0];
|
||||||
assertEquals(0, ptg.getExternSheetIndex());
|
assertEquals(0, ptg.getExternSheetIndex());
|
||||||
assertEquals(0, ptg.getFirstColumn());
|
assertEquals(0, ptg.getFirstColumn());
|
||||||
assertEquals(2, ptg.getFirstRow());
|
assertEquals(2, ptg.getFirstRow());
|
||||||
|
@ -475,9 +475,9 @@ public final class TestHSSFWorkbook extends TestCase {
|
||||||
assertEquals("OnSheet3", nr.getNameText());
|
assertEquals("OnSheet3", nr.getNameText());
|
||||||
assertEquals(0, nr.getSheetNumber());
|
assertEquals(0, nr.getSheetNumber());
|
||||||
assertEquals(2, nr.getExternSheetNumber());
|
assertEquals(2, nr.getExternSheetNumber());
|
||||||
assertEquals(1, nr.getNameDefinition().size());
|
assertEquals(1, nr.getNameDefinition().length);
|
||||||
|
|
||||||
ptg = (Area3DPtg)nr.getNameDefinition().get(0);
|
ptg = (Area3DPtg)nr.getNameDefinition()[0];
|
||||||
assertEquals(2, ptg.getExternSheetIndex());
|
assertEquals(2, ptg.getExternSheetIndex());
|
||||||
assertEquals(0, ptg.getFirstColumn());
|
assertEquals(0, ptg.getFirstColumn());
|
||||||
assertEquals(0, ptg.getFirstRow());
|
assertEquals(0, ptg.getFirstRow());
|
||||||
|
|
|
@ -19,7 +19,6 @@ package org.apache.poi.hssf.util;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
@ -28,6 +27,7 @@ import org.apache.poi.hssf.model.Workbook;
|
||||||
import org.apache.poi.hssf.record.NameRecord;
|
import org.apache.poi.hssf.record.NameRecord;
|
||||||
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
||||||
import org.apache.poi.hssf.record.formula.MemFuncPtg;
|
import org.apache.poi.hssf.record.formula.MemFuncPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.Ptg;
|
||||||
import org.apache.poi.hssf.record.formula.UnionPtg;
|
import org.apache.poi.hssf.record.formula.UnionPtg;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFName;
|
import org.apache.poi.hssf.usermodel.HSSFName;
|
||||||
|
@ -204,13 +204,13 @@ public final class TestAreaReference extends TestCase {
|
||||||
assertNotNull(nr);
|
assertNotNull(nr);
|
||||||
assertEquals("test", nr.getNameText());
|
assertEquals("test", nr.getNameText());
|
||||||
|
|
||||||
List def =nr.getNameDefinition();
|
Ptg[] def =nr.getNameDefinition();
|
||||||
assertEquals(4, def.size());
|
assertEquals(4, def.length);
|
||||||
|
|
||||||
MemFuncPtg ptgA = (MemFuncPtg)def.get(0);
|
MemFuncPtg ptgA = (MemFuncPtg)def[0];
|
||||||
Area3DPtg ptgB = (Area3DPtg)def.get(1);
|
Area3DPtg ptgB = (Area3DPtg)def[1];
|
||||||
Area3DPtg ptgC = (Area3DPtg)def.get(2);
|
Area3DPtg ptgC = (Area3DPtg)def[2];
|
||||||
UnionPtg ptgD = (UnionPtg)def.get(3);
|
UnionPtg ptgD = (UnionPtg)def[3];
|
||||||
assertEquals("", ptgA.toFormulaString(wb));
|
assertEquals("", ptgA.toFormulaString(wb));
|
||||||
assertEquals(refA, ptgB.toFormulaString(wb));
|
assertEquals(refA, ptgB.toFormulaString(wb));
|
||||||
assertEquals(refB, ptgC.toFormulaString(wb));
|
assertEquals(refB, ptgC.toFormulaString(wb));
|
||||||
|
|
Loading…
Reference in New Issue