jxl.read.biff.SupbookRecord Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jxl Show documentation
Show all versions of jxl Show documentation
JExcelApi is a java library which provides the ability to read, write, and modify Microsoft Excel spreadsheets.
The newest version!
/*********************************************************************
*
* Copyright (C) 2002 Andrew Khan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
***************************************************************************/
package jxl.read.biff;
import jxl.common.Logger;
import jxl.WorkbookSettings;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.StringHelper;
/**
* A record containing the references to the various sheets (internal and
* external) referenced by formulas in this workbook
*/
public class SupbookRecord extends RecordData
{
/**
* The logger
*/
private static Logger logger = Logger.getLogger(SupbookRecord.class);
/**
* The type of this supbook record
*/
private Type type;
/**
* The number of sheets - internal & external supbooks only
*/
private int numSheets;
/**
* The name of the external file
*/
private String fileName;
/**
* The names of the external sheets
*/
private String[] sheetNames;
/**
* The type of supbook this refers to
*/
private static class Type {};
public static final Type INTERNAL = new Type();
public static final Type EXTERNAL = new Type();
public static final Type ADDIN = new Type();
public static final Type LINK = new Type();
public static final Type UNKNOWN = new Type();
/**
* Constructs this object from the raw data
*
* @param t the raw data
* @param ws the workbook settings
*/
SupbookRecord(Record t, WorkbookSettings ws)
{
super(t);
byte[] data = getRecord().getData();
// First deduce the type
if (data.length == 4)
{
if (data[2] == 0x01 && data[3] == 0x04)
{
type = INTERNAL;
}
else if (data[2] == 0x01 && data[3] == 0x3a)
{
type = ADDIN;
}
else
{
type = UNKNOWN;
}
}
else if (data[0] == 0 && data[1] == 0)
{
type = LINK;
}
else
{
type = EXTERNAL;
}
if (type == INTERNAL)
{
numSheets = IntegerHelper.getInt(data[0], data[1]);
}
if (type == EXTERNAL)
{
readExternal(data, ws);
}
}
/**
* Reads the external data records
*
* @param data the data
* @param ws the workbook settings
*/
private void readExternal(byte[] data, WorkbookSettings ws)
{
numSheets = IntegerHelper.getInt(data[0], data[1]);
// subtract file name encoding from the length
int ln = IntegerHelper.getInt(data[2], data[3]) - 1;
int pos = 0;
if (data[4] == 0)
{
// non-unicode string
int encoding = data[5];
pos = 6;
if (encoding == 0)
{
fileName = StringHelper.getString(data, ln, pos, ws);
pos += ln;
}
else
{
fileName = getEncodedFilename(data, ln, pos);
pos += ln;
}
}
else
{
// unicode string
int encoding = IntegerHelper.getInt(data[5], data[6]);
pos = 7;
if (encoding == 0)
{
fileName = StringHelper.getUnicodeString(data, ln, pos);
pos += ln * 2;
}
else
{
fileName = getUnicodeEncodedFilename(data, ln, pos);
pos += ln * 2;
}
}
sheetNames = new String[numSheets];
for (int i = 0; i < sheetNames.length; i++)
{
ln = IntegerHelper.getInt(data[pos], data[pos + 1]);
if (data[pos + 2] == 0x0)
{
sheetNames[i] = StringHelper.getString(data, ln, pos + 3, ws);
pos += ln + 3;
}
else if (data[pos + 2] == 0x1)
{
sheetNames[i] = StringHelper.getUnicodeString(data, ln, pos + 3);
pos += ln * 2 + 3;
}
}
}
/**
* Gets the type of this supbook record
*
* @return the type of this supbook
*/
public Type getType()
{
return type;
}
/**
* Gets the number of sheets. This will only be non-zero for internal
* and external supbooks
*
* @return the number of sheets
*/
public int getNumberOfSheets()
{
return numSheets;
}
/**
* Gets the name of the external file
*
* @return the name of the external file
*/
public String getFileName()
{
return fileName;
}
/**
* Gets the name of the external sheet
*
* @param i the index of the external sheet
* @return the name of the sheet
*/
public String getSheetName(int i)
{
return sheetNames[i];
}
/**
* Gets the data - used when copying a spreadsheet
*
* @return the raw external sheet data
*/
public byte[] getData()
{
return getRecord().getData();
}
/**
* Gets the encoded string from the data array
*
* @param data the data
* @param ln length of the string
* @param pos the position in the array
* @return the string
*/
private String getEncodedFilename(byte[] data, int ln, int pos)
{
StringBuffer buf = new StringBuffer();
int endpos = pos + ln;
while (pos < endpos)
{
char c = (char) data[pos];
if (c == '\u0001')
{
// next character is a volume letter
pos++;
c = (char) data[pos];
buf.append(c);
buf.append(":\\\\");
}
else if (c == '\u0002')
{
// file is on the same volume
buf.append('\\');
}
else if (c == '\u0003')
{
// down directory
buf.append('\\');
}
else if (c == '\u0004')
{
// up directory
buf.append("..\\");
}
else
{
// just add on the character
buf.append(c);
}
pos++;
}
return buf.toString();
}
/**
* Gets the encoded string from the data array
*
* @param data the data
* @param ln length of the string
* @param pos the position in the array
* @return the string
*/
private String getUnicodeEncodedFilename(byte[] data, int ln, int pos)
{
StringBuffer buf = new StringBuffer();
int endpos = pos + ln * 2;
while (pos < endpos)
{
char c = (char) IntegerHelper.getInt(data[pos], data[pos + 1]);
if (c == '\u0001')
{
// next character is a volume letter
pos += 2;
c = (char) IntegerHelper.getInt(data[pos], data[pos + 1]);
buf.append(c);
buf.append(":\\\\");
}
else if (c == '\u0002')
{
// file is on the same volume
buf.append('\\');
}
else if (c == '\u0003')
{
// down directory
buf.append('\\');
}
else if (c == '\u0004')
{
// up directory
buf.append("..\\");
}
else
{
// just add on the character
buf.append(c);
}
pos += 2;
}
return buf.toString();
}
}