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;
|
||||
|
||||
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;
|
||||
|
@ -44,51 +43,33 @@ import org.apache.poi.util.StringUtil;
|
|||
*/
|
||||
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_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;
|
||||
|
||||
/**Included for completeness sake, not implemented
|
||||
*/
|
||||
public final static byte BUILTIN_AUTO_CLOSE = (byte)3;
|
||||
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_DATABASE = (byte)4;
|
||||
/**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;
|
||||
|
||||
/**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_FILTER_DB = 13;
|
||||
|
||||
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 {
|
||||
public static final int OPT_HIDDEN_NAME = 0x0001;
|
||||
public static final int OPT_FUNCTION_NAME = 0x0002;
|
||||
|
@ -98,22 +79,16 @@ public final class NameRecord extends Record {
|
|||
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;
|
||||
|
@ -122,13 +97,13 @@ public final class NameRecord extends Record {
|
|||
|
||||
/** 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 = "";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,19 +121,10 @@ public final class NameRecord extends Record {
|
|||
*/
|
||||
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
|
||||
|
@ -176,34 +142,9 @@ public final class NameRecord extends Record {
|
|||
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()
|
||||
{
|
||||
|
@ -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
|
||||
* @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
|
||||
|
@ -313,72 +217,15 @@ public final class NameRecord extends Record {
|
|||
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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -388,6 +235,13 @@ public final class NameRecord extends Record {
|
|||
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
|
||||
*/
|
||||
|
@ -419,7 +273,7 @@ public final class NameRecord extends Record {
|
|||
*/
|
||||
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(){
|
||||
|
||||
return this.isBuiltInName() ? this.translateBuiltInName(this.getBuiltInName()) : field_12_name_text;
|
||||
return isBuiltInName() ? translateBuiltInName(getBuiltInName()) : field_12_name_text;
|
||||
}
|
||||
|
||||
/** Gets the Built In Name
|
||||
|
@ -436,19 +290,19 @@ public final class NameRecord extends Record {
|
|||
*/
|
||||
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
|
||||
|
@ -490,7 +344,8 @@ public final class NameRecord extends Record {
|
|||
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
|
||||
|
@ -498,109 +353,107 @@ public final class NameRecord extends Record {
|
|||
* @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();
|
||||
public int serialize( int offset, byte[] data ) {
|
||||
|
||||
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 );
|
||||
|
||||
|
||||
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
|
||||
|
@ -609,11 +462,13 @@ public final class NameRecord extends Record {
|
|||
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){
|
||||
|
@ -625,11 +480,8 @@ public final class NameRecord extends Record {
|
|||
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -646,16 +498,14 @@ public final class NameRecord extends Record {
|
|||
//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){
|
||||
|
@ -667,29 +517,27 @@ public final class NameRecord extends Record {
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -699,40 +547,36 @@ public final class NameRecord extends Record {
|
|||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -742,113 +586,90 @@ public final class NameRecord extends Record {
|
|||
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();
|
||||
StringBuffer sb = 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");
|
||||
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)
|
||||
{
|
||||
|
@ -859,14 +680,15 @@ public final class NameRecord extends Record {
|
|||
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";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ public final class Ref3DPtg extends OperandPtg {
|
|||
private static final BitField colRelative = BitFieldFactory.getInstance(0x4000);
|
||||
|
||||
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 */
|
||||
private int field_2_row;
|
||||
/** Field 2
|
||||
|
@ -93,10 +93,10 @@ public final class Ref3DPtg extends OperandPtg {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,15 +22,15 @@ import org.apache.poi.hssf.record.NameRecord;
|
|||
import org.apache.poi.hssf.util.RangeAddress;
|
||||
|
||||
/**
|
||||
* High Level Representation of a 'defined name' which could be a 'built-in' name,
|
||||
* High Level Representation of a 'defined name' which could be a 'built-in' name,
|
||||
* 'named range' or name of a user defined function.
|
||||
*
|
||||
*
|
||||
* @author Libin Roman (Vista Portal LDT. Developer)
|
||||
*/
|
||||
public final class HSSFName {
|
||||
private HSSFWorkbook _book;
|
||||
private NameRecord _definedNameRec;
|
||||
|
||||
|
||||
/** Creates new HSSFName - called by HSSFWorkbook to create a sheet from
|
||||
* scratch.
|
||||
*
|
||||
|
@ -42,69 +42,68 @@ public final class HSSFName {
|
|||
_book = book;
|
||||
_definedNameRec = name;
|
||||
}
|
||||
|
||||
|
||||
/** Get the sheets name which this named range is referenced to
|
||||
* @return sheet name, which this named range referred to
|
||||
*/
|
||||
*/
|
||||
public String getSheetName() {
|
||||
short indexToExternSheet = _definedNameRec.getExternSheetNumber();
|
||||
|
||||
|
||||
return _book.getWorkbook().findSheetNameFromExternSheet(indexToExternSheet);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* @return text name of this defined name
|
||||
*/
|
||||
*/
|
||||
public String getNameName(){
|
||||
return _definedNameRec.getNameText();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* sets the name of the named range
|
||||
* @param nameName named range name to set
|
||||
*/
|
||||
*/
|
||||
public void setNameName(String nameName){
|
||||
_definedNameRec.setNameText(nameName);
|
||||
_definedNameRec.setNameTextLength((byte)nameName.length());
|
||||
Workbook wb = _book.getWorkbook();
|
||||
|
||||
|
||||
//Check to ensure no other names have the same case-insensitive name
|
||||
for ( int i = wb.getNumNames()-1; i >=0; i-- )
|
||||
{
|
||||
NameRecord rec = wb.getNameRecord(i);
|
||||
if (rec != _definedNameRec) {
|
||||
if (rec.getNameText().equalsIgnoreCase(getNameName()))
|
||||
throw new IllegalArgumentException("The workbook already contains this name (case-insensitive)");
|
||||
}
|
||||
NameRecord rec = wb.getNameRecord(i);
|
||||
if (rec != _definedNameRec) {
|
||||
if (rec.getNameText().equalsIgnoreCase(getNameName()))
|
||||
throw new IllegalArgumentException("The workbook already contains this name (case-insensitive)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Note - this method only applies to named ranges
|
||||
* @return the formula text defining the named range
|
||||
*/
|
||||
*/
|
||||
public String getReference() {
|
||||
if (_definedNameRec.isFunctionName()) {
|
||||
throw new IllegalStateException("Only applicable to named ranges");
|
||||
}
|
||||
if (_definedNameRec.isFunctionName()) {
|
||||
throw new IllegalStateException("Only applicable to named ranges");
|
||||
}
|
||||
return _definedNameRec.getAreaReference(_book);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* sets the sheet name which this named range referenced to
|
||||
* @param sheetName the sheet name of the reference
|
||||
*/
|
||||
*/
|
||||
private void setSheetName(String sheetName){
|
||||
int sheetNumber = _book.getSheetIndex(sheetName);
|
||||
short externSheetNumber = _book.getExternalSheetIndex(sheetNumber);
|
||||
_definedNameRec.setExternSheetNumber(externSheetNumber);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* sets the reference of this named range
|
||||
* @param ref the reference to set
|
||||
*/
|
||||
*/
|
||||
public void setReference(String ref){
|
||||
|
||||
RangeAddress ra = new RangeAddress(ref);
|
||||
|
@ -115,7 +114,7 @@ public final class HSSFName {
|
|||
setSheetName(sheetName);
|
||||
}
|
||||
|
||||
//allow the poi utilities to parse it out
|
||||
//allow the poi utilities to parse it out
|
||||
_definedNameRec.setAreaReference(ref);
|
||||
}
|
||||
|
||||
|
@ -129,7 +128,7 @@ public final class HSSFName {
|
|||
return "#REF!".endsWith(ref);
|
||||
}
|
||||
public boolean isFunctionName() {
|
||||
return _definedNameRec.isFunctionName();
|
||||
return _definedNameRec.isFunctionName();
|
||||
}
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.ArrayList;
|
|||
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;
|
||||
|
@ -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.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;
|
||||
|
@ -666,33 +667,81 @@ public class HSSFWorkbook extends POIDocument
|
|||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -901,7 +950,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
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);
|
||||
|
@ -919,29 +968,27 @@ public class HSSFWorkbook extends POIDocument
|
|||
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)
|
||||
|
@ -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++) {
|
||||
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) {
|
||||
|
@ -979,10 +1026,6 @@ public class HSSFWorkbook extends POIDocument
|
|||
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
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
|
|||
import org.apache.poi.hssf.record.NameRecord;
|
||||
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
|
||||
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.util.TempFile;
|
||||
|
||||
|
@ -1018,9 +1019,9 @@ public final class TestBugs extends TestCase {
|
|||
NameRecord r = w.getNameRecord(i);
|
||||
assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
|
||||
|
||||
List nd = r.getNameDefinition();
|
||||
assertEquals(1, nd.size());
|
||||
assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
|
||||
Ptg[] nd = r.getNameDefinition();
|
||||
assertEquals(1, nd.length);
|
||||
assertTrue(nd[0] instanceof DeletedArea3DPtg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1036,9 +1037,9 @@ public final class TestBugs extends TestCase {
|
|||
NameRecord r = w.getNameRecord(i);
|
||||
assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
|
||||
|
||||
List nd = r.getNameDefinition();
|
||||
assertEquals(1, nd.size());
|
||||
assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
|
||||
Ptg[] nd = r.getNameDefinition();
|
||||
assertEquals(1, nd.length);
|
||||
assertTrue(nd[0] instanceof DeletedArea3DPtg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1053,9 +1054,9 @@ public final class TestBugs extends TestCase {
|
|||
NameRecord r = w.getNameRecord(i);
|
||||
assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
|
||||
|
||||
List nd = r.getNameDefinition();
|
||||
assertEquals(1, nd.size());
|
||||
assertTrue(nd.get(0) instanceof DeletedArea3DPtg);
|
||||
Ptg[] nd = r.getNameDefinition();
|
||||
assertEquals(1, nd.length);
|
||||
assertTrue(nd[0] instanceof DeletedArea3DPtg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -223,8 +223,16 @@ public final class TestHSSFSheet extends TestCase {
|
|||
workbook.cloneSheet(0);
|
||||
|
||||
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(0, nr.getSheetNumber());
|
||||
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(0, ptg.getFirstColumn());
|
||||
assertEquals(0, ptg.getFirstRow());
|
||||
|
@ -452,9 +452,9 @@ public final class TestHSSFWorkbook extends TestCase {
|
|||
assertEquals("OnOne", nr.getNameText());
|
||||
assertEquals(0, nr.getSheetNumber());
|
||||
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.getFirstColumn());
|
||||
assertEquals(2, ptg.getFirstRow());
|
||||
|
@ -475,9 +475,9 @@ public final class TestHSSFWorkbook extends TestCase {
|
|||
assertEquals("OnSheet3", nr.getNameText());
|
||||
assertEquals(0, nr.getSheetNumber());
|
||||
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(0, ptg.getFirstColumn());
|
||||
assertEquals(0, ptg.getFirstRow());
|
||||
|
|
|
@ -19,7 +19,6 @@ package org.apache.poi.hssf.util;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
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.formula.Area3DPtg;
|
||||
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.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFName;
|
||||
|
@ -204,13 +204,13 @@ public final class TestAreaReference extends TestCase {
|
|||
assertNotNull(nr);
|
||||
assertEquals("test", nr.getNameText());
|
||||
|
||||
List def =nr.getNameDefinition();
|
||||
assertEquals(4, def.size());
|
||||
Ptg[] def =nr.getNameDefinition();
|
||||
assertEquals(4, def.length);
|
||||
|
||||
MemFuncPtg ptgA = (MemFuncPtg)def.get(0);
|
||||
Area3DPtg ptgB = (Area3DPtg)def.get(1);
|
||||
Area3DPtg ptgC = (Area3DPtg)def.get(2);
|
||||
UnionPtg ptgD = (UnionPtg)def.get(3);
|
||||
MemFuncPtg ptgA = (MemFuncPtg)def[0];
|
||||
Area3DPtg ptgB = (Area3DPtg)def[1];
|
||||
Area3DPtg ptgC = (Area3DPtg)def[2];
|
||||
UnionPtg ptgD = (UnionPtg)def[3];
|
||||
assertEquals("", ptgA.toFormulaString(wb));
|
||||
assertEquals(refA, ptgB.toFormulaString(wb));
|
||||
assertEquals(refB, ptgC.toFormulaString(wb));
|
||||
|
|
Loading…
Reference in New Issue