Home » JCraft » jxl.read » biff » [javadoc | source]

    1   /*********************************************************************
    2   *
    3   *      Copyright (C) 2002 Andrew Khan
    4   *
    5   * This library is free software; you can redistribute it and/or
    6   * modify it under the terms of the GNU Lesser General Public
    7   * License as published by the Free Software Foundation; either
    8   * version 2.1 of the License, or (at your option) any later version.
    9   *
   10   * This library is distributed in the hope that it will be useful,
   11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13   * Lesser General Public License for more details.
   14   *
   15   * You should have received a copy of the GNU Lesser General Public
   16   * License along with this library; if not, write to the Free Software
   17   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   18   ***************************************************************************/
   19   
   20   package jxl.read.biff;
   21   
   22   import jxl.common.Logger;
   23   
   24   import jxl.WorkbookSettings;
   25   import jxl.biff.IntegerHelper;
   26   import jxl.biff.RecordData;
   27   import jxl.biff.StringHelper;
   28   
   29   /**
   30    * A record containing the references to the various sheets (internal and
   31    * external) referenced by formulas in this workbook
   32    */
   33   public class SupbookRecord extends RecordData
   34   {
   35     /**
   36      * The logger
   37      */
   38     private static Logger logger = Logger.getLogger(SupbookRecord.class);
   39   
   40     /**
   41      * The type of this supbook record
   42      */
   43     private Type type;
   44   
   45     /**
   46      * The number of sheets - internal & external supbooks only
   47      */
   48     private int numSheets;
   49   
   50     /**
   51      * The name of the external file
   52      */
   53     private String fileName;
   54   
   55     /**
   56      * The names of the external sheets
   57      */
   58     private String[] sheetNames;
   59   
   60     /**
   61      * The type of supbook this refers to
   62      */
   63     private static class Type {};
   64   
   65   
   66     public static final Type INTERNAL = new Type();
   67     public static final Type EXTERNAL = new Type();
   68     public static final Type ADDIN    = new Type();
   69     public static final Type LINK     = new Type();
   70     public static final Type UNKNOWN  = new Type();
   71   
   72     /**
   73      * Constructs this object from the raw data
   74      *
   75      * @param t the raw data
   76      * @param ws the workbook settings
   77      */
   78     SupbookRecord(Record t, WorkbookSettings ws)
   79     {
   80       super(t);
   81       byte[] data = getRecord().getData();
   82   
   83       // First deduce the type
   84       if (data.length == 4)
   85       {
   86         if (data[2] == 0x01 && data[3] == 0x04)
   87         {
   88           type = INTERNAL;
   89         }
   90         else if (data[2] == 0x01 && data[3] == 0x3a)
   91         {
   92           type = ADDIN;
   93         }
   94         else
   95         {
   96           type = UNKNOWN;
   97         }
   98       }
   99       else if (data[0] == 0 && data[1] == 0)
  100       {
  101         type = LINK;
  102       }
  103       else
  104       {
  105         type = EXTERNAL;
  106       }
  107   
  108       if (type == INTERNAL)
  109       {
  110         numSheets = IntegerHelper.getInt(data[0], data[1]);
  111       }
  112   
  113       if (type == EXTERNAL)
  114       {
  115         readExternal(data, ws);
  116       }
  117     }
  118   
  119     /**
  120      * Reads the external data records
  121      *
  122      * @param data the data
  123      * @param ws the workbook settings
  124      */
  125     private void readExternal(byte[] data, WorkbookSettings ws)
  126     {
  127       numSheets = IntegerHelper.getInt(data[0], data[1]);
  128   
  129       // subtract file name encoding from the length
  130       int ln = IntegerHelper.getInt(data[2], data[3]) - 1;
  131       int pos = 0;
  132   
  133       if (data[4] == 0)
  134       {
  135         // non-unicode string
  136         int encoding = data[5];
  137         pos = 6;
  138         if (encoding == 0)
  139         {
  140           fileName = StringHelper.getString(data, ln, pos, ws);
  141           pos += ln;
  142         }
  143         else
  144         {
  145           fileName = getEncodedFilename(data, ln, pos);
  146           pos += ln;
  147         }
  148       }
  149       else
  150       {
  151         // unicode string
  152         int encoding = IntegerHelper.getInt(data[5], data[6]);
  153         pos = 7;
  154         if (encoding == 0)
  155         {
  156           fileName = StringHelper.getUnicodeString(data, ln, pos);
  157           pos += ln * 2;
  158         }
  159         else
  160         {
  161           fileName = getUnicodeEncodedFilename(data, ln, pos);
  162           pos += ln * 2;
  163         }
  164       }
  165   
  166       sheetNames = new String[numSheets];
  167   
  168       for (int i = 0; i < sheetNames.length; i++)
  169       {
  170         ln = IntegerHelper.getInt(data[pos], data[pos + 1]);
  171   
  172         if (data[pos + 2] == 0x0)
  173         {
  174           sheetNames[i] = StringHelper.getString(data, ln, pos + 3, ws);
  175           pos += ln + 3;
  176         }
  177         else if (data[pos + 2] == 0x1)
  178         {
  179           sheetNames[i] = StringHelper.getUnicodeString(data, ln, pos + 3);
  180           pos += ln * 2 + 3;
  181         }
  182       }
  183     }
  184   
  185     /**
  186      * Gets the type of this supbook record
  187      *
  188      * @return the type of this supbook
  189      */
  190     public Type getType()
  191     {
  192       return type;
  193     }
  194   
  195     /**
  196      * Gets the number of sheets.  This will only be non-zero for internal
  197      * and external supbooks
  198      *
  199      * @return the number of sheets
  200      */
  201     public int getNumberOfSheets()
  202     {
  203       return numSheets;
  204     }
  205   
  206     /**
  207      * Gets the name of the external file
  208      *
  209      * @return the name of the external file
  210      */
  211     public String getFileName()
  212     {
  213       return fileName;
  214     }
  215   
  216     /**
  217      * Gets the name of the external sheet
  218      *
  219      * @param i the index of the external sheet
  220      * @return the name of the sheet
  221      */
  222     public String getSheetName(int i)
  223     {
  224       return sheetNames[i];
  225     }
  226   
  227     /**
  228      * Gets the data - used when copying a spreadsheet
  229      *
  230      * @return the raw external sheet data
  231      */
  232     public byte[] getData()
  233     {
  234       return getRecord().getData();
  235     }
  236   
  237     /**
  238      * Gets the encoded string from the data array
  239      *
  240      * @param data the data
  241      * @param ln length of the string
  242      * @param pos the position in the array
  243      * @return the string
  244      */
  245     private String getEncodedFilename(byte[] data, int ln, int pos)
  246     {
  247       StringBuffer buf = new StringBuffer();
  248       int endpos = pos + ln;
  249       while (pos <  endpos)
  250       {
  251         char c = (char) data[pos];
  252   
  253         if (c == '\u0001')
  254         {
  255           // next character is a volume letter
  256           pos++;
  257           c = (char) data[pos];
  258           buf.append(c);
  259           buf.append(":\\\\");
  260         }
  261         else if (c == '\u0002')
  262         {
  263           // file is on the same volume
  264           buf.append('\\');
  265         }
  266         else if (c == '\u0003')
  267         {
  268           // down directory
  269           buf.append('\\');
  270         }
  271         else if (c == '\u0004')
  272         {
  273           // up directory
  274           buf.append("..\\");
  275         }
  276         else
  277         {
  278           // just add on the character
  279           buf.append(c);
  280         }
  281   
  282         pos++;
  283       }
  284   
  285       return buf.toString();
  286     }
  287   
  288     /**
  289      * Gets the encoded string from the data array
  290      *
  291      * @param data the data
  292      * @param ln length of the string
  293      * @param pos the position in the array
  294      * @return the string
  295      */
  296     private String getUnicodeEncodedFilename(byte[] data, int ln, int pos)
  297     {
  298       StringBuffer buf = new StringBuffer();
  299       int endpos = pos + ln * 2;
  300       while (pos <  endpos)
  301       {
  302         char c = (char) IntegerHelper.getInt(data[pos], data[pos + 1]);
  303   
  304         if (c == '\u0001')
  305         {
  306           // next character is a volume letter
  307           pos += 2;
  308           c = (char) IntegerHelper.getInt(data[pos], data[pos + 1]);
  309           buf.append(c);
  310           buf.append(":\\\\");
  311         }
  312         else if (c == '\u0002')
  313         {
  314           // file is on the same volume
  315           buf.append('\\');
  316         }
  317         else if (c == '\u0003')
  318         {
  319           // down directory
  320           buf.append('\\');
  321         }
  322         else if (c == '\u0004')
  323         {
  324           // up directory
  325           buf.append("..\\");
  326         }
  327         else
  328         {
  329           // just add on the character
  330           buf.append(c);
  331         }
  332   
  333         pos += 2;
  334       }
  335   
  336       return buf.toString();
  337     }
  338   }

Home » JCraft » jxl.read » biff » [javadoc | source]