Package org.apache.poi.hssf.record

Source Code of org.apache.poi.hssf.record.NameRecord$Option

/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */

package org.apache.poi.hssf.record;

import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.formula.Area3DPtg;
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.HSSFWorkbook;
import org.apache.poi.hssf.util.AreaReference;
import org.apache.poi.hssf.util.RangeAddress;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;

/**
* Title:        DEFINEDNAME Record (0x0018) <p/>
* Description:  Defines a named range within a workbook. <P>
* REFERENCE:  <P>
* @author Libin Roman (Vista Portal LDT. Developer)
* @author  Sergei Kozello (sergeikozello at mail.ru)
* @author Glen Stampoultzis (glens at apache.org)
* @version 1.0-pre
*/
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      = 1;
  /**Included for completeness sake, not implemented */
  public final static byte  BUILTIN_AUTO_OPEN             = 2;
  /**Included for completeness sake, not implemented */
  public final static byte  BUILTIN_AUTO_CLOSE            = 3;
  /**Included for completeness sake, not implemented */
  public final static byte  BUILTIN_DATABASE              = 4;
  /**Included for completeness sake, not implemented */
  public final static byte  BUILTIN_CRITERIA              = 5;

  public final static byte  BUILTIN_PRINT_AREA            = 6;
  public final static byte  BUILTIN_PRINT_TITLE           = 7;

  /**Included for completeness sake, not implemented */
  public final static byte  BUILTIN_RECORDER              = 8;
  /**Included for completeness sake, not implemented */
  public final static byte  BUILTIN_DATA_FORM             = 9;
  /**Included for completeness sake, not implemented */
  public final static byte  BUILTIN_AUTO_ACTIVATE         = 10;
  /**Included for completeness sake, not implemented */
  public final static byte  BUILTIN_AUTO_DEACTIVATE       = 11;
  /**Included for completeness sake, not implemented */
  public final static byte  BUILTIN_SHEET_TITLE           = 12;

  public final static byte  BUILTIN_FILTER_DB             = 13;

  private static final class Option {
    public static final int OPT_HIDDEN_NAME =   0x0001;
    public static final int OPT_FUNCTION_NAME = 0x0002;
    public static final int OPT_COMMAND_NAME =  0x0004;
    public static final int OPT_MACRO =         0x0008;
    public static final int OPT_COMPLEX =       0x0010;
    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;
  /** One-based extern index of sheet (resolved via LinkTable). Zero if this is a global name  */
  private short             field_5_externSheetIndex_plus1;
  /** the one based sheet number.  */
  private int               field_6_sheetNumber;
  private boolean           field_11_nameIsMultibyte;
  private byte              field_12_built_in_code;
  private String            field_12_name_text;
  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;
  private String            field_17_status_bar_text;


  /** Creates new NameRecord */
  public NameRecord() {
    field_13_name_definition = Ptg.EMPTY_PTG_ARRAY;

    field_12_name_text = "";
    field_14_custom_menu_text = "";
    field_15_description_text = "";
    field_16_help_topic_text = "";
    field_17_status_bar_text = "";
  }

  /**
   * Constructor to create a built-in named region
   * @param builtin Built-in byte representation for the name record, use the public constants
   */
  public NameRecord(byte builtin, int sheetNumber)
  {
    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
  }

  /** sets the option flag for the named range
   * @param flag option flag
   */
  public void setOptionFlag(short flag){
    field_1_option_flag = flag;
  }


  /** sets the keyboard shortcut
   * @param shortcut keyboard shortcut
   */
  public void setKeyboardShortcut(byte shortcut){
    field_2_keyboard_shortcut = shortcut;
  }

  /**
   * For named ranges, and built-in names
   * @return the 1-based sheet number.
   */
  public int getSheetNumber()
  {
    return field_6_sheetNumber;
  }

  /**
   * @return function group
   * @see FnGroupCountRecord
   */
  public byte getFnGroup() {
    int masked = field_1_option_flag & 0x0fc0;
    return (byte) (masked >> 4);
  }


  public void setSheetNumber(int value)
  {
    field_6_sheetNumber = value;
  }


  /** sets the name of the named range
   * @param name named range name
   */
  public void setNameText(String name){
    field_12_name_text = name;
    field_11_nameIsMultibyte = StringUtil.hasMultibyte(name);
  }

  /** sets the custom menu text
   * @param text custom menu text
   */
  public void setCustomMenuText(String text){
    field_14_custom_menu_text = text;
  }

  /** sets the description text
   * @param text the description text
   */
  public void setDescriptionText(String text){
    field_15_description_text = text;
  }

  /** sets the help topic text
   * @param text help topix text
   */
  public void setHelpTopicText(String text){
    field_16_help_topic_text = text;
  }

  /** sets the status bar text
   * @param text status bar text
   */
  public void setStatusBarText(String text){
    field_17_status_bar_text = text;
  }

  /** gets the option flag
   * @return option flag
   */
  public short getOptionFlag(){
    return field_1_option_flag;
  }

  /** returns the keyboard shortcut
   * @return keyboard shortcut
   */
  public byte getKeyboardShortcut(){
    return field_2_keyboard_shortcut ;
  }

  /**
   * gets the name length, in characters
   * @return name length
   */
  private int getNameTextLength(){
    if (isBuiltInName()) {
      return 1;
    }
    return field_12_name_text.length();
  }


  /**
   * @return true if name is hidden
   */
  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 <code>true</code> if name is a function
   */
  public boolean isFunctionName() {
    return (field_1_option_flag & Option.OPT_FUNCTION_NAME) != 0;
  }

  /**
   * @return <code>true</code> if name has a formula (named range or defined value)
   */
  public boolean hasFormula() {
    return field_1_option_flag == 0 && field_13_name_definition.length > 0;
  }

  /**
   * @return true if name is a command
   */
  public boolean isCommandName() {
    return (field_1_option_flag & Option.OPT_COMMAND_NAME) != 0;
  }
  /**
   * @return true if function macro or command macro
   */
  public boolean isMacro() {
    return (field_1_option_flag & Option.OPT_MACRO) != 0;
  }
  /**
   * @return true if array formula or user defined
   */
  public boolean isComplexFunction() {
    return (field_1_option_flag & Option.OPT_COMPLEX) != 0;
  }

  /**Convenience Function to determine if the name is a built-in name
   */
  public boolean isBuiltInName()
  {
    return ((field_1_option_flag & Option.OPT_BUILTIN) != 0);
  }


  /** gets the name
   * @return name
   */
  public String getNameText(){

    return isBuiltInName() ? translateBuiltInName(getBuiltInName()) : field_12_name_text;
  }

  /** Gets the Built In Name
   * @return the built in Name
   */
  public byte getBuiltInName()
  {
    return field_12_built_in_code;
  }


  /** gets the definition, reference (Formula)
   * @return the name formula. never <code>null</code>
   */
  public Ptg[] getNameDefinition() {
    return (Ptg[]) field_13_name_definition.clone();
  }

  public void setNameDefinition(Ptg[] ptgs) {
    field_13_name_definition = (Ptg[]) ptgs.clone();
  }

  /** get the custom menu text
   * @return custom menu text
   */
  public String getCustomMenuText(){
    return field_14_custom_menu_text;
  }

  /** gets the description text
   * @return description text
   */
  public String getDescriptionText(){
    return field_15_description_text;
  }

  /** get the help topic text
   * @return gelp topic text
   */
  public String getHelpTopicText(){
    return field_16_help_topic_text;
  }

  /** gets the status bar text
   * @return status bar text
   */
  public String getStatusBarText(){
    return field_17_status_bar_text;
  }


  /**
   * called by the class that is responsible for writing this sucker.
   * Subclasses should implement this so that their data is passed back in a
   * @param offset to begin writing at
   * @param data byte array containing instance data
   * @return number of bytes written
   */
  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.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_externSheetIndex_plus1);
    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);
        }
    }
    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;
  }

  public int getRecordSize(){
    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 int getExternSheetNumber(){
    if (field_13_name_definition.length < 1) {
      return 0;
    }
    Ptg ptg = field_13_name_definition[0];

    if (ptg.getClass() == Area3DPtg.class){
      return ((Area3DPtg) ptg).getExternSheetIndex();

    }
    if (ptg.getClass() == Ref3DPtg.class){
      return ((Ref3DPtg) ptg).getExternSheetIndex();
    }
    return 0;
  }

  /** sets the extern sheet number
   * @param externSheetNumber extern sheet number
   */
  public void setExternSheetNumber(short externSheetNumber){
    Ptg ptg;

    if (field_13_name_definition.length < 1){
      ptg = createNewPtg();
      field_13_name_definition = new Ptg[] {
        ptg,
      };
    } else {
      ptg = field_13_name_definition[0];
    }

    if (ptg.getClass() == Area3DPtg.class){
      ((Area3DPtg) ptg).setExternSheetIndex(externSheetNumber);

    } else if (ptg.getClass() == Ref3DPtg.class){
      ((Ref3DPtg) ptg).setExternSheetIndex(externSheetNumber);
    }

  }

  private static Ptg createNewPtg(){
    return new Area3DPtg("A1:A1", 0); // TODO - change to not be partially initialised
  }

  /** gets the reference , the area only (range)
   * @return area reference
   */
  public String getAreaReference(HSSFWorkbook book){
    return HSSFFormulaParser.toFormulaString(book, field_13_name_definition);
  }

  /** sets the reference , the area only (range)
   * @param ref area reference
   */
  public void setAreaReference(String ref){
    //Trying to find if what ptg do we need
    RangeAddress ra = new RangeAddress(ref);
    Ptg oldPtg;

    if (field_13_name_definition.length < 1){
      oldPtg = createNewPtg();
    } else {
      //Trying to find extern sheet index
      oldPtg = field_13_name_definition[0];
    }
    List temp = new ArrayList();
    int externSheetIndex = 0;

    if (oldPtg.getClass() == Area3DPtg.class){
      externSheetIndex =  ((Area3DPtg) oldPtg).getExternSheetIndex();

    } else if (oldPtg.getClass() == Ref3DPtg.class){
      externSheetIndex =  ((Ref3DPtg) oldPtg).getExternSheetIndex();
    }

    if (ra.hasRange()) {
      // Is it contiguous or not?
      AreaReference[] refs = AreaReference.generateContiguous(ref);

      // Add the area reference(s)
      for(int i=0; i<refs.length; i++) {
        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 ptg = UnionPtg.instance;
        temp.add(ptg);
      }
    } else {
      Ref3DPtg ptg = new Ref3DPtg(ra.getFromCell(), externSheetIndex);
      temp.add(ptg);
    }
    Ptg[] ptgs = new Ptg[temp.size()];
    temp.toArray(ptgs);
    field_13_name_definition = ptgs;
  }

  /**
   * called by the constructor, should set class level fields.  Should throw
   * runtime exception for bad/icomplete data.
   *
   * @param in the RecordInputstream to read the record from
   */
  public NameRecord(RecordInputStream in) {
    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_externSheetIndex_plus1      = 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.readTokens(field_4_length_name_definition, in);

    //Who says that this can only ever be compressed unicode???
    field_14_custom_menu_text = in.readCompressedUnicode(field_7_length_custom_menu);
    field_15_description_text = in.readCompressedUnicode(field_8_length_description_text);
    field_16_help_topic_text  = in.readCompressedUnicode(field_9_length_help_topic_text);
    field_17_status_bar_text  = in.readCompressedUnicode(field_10_length_status_bar_text);
  }

  /**
   * return the non static version of the id for this record.
   */
  public short getSid() {
    return sid;
  }
  /*
    20 00
    00
    01
    1A 00 // sz = 0x1A = 26
    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
    0B 00 // sz = 0xB = 11
    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 ]
   */

  public String toString() {
    StringBuffer sb = new StringBuffer();

    sb.append("[NAME]\n");
    sb.append("    .option flags           = ").append(HexDump.shortToHex(field_1_option_flag)).append("\n");
    sb.append("    .keyboard shortcut      = ").append(HexDump.byteToHex(field_2_keyboard_shortcut)).append("\n");
    sb.append("    .length of the name     = ").append(getNameTextLength()).append("\n");
    sb.append("    .extSheetIx(1-based, 0=Global)= ").append( field_5_externSheetIndex_plus1 ).append("\n");
    sb.append("    .sheetTabIx             = ").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");
    }

    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
   */
  private static String translateBuiltInName(byte name)
  {
    switch (name)
    {
      case NameRecord.BUILTIN_AUTO_ACTIVATE :     return "Auto_Activate";
      case NameRecord.BUILTIN_AUTO_CLOSE :        return "Auto_Close";
      case NameRecord.BUILTIN_AUTO_DEACTIVATE :   return "Auto_Deactivate";
      case NameRecord.BUILTIN_AUTO_OPEN :         return "Auto_Open";
      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_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";
  }
}
TOP

Related Classes of org.apache.poi.hssf.record.NameRecord$Option

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.