first commit

This commit is contained in:
MaddoScientisto 2026-03-14 20:04:39 +01:00
commit cf97b64877
27585 changed files with 3281780 additions and 0 deletions

View file

@ -0,0 +1,60 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
public class BOFRecord extends RecordData {
private static Logger logger = Logger.getLogger(BOFRecord.class);
private static final int Biff8 = 1536;
private static final int Biff7 = 1280;
private static final int WorkbookGlobals = 5;
private static final int Worksheet = 16;
private static final int Chart = 32;
private static final int MacroSheet = 64;
private int version;
private int substreamType;
BOFRecord(Record t) {
super(t);
byte[] data = getRecord().getData();
this.version = IntegerHelper.getInt(data[0], data[1]);
this.substreamType = IntegerHelper.getInt(data[2], data[3]);
}
public boolean isBiff8() {
return (this.version == 1536);
}
public boolean isBiff7() {
return (this.version == 1280);
}
boolean isWorkbookGlobals() {
return (this.substreamType == 5);
}
public boolean isWorksheet() {
return (this.substreamType == 16);
}
public boolean isMacroSheet() {
return (this.substreamType == 64);
}
public boolean isChart() {
return (this.substreamType == 32);
}
int getLength() {
return getRecord().getLength();
}
}

View file

@ -0,0 +1,60 @@
package jxl.read.biff;
import jxl.biff.FormattingRecords;
import jxl.biff.FormulaData;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.biff.formula.FormulaException;
import jxl.biff.formula.FormulaParser;
public abstract class BaseSharedFormulaRecord extends CellValue implements FormulaData {
private String formulaString;
private int filePos;
private byte[] tokens;
private ExternalSheet externalSheet;
private WorkbookMethods nameTable;
public BaseSharedFormulaRecord(Record t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si, int pos) {
super(t, fr, si);
this.externalSheet = es;
this.nameTable = nt;
this.filePos = pos;
}
public String getFormula() throws FormulaException {
if (this.formulaString == null) {
FormulaParser fp = new FormulaParser(this.tokens, this, this.externalSheet, this.nameTable, getSheet().getWorkbook().getSettings());
fp.parse();
this.formulaString = fp.getFormula();
}
return this.formulaString;
}
void setTokens(byte[] t) {
this.tokens = t;
}
protected final byte[] getTokens() {
return this.tokens;
}
protected final ExternalSheet getExternalSheet() {
return this.externalSheet;
}
protected final WorkbookMethods getNameTable() {
return this.nameTable;
}
public Record getRecord() {
return super.getRecord();
}
final int getFilePos() {
return this.filePos;
}
}

View file

@ -0,0 +1,33 @@
package jxl.read.biff;
import jxl.JXLException;
public class BiffException extends JXLException {
private static class BiffMessage {
public String message;
BiffMessage(String m) {
this.message = m;
}
}
static final BiffMessage unrecognizedBiffVersion = new BiffMessage("Unrecognized biff version");
static final BiffMessage expectedGlobals = new BiffMessage("Expected globals");
static final BiffMessage excelFileTooBig = new BiffMessage("Not all of the excel file could be read");
static final BiffMessage excelFileNotFound = new BiffMessage("The input file was not found");
static final BiffMessage unrecognizedOLEFile = new BiffMessage("Unable to recognize OLE stream");
static final BiffMessage streamNotFound = new BiffMessage("Compound file does not contain the specified stream");
static final BiffMessage passwordProtected = new BiffMessage("The workbook is password protected");
static final BiffMessage corruptFileFormat = new BiffMessage("The file format is corrupt");
public BiffException(BiffMessage m) {
super(m.message);
}
}

View file

@ -0,0 +1,24 @@
package jxl.read.biff;
public class BiffRecordReader {
private File file;
private Record record;
public BiffRecordReader(File f) {
this.file = f;
}
public boolean hasNext() {
return this.file.hasNext();
}
public Record next() {
this.record = this.file.next();
return this.record;
}
public int getPos() {
return this.file.getPos() - this.record.getLength() - 4;
}
}

View file

@ -0,0 +1,18 @@
package jxl.read.biff;
import jxl.CellType;
import jxl.biff.FormattingRecords;
public class BlankCell extends CellValue {
BlankCell(Record t, FormattingRecords fr, SheetImpl si) {
super(t, fr, si);
}
public String getContents() {
return "";
}
public CellType getType() {
return CellType.EMPTY;
}
}

View file

@ -0,0 +1,65 @@
package jxl.read.biff;
import jxl.BooleanCell;
import jxl.BooleanFormulaCell;
import jxl.CellType;
import jxl.biff.FormattingRecords;
import jxl.biff.FormulaData;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.biff.formula.FormulaException;
import jxl.biff.formula.FormulaParser;
import jxl.common.Assert;
class BooleanFormulaRecord extends CellValue implements BooleanCell, FormulaData, BooleanFormulaCell {
private boolean value;
private ExternalSheet externalSheet;
private WorkbookMethods nameTable;
private String formulaString;
private byte[] data;
public BooleanFormulaRecord(Record t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) {
super(t, fr, si);
this.externalSheet = es;
this.nameTable = nt;
this.value = false;
this.data = getRecord().getData();
Assert.verify((this.data[6] != 2));
this.value = (this.data[8] == 1);
}
public boolean getValue() {
return this.value;
}
public String getContents() {
return new Boolean(this.value).toString();
}
public CellType getType() {
return CellType.BOOLEAN_FORMULA;
}
public byte[] getFormulaData() throws FormulaException {
if (!getSheet().getWorkbookBof().isBiff8())
throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
byte[] d = new byte[this.data.length - 6];
System.arraycopy(this.data, 6, d, 0, this.data.length - 6);
return d;
}
public String getFormula() throws FormulaException {
if (this.formulaString == null) {
byte[] tokens = new byte[this.data.length - 22];
System.arraycopy(this.data, 22, tokens, 0, tokens.length);
FormulaParser fp = new FormulaParser(tokens, this, this.externalSheet, this.nameTable, getSheet().getWorkbook().getSettings());
fp.parse();
this.formulaString = fp.getFormula();
}
return this.formulaString;
}
}

View file

@ -0,0 +1,43 @@
package jxl.read.biff;
import jxl.BooleanCell;
import jxl.CellType;
import jxl.biff.FormattingRecords;
import jxl.common.Assert;
class BooleanRecord extends CellValue implements BooleanCell {
private boolean error;
private boolean value;
public BooleanRecord(Record t, FormattingRecords fr, SheetImpl si) {
super(t, fr, si);
this.error = false;
this.value = false;
byte[] data = getRecord().getData();
this.error = (data[7] == 1);
if (!this.error)
this.value = (data[6] == 1);
}
public boolean isError() {
return this.error;
}
public boolean getValue() {
return this.value;
}
public String getContents() {
Assert.verify(!isError());
return new Boolean(this.value).toString();
}
public CellType getType() {
return CellType.BOOLEAN;
}
public Record getRecord() {
return super.getRecord();
}
}

View file

@ -0,0 +1,9 @@
package jxl.read.biff;
import jxl.biff.Type;
class BottomMarginRecord extends MarginRecord {
BottomMarginRecord(Record r) {
super(Type.BOTTOMMARGIN, r);
}
}

View file

@ -0,0 +1,70 @@
package jxl.read.biff;
import jxl.WorkbookSettings;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.StringHelper;
class BoundsheetRecord extends RecordData {
private int offset;
private byte typeFlag;
private byte visibilityFlag;
private int length;
private String name;
private static class Biff7 {
private Biff7() {}
}
public static Biff7 biff7 = new Biff7();
public BoundsheetRecord(Record t, WorkbookSettings s) {
super(t);
byte[] data = getRecord().getData();
this.offset = IntegerHelper.getInt(data[0], data[1], data[2], data[3]);
this.typeFlag = data[5];
this.visibilityFlag = data[4];
this.length = data[6];
if (data[7] == 0) {
byte[] bytes = new byte[this.length];
System.arraycopy(data, 8, bytes, 0, this.length);
this.name = StringHelper.getString(bytes, this.length, 0, s);
} else {
byte[] bytes = new byte[this.length * 2];
System.arraycopy(data, 8, bytes, 0, this.length * 2);
this.name = StringHelper.getUnicodeString(bytes, this.length, 0);
}
}
public BoundsheetRecord(Record t, Biff7 biff7) {
super(t);
byte[] data = getRecord().getData();
this.offset = IntegerHelper.getInt(data[0], data[1], data[2], data[3]);
this.typeFlag = data[5];
this.visibilityFlag = data[4];
this.length = data[6];
byte[] bytes = new byte[this.length];
System.arraycopy(data, 7, bytes, 0, this.length);
this.name = new String(bytes);
}
public String getName() {
return this.name;
}
public boolean isHidden() {
return (this.visibilityFlag != 0);
}
public boolean isSheet() {
return (this.typeFlag == 0);
}
public boolean isChart() {
return (this.typeFlag == 2);
}
}

View file

@ -0,0 +1,16 @@
package jxl.read.biff;
import jxl.biff.RecordData;
import jxl.common.Logger;
public class ButtonPropertySetRecord extends RecordData {
private static Logger logger = Logger.getLogger(ButtonPropertySetRecord.class);
ButtonPropertySetRecord(Record t) {
super(t);
}
public byte[] getData() {
return getRecord().getData();
}
}

View file

@ -0,0 +1,22 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class CalcModeRecord extends RecordData {
private static Logger logger = Logger.getLogger(CalcModeRecord.class);
private boolean automatic;
public CalcModeRecord(Record t) {
super(t);
byte[] data = t.getData();
int mode = IntegerHelper.getInt(data[0], data[1]);
this.automatic = (mode == 1);
}
public boolean isAutomatic() {
return this.automatic;
}
}

View file

@ -0,0 +1,9 @@
package jxl.read.biff;
import jxl.CellFeatures;
interface CellFeaturesAccessor {
void setCellFeatures(CellFeatures paramCellFeatures);
CellFeatures getCellFeatures();
}

View file

@ -0,0 +1,85 @@
package jxl.read.biff;
import jxl.Cell;
import jxl.CellFeatures;
import jxl.biff.FormattingRecords;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.XFRecord;
import jxl.common.Logger;
import jxl.format.CellFormat;
public abstract class CellValue extends RecordData implements Cell, CellFeaturesAccessor {
private static Logger logger = Logger.getLogger(CellValue.class);
private int row;
private int column;
private int xfIndex;
private FormattingRecords formattingRecords;
private boolean initialized;
private XFRecord format;
private SheetImpl sheet;
private CellFeatures features;
protected CellValue(Record t, FormattingRecords fr, SheetImpl si) {
super(t);
byte[] data = getRecord().getData();
this.row = IntegerHelper.getInt(data[0], data[1]);
this.column = IntegerHelper.getInt(data[2], data[3]);
this.xfIndex = IntegerHelper.getInt(data[4], data[5]);
this.sheet = si;
this.formattingRecords = fr;
this.initialized = false;
}
public final int getRow() {
return this.row;
}
public final int getColumn() {
return this.column;
}
public final int getXFIndex() {
return this.xfIndex;
}
public CellFormat getCellFormat() {
if (!this.initialized) {
this.format = this.formattingRecords.getXFRecord(this.xfIndex);
this.initialized = true;
}
return this.format;
}
public boolean isHidden() {
ColumnInfoRecord cir = this.sheet.getColumnInfo(this.column);
if (cir != null && (cir.getWidth() == 0 || cir.getHidden()))
return true;
RowRecord rr = this.sheet.getRowInfo(this.row);
if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed()))
return true;
return false;
}
protected SheetImpl getSheet() {
return this.sheet;
}
public CellFeatures getCellFeatures() {
return this.features;
}
public void setCellFeatures(CellFeatures cf) {
if (this.features != null)
logger.warn("current cell features not null - overwriting");
this.features = cf;
}
}

View file

@ -0,0 +1,18 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
class CentreRecord extends RecordData {
private boolean centre;
public CentreRecord(Record t) {
super(t);
byte[] data = getRecord().getData();
this.centre = (IntegerHelper.getInt(data[0], data[1]) != 0);
}
public boolean isCentre() {
return this.centre;
}
}

View file

@ -0,0 +1,21 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class CodepageRecord extends RecordData {
private static Logger logger = Logger.getLogger(CodepageRecord.class);
private int characterSet;
public CodepageRecord(Record t) {
super(t);
byte[] data = t.getData();
this.characterSet = IntegerHelper.getInt(data[0], data[1]);
}
public int getCharacterSet() {
return this.characterSet;
}
}

View file

@ -0,0 +1,64 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.Type;
public class ColumnInfoRecord extends RecordData {
private byte[] data;
private int startColumn;
private int endColumn;
private int xfIndex;
private int width;
private boolean hidden;
private int outlineLevel;
private boolean collapsed;
ColumnInfoRecord(Record t) {
super(Type.COLINFO);
this.data = t.getData();
this.startColumn = IntegerHelper.getInt(this.data[0], this.data[1]);
this.endColumn = IntegerHelper.getInt(this.data[2], this.data[3]);
this.width = IntegerHelper.getInt(this.data[4], this.data[5]);
this.xfIndex = IntegerHelper.getInt(this.data[6], this.data[7]);
int options = IntegerHelper.getInt(this.data[8], this.data[9]);
this.hidden = ((options & 0x1) != 0);
this.outlineLevel = (options & 0x700) >> 8;
this.collapsed = ((options & 0x1000) != 0);
}
public int getStartColumn() {
return this.startColumn;
}
public int getEndColumn() {
return this.endColumn;
}
public int getXFIndex() {
return this.xfIndex;
}
public int getOutlineLevel() {
return this.outlineLevel;
}
public boolean getCollapsed() {
return this.collapsed;
}
public int getWidth() {
return this.width;
}
public boolean getHidden() {
return this.hidden;
}
}

View file

@ -0,0 +1,275 @@
package jxl.read.biff;
import java.util.ArrayList;
import java.util.Iterator;
import jxl.WorkbookSettings;
import jxl.biff.BaseCompoundFile;
import jxl.biff.IntegerHelper;
import jxl.common.Logger;
public final class CompoundFile extends BaseCompoundFile {
private static Logger logger = Logger.getLogger(CompoundFile.class);
private byte[] data;
private int numBigBlockDepotBlocks;
private int sbdStartBlock;
private int rootStartBlock;
private int extensionBlock;
private int numExtensionBlocks;
private byte[] rootEntry;
private int[] bigBlockChain;
private int[] smallBlockChain;
private int[] bigBlockDepotBlocks;
private ArrayList propertySets;
private WorkbookSettings settings;
private BaseCompoundFile.PropertyStorage rootEntryPropertyStorage;
public CompoundFile(byte[] d, WorkbookSettings ws) throws BiffException {
this.data = d;
this.settings = ws;
for (int i = 0; i < IDENTIFIER.length; i++) {
if (this.data[i] != IDENTIFIER[i])
throw new BiffException(BiffException.unrecognizedOLEFile);
}
this.propertySets = new ArrayList();
this.numBigBlockDepotBlocks = IntegerHelper.getInt(this.data[44], this.data[45], this.data[46], this.data[47]);
this.sbdStartBlock = IntegerHelper.getInt(this.data[60], this.data[61], this.data[62], this.data[63]);
this.rootStartBlock = IntegerHelper.getInt(this.data[48], this.data[49], this.data[50], this.data[51]);
this.extensionBlock = IntegerHelper.getInt(this.data[68], this.data[69], this.data[70], this.data[71]);
this.numExtensionBlocks = IntegerHelper.getInt(this.data[72], this.data[73], this.data[74], this.data[75]);
this.bigBlockDepotBlocks = new int[this.numBigBlockDepotBlocks];
int pos = 76;
int bbdBlocks = this.numBigBlockDepotBlocks;
if (this.numExtensionBlocks != 0)
bbdBlocks = 109;
for (int k = 0; k < bbdBlocks; k++) {
this.bigBlockDepotBlocks[k] = IntegerHelper.getInt(d[pos], d[pos + 1], d[pos + 2], d[pos + 3]);
pos += 4;
}
for (int j = 0; j < this.numExtensionBlocks; j++) {
pos = (this.extensionBlock + 1) * 512;
int blocksToRead = Math.min(this.numBigBlockDepotBlocks - bbdBlocks, 127);
for (int m = bbdBlocks; m < bbdBlocks + blocksToRead; m++) {
this.bigBlockDepotBlocks[m] = IntegerHelper.getInt(d[pos], d[pos + 1], d[pos + 2], d[pos + 3]);
pos += 4;
}
bbdBlocks += blocksToRead;
if (bbdBlocks < this.numBigBlockDepotBlocks)
this.extensionBlock = IntegerHelper.getInt(d[pos], d[pos + 1], d[pos + 2], d[pos + 3]);
}
readBigBlockDepot();
readSmallBlockDepot();
this.rootEntry = readData(this.rootStartBlock);
readPropertySets();
}
private void readBigBlockDepot() {
int pos = 0;
int index = 0;
this.bigBlockChain = new int[this.numBigBlockDepotBlocks * 512 / 4];
for (int i = 0; i < this.numBigBlockDepotBlocks; i++) {
pos = (this.bigBlockDepotBlocks[i] + 1) * 512;
for (int j = 0; j < 128; j++) {
this.bigBlockChain[index] = IntegerHelper.getInt(this.data[pos], this.data[pos + 1], this.data[pos + 2], this.data[pos + 3]);
pos += 4;
index++;
}
}
}
private void readSmallBlockDepot() throws BiffException {
int pos = 0;
int index = 0;
int sbdBlock = this.sbdStartBlock;
this.smallBlockChain = new int[0];
if (sbdBlock == -1) {
logger.warn("invalid small block depot number");
return;
}
int blockCount = 0;
for (; blockCount <= this.bigBlockChain.length && sbdBlock != -2; blockCount++) {
int[] oldChain = this.smallBlockChain;
this.smallBlockChain = new int[this.smallBlockChain.length + 128];
System.arraycopy(oldChain, 0, this.smallBlockChain, 0, oldChain.length);
pos = (sbdBlock + 1) * 512;
for (int j = 0; j < 128; j++) {
this.smallBlockChain[index] = IntegerHelper.getInt(this.data[pos], this.data[pos + 1], this.data[pos + 2], this.data[pos + 3]);
pos += 4;
index++;
}
sbdBlock = this.bigBlockChain[sbdBlock];
}
if (blockCount > this.bigBlockChain.length)
throw new BiffException(BiffException.corruptFileFormat);
}
private void readPropertySets() {
int offset = 0;
byte[] d = null;
while (offset < this.rootEntry.length) {
d = new byte[128];
System.arraycopy(this.rootEntry, offset, d, 0, d.length);
BaseCompoundFile.PropertyStorage ps = new BaseCompoundFile.PropertyStorage(this, d);
if (ps.name == null || ps.name.length() == 0)
if (ps.type == 5) {
ps.name = "Root Entry";
logger.warn("Property storage name for " + ps.type + " is empty - setting to " + "Root Entry");
} else if (ps.size != 0) {
logger.warn("Property storage type " + ps.type + " is non-empty and has no associated name");
}
this.propertySets.add(ps);
if (ps.name.equalsIgnoreCase("Root Entry"))
this.rootEntryPropertyStorage = ps;
offset += 128;
}
if (this.rootEntryPropertyStorage == null)
this.rootEntryPropertyStorage = this.propertySets.get(0);
}
public byte[] getStream(String streamName) throws BiffException {
BaseCompoundFile.PropertyStorage ps = findPropertyStorage(streamName, this.rootEntryPropertyStorage);
if (ps == null)
ps = getPropertyStorage(streamName);
if (ps.size >= 4096 || streamName.equalsIgnoreCase("Root Entry"))
return getBigBlockStream(ps);
return getSmallBlockStream(ps);
}
public byte[] getStream(int psIndex) throws BiffException {
BaseCompoundFile.PropertyStorage ps = getPropertyStorage(psIndex);
if (ps.size >= 4096 || ps.name.equalsIgnoreCase("Root Entry"))
return getBigBlockStream(ps);
return getSmallBlockStream(ps);
}
public BaseCompoundFile.PropertyStorage findPropertyStorage(String name) {
return findPropertyStorage(name, this.rootEntryPropertyStorage);
}
private BaseCompoundFile.PropertyStorage findPropertyStorage(String name, BaseCompoundFile.PropertyStorage base) {
if (base.child == -1)
return null;
BaseCompoundFile.PropertyStorage child = getPropertyStorage(base.child);
if (child.name.equalsIgnoreCase(name))
return child;
BaseCompoundFile.PropertyStorage prev = child;
while (prev.previous != -1) {
prev = getPropertyStorage(prev.previous);
if (prev.name.equalsIgnoreCase(name))
return prev;
}
BaseCompoundFile.PropertyStorage next = child;
while (next.next != -1) {
next = getPropertyStorage(next.next);
if (next.name.equalsIgnoreCase(name))
return next;
}
return findPropertyStorage(name, child);
}
private BaseCompoundFile.PropertyStorage getPropertyStorage(String name) throws BiffException {
Iterator<BaseCompoundFile.PropertyStorage> i = this.propertySets.iterator();
boolean found = false;
boolean multiple = false;
BaseCompoundFile.PropertyStorage ps = null;
while (i.hasNext()) {
BaseCompoundFile.PropertyStorage ps2 = i.next();
if (ps2.name.equalsIgnoreCase(name)) {
multiple = (found == true);
found = true;
ps = ps2;
}
}
if (multiple)
logger.warn("found multiple copies of property set " + name);
if (!found)
throw new BiffException(BiffException.streamNotFound);
return ps;
}
private BaseCompoundFile.PropertyStorage getPropertyStorage(int index) {
return this.propertySets.get(index);
}
private byte[] getBigBlockStream(BaseCompoundFile.PropertyStorage ps) {
int numBlocks = ps.size / 512;
if (ps.size % 512 != 0)
numBlocks++;
byte[] streamData = new byte[numBlocks * 512];
int block = ps.startBlock;
int count = 0;
int pos = 0;
while (block != -2 && count < numBlocks) {
pos = (block + 1) * 512;
System.arraycopy(this.data, pos, streamData, count * 512, 512);
count++;
block = this.bigBlockChain[block];
}
if (block != -2 && count == numBlocks)
logger.warn("Property storage size inconsistent with block chain.");
return streamData;
}
private byte[] getSmallBlockStream(BaseCompoundFile.PropertyStorage ps) throws BiffException {
byte[] rootdata = readData(this.rootEntryPropertyStorage.startBlock);
byte[] sbdata = new byte[0];
int block = ps.startBlock;
int pos = 0;
int blockCount = 0;
for (; blockCount <= this.smallBlockChain.length && block != -2; blockCount++) {
byte[] olddata = sbdata;
sbdata = new byte[olddata.length + 64];
System.arraycopy(olddata, 0, sbdata, 0, olddata.length);
pos = block * 64;
System.arraycopy(rootdata, pos, sbdata, olddata.length, 64);
block = this.smallBlockChain[block];
if (block == -1) {
logger.warn("Incorrect terminator for small block stream " + ps.name);
block = -2;
}
}
if (blockCount > this.smallBlockChain.length)
throw new BiffException(BiffException.corruptFileFormat);
return sbdata;
}
private byte[] readData(int bl) throws BiffException {
int block = bl;
int pos = 0;
byte[] entry = new byte[0];
int blockCount = 0;
for (; blockCount <= this.bigBlockChain.length && block != -2; blockCount++) {
byte[] oldEntry = entry;
entry = new byte[oldEntry.length + 512];
System.arraycopy(oldEntry, 0, entry, 0, oldEntry.length);
pos = (block + 1) * 512;
System.arraycopy(this.data, pos, entry, oldEntry.length, 512);
if (this.bigBlockChain[block] == block)
throw new BiffException(BiffException.corruptFileFormat);
block = this.bigBlockChain[block];
}
if (blockCount > this.bigBlockChain.length)
throw new BiffException(BiffException.corruptFileFormat);
return entry;
}
public int getNumberOfPropertySets() {
return this.propertySets.size();
}
public BaseCompoundFile.PropertyStorage getPropertySet(int index) {
return getPropertyStorage(index);
}
}

View file

@ -0,0 +1,28 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
public class CountryRecord extends RecordData {
private static Logger logger = Logger.getLogger(CountryRecord.class);
private int language;
private int regionalSettings;
public CountryRecord(Record t) {
super(t);
byte[] data = t.getData();
this.language = IntegerHelper.getInt(data[0], data[1]);
this.regionalSettings = IntegerHelper.getInt(data[2], data[3]);
}
public int getLanguageCode() {
return this.language;
}
public int getRegionalSettingsCode() {
return this.regionalSettings;
}
}

View file

@ -0,0 +1,58 @@
package jxl.read.biff;
import java.text.NumberFormat;
import jxl.CellType;
import jxl.DateCell;
import jxl.DateFormulaCell;
import jxl.biff.FormattingRecords;
import jxl.biff.FormulaData;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.biff.formula.FormulaException;
import jxl.biff.formula.FormulaParser;
class DateFormulaRecord extends DateRecord implements DateCell, FormulaData, DateFormulaCell {
private String formulaString;
private ExternalSheet externalSheet;
private WorkbookMethods nameTable;
private byte[] data;
public DateFormulaRecord(NumberFormulaRecord t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, boolean nf, SheetImpl si) throws FormulaException {
super(t, t.getXFIndex(), fr, nf, si);
this.externalSheet = es;
this.nameTable = nt;
this.data = t.getFormulaData();
}
public CellType getType() {
return CellType.DATE_FORMULA;
}
public byte[] getFormulaData() throws FormulaException {
if (!getSheet().getWorkbookBof().isBiff8())
throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
return this.data;
}
public String getFormula() throws FormulaException {
if (this.formulaString == null) {
byte[] tokens = new byte[this.data.length - 16];
System.arraycopy(this.data, 16, tokens, 0, tokens.length);
FormulaParser fp = new FormulaParser(tokens, this, this.externalSheet, this.nameTable, getSheet().getWorkbook().getSettings());
fp.parse();
this.formulaString = fp.getFormula();
}
return this.formulaString;
}
public double getValue() {
return 0.0D;
}
public NumberFormat getNumberFormat() {
return null;
}
}

View file

@ -0,0 +1,144 @@
package jxl.read.biff;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import jxl.CellFeatures;
import jxl.CellType;
import jxl.DateCell;
import jxl.NumberCell;
import jxl.biff.FormattingRecords;
import jxl.common.Assert;
import jxl.common.Logger;
import jxl.format.CellFormat;
class DateRecord implements DateCell, CellFeaturesAccessor {
private static Logger logger = Logger.getLogger(DateRecord.class);
private Date date;
private int row;
private int column;
private boolean time;
private DateFormat format;
private CellFormat cellFormat;
private int xfIndex;
private FormattingRecords formattingRecords;
private SheetImpl sheet;
private CellFeatures features;
private boolean initialized;
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy");
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
private static final int nonLeapDay = 61;
private static final TimeZone gmtZone = TimeZone.getTimeZone("GMT");
private static final int utcOffsetDays = 25569;
private static final int utcOffsetDays1904 = 24107;
private static final long secondsInADay = 86400L;
private static final long msInASecond = 1000L;
private static final long msInADay = 86400000L;
public DateRecord(NumberCell num, int xfi, FormattingRecords fr, boolean nf, SheetImpl si) {
this.row = num.getRow();
this.column = num.getColumn();
this.xfIndex = xfi;
this.formattingRecords = fr;
this.sheet = si;
this.initialized = false;
this.format = this.formattingRecords.getDateFormat(this.xfIndex);
double numValue = num.getValue();
if (Math.abs(numValue) < 1.0D) {
if (this.format == null)
this.format = timeFormat;
this.time = true;
} else {
if (this.format == null)
this.format = dateFormat;
this.time = false;
}
if (!nf && !this.time && numValue < 61.0D)
numValue++;
this.format.setTimeZone(gmtZone);
int offsetDays = nf ? 24107 : 25569;
double utcDays = numValue - (double)offsetDays;
long utcValue = Math.round(utcDays * 86400.0D) * 1000L;
this.date = new Date(utcValue);
}
public final int getRow() {
return this.row;
}
public final int getColumn() {
return this.column;
}
public Date getDate() {
return this.date;
}
public String getContents() {
return this.format.format(this.date);
}
public CellType getType() {
return CellType.DATE;
}
public boolean isTime() {
return this.time;
}
public DateFormat getDateFormat() {
Assert.verify((this.format != null));
return this.format;
}
public CellFormat getCellFormat() {
if (!this.initialized) {
this.cellFormat = this.formattingRecords.getXFRecord(this.xfIndex);
this.initialized = true;
}
return this.cellFormat;
}
public boolean isHidden() {
ColumnInfoRecord cir = this.sheet.getColumnInfo(this.column);
if (cir != null && cir.getWidth() == 0)
return true;
RowRecord rr = this.sheet.getRowInfo(this.row);
if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed()))
return true;
return false;
}
protected final SheetImpl getSheet() {
return this.sheet;
}
public CellFeatures getCellFeatures() {
return this.features;
}
public void setCellFeatures(CellFeatures cf) {
this.features = cf;
}
}

View file

@ -0,0 +1,18 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
class DefaultColumnWidthRecord extends RecordData {
private int width;
public DefaultColumnWidthRecord(Record t) {
super(t);
byte[] data = t.getData();
this.width = IntegerHelper.getInt(data[0], data[1]);
}
public int getWidth() {
return this.width;
}
}

View file

@ -0,0 +1,19 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
class DefaultRowHeightRecord extends RecordData {
private int height;
public DefaultRowHeightRecord(Record t) {
super(t);
byte[] data = t.getData();
if (data.length > 2)
this.height = IntegerHelper.getInt(data[2], data[3]);
}
public int getHeight() {
return this.height;
}
}

View file

@ -0,0 +1,53 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class DimensionRecord extends RecordData {
private static Logger logger = Logger.getLogger(DimensionRecord.class);
private int numRows;
private int numCols;
private static class Biff7 {
private Biff7() {}
}
public static Biff7 biff7 = new Biff7();
public DimensionRecord(Record t) {
super(t);
byte[] data = t.getData();
if (data.length == 10) {
read10ByteData(data);
} else {
read14ByteData(data);
}
}
public DimensionRecord(Record t, Biff7 biff7) {
super(t);
byte[] data = t.getData();
read10ByteData(data);
}
private void read10ByteData(byte[] data) {
this.numRows = IntegerHelper.getInt(data[2], data[3]);
this.numCols = IntegerHelper.getInt(data[6], data[7]);
}
private void read14ByteData(byte[] data) {
this.numRows = IntegerHelper.getInt(data[4], data[5], data[6], data[7]);
this.numCols = IntegerHelper.getInt(data[10], data[11]);
}
public int getNumberOfRows() {
return this.numRows;
}
public int getNumberOfColumns() {
return this.numCols;
}
}

View file

@ -0,0 +1,69 @@
package jxl.read.biff;
import jxl.CellType;
import jxl.ErrorCell;
import jxl.ErrorFormulaCell;
import jxl.biff.FormattingRecords;
import jxl.biff.FormulaData;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.biff.formula.FormulaErrorCode;
import jxl.biff.formula.FormulaException;
import jxl.biff.formula.FormulaParser;
import jxl.common.Assert;
class ErrorFormulaRecord extends CellValue implements ErrorCell, FormulaData, ErrorFormulaCell {
private int errorCode;
private ExternalSheet externalSheet;
private WorkbookMethods nameTable;
private String formulaString;
private byte[] data;
private FormulaErrorCode error;
public ErrorFormulaRecord(Record t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) {
super(t, fr, si);
this.externalSheet = es;
this.nameTable = nt;
this.data = getRecord().getData();
Assert.verify((this.data[6] == 2));
this.errorCode = this.data[8];
}
public int getErrorCode() {
return this.errorCode;
}
public String getContents() {
if (this.error == null)
this.error = FormulaErrorCode.getErrorCode(this.errorCode);
return (this.error != FormulaErrorCode.UNKNOWN) ? this.error.getDescription() : ("ERROR " + this.errorCode);
}
public CellType getType() {
return CellType.FORMULA_ERROR;
}
public byte[] getFormulaData() throws FormulaException {
if (!getSheet().getWorkbookBof().isBiff8())
throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
byte[] d = new byte[this.data.length - 6];
System.arraycopy(this.data, 6, d, 0, this.data.length - 6);
return d;
}
public String getFormula() throws FormulaException {
if (this.formulaString == null) {
byte[] tokens = new byte[this.data.length - 22];
System.arraycopy(this.data, 22, tokens, 0, tokens.length);
FormulaParser fp = new FormulaParser(tokens, this, this.externalSheet, this.nameTable, getSheet().getWorkbook().getSettings());
fp.parse();
this.formulaString = fp.getFormula();
}
return this.formulaString;
}
}

View file

@ -0,0 +1,27 @@
package jxl.read.biff;
import jxl.CellType;
import jxl.ErrorCell;
import jxl.biff.FormattingRecords;
class ErrorRecord extends CellValue implements ErrorCell {
private int errorCode;
public ErrorRecord(Record t, FormattingRecords fr, SheetImpl si) {
super(t, fr, si);
byte[] data = getRecord().getData();
this.errorCode = data[6];
}
public int getErrorCode() {
return this.errorCode;
}
public String getContents() {
return "ERROR " + this.errorCode;
}
public CellType getType() {
return CellType.ERROR;
}
}

View file

@ -0,0 +1,19 @@
package jxl.read.biff;
import jxl.biff.RecordData;
import jxl.common.Logger;
class Excel9FileRecord extends RecordData {
private static Logger logger = Logger.getLogger(Excel9FileRecord.class);
private boolean excel9file;
public Excel9FileRecord(Record t) {
super(t);
this.excel9file = true;
}
public boolean getExcel9File() {
return this.excel9file;
}
}

View file

@ -0,0 +1,40 @@
package jxl.read.biff;
import jxl.WorkbookSettings;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.StringHelper;
import jxl.common.Logger;
public class ExternalNameRecord extends RecordData {
private static Logger logger = Logger.getLogger(ExternalNameRecord.class);
private String name;
private boolean addInFunction;
ExternalNameRecord(Record t, WorkbookSettings ws) {
super(t);
byte[] data = getRecord().getData();
int options = IntegerHelper.getInt(data[0], data[1]);
if (options == 0)
this.addInFunction = true;
if (!this.addInFunction)
return;
int length = data[6];
boolean unicode = (data[7] != 0);
if (unicode) {
this.name = StringHelper.getUnicodeString(data, length, 8);
} else {
this.name = StringHelper.getString(data, length, 8, ws);
}
}
public boolean isAddInFunction() {
return this.addInFunction;
}
public String getName() {
return this.name;
}
}

View file

@ -0,0 +1,77 @@
package jxl.read.biff;
import jxl.WorkbookSettings;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
public class ExternalSheetRecord extends RecordData {
private static Logger logger = Logger.getLogger(ExternalSheetRecord.class);
private static class Biff7 {
private Biff7() {}
}
public static Biff7 biff7 = new Biff7();
private XTI[] xtiArray;
private static class XTI {
int supbookIndex;
int firstTab;
int lastTab;
XTI(int s, int f, int l) {
this.supbookIndex = s;
this.firstTab = f;
this.lastTab = l;
}
}
ExternalSheetRecord(Record t, WorkbookSettings ws) {
super(t);
byte[] data = getRecord().getData();
int numxtis = IntegerHelper.getInt(data[0], data[1]);
if (data.length < numxtis * 6 + 2) {
this.xtiArray = new XTI[0];
logger.warn("Could not process external sheets. Formulas may be compromised.");
return;
}
this.xtiArray = new XTI[numxtis];
int pos = 2;
for (int i = 0; i < numxtis; i++) {
int s = IntegerHelper.getInt(data[pos], data[pos + 1]);
int f = IntegerHelper.getInt(data[pos + 2], data[pos + 3]);
int l = IntegerHelper.getInt(data[pos + 4], data[pos + 5]);
this.xtiArray[i] = new XTI(s, f, l);
pos += 6;
}
}
ExternalSheetRecord(Record t, WorkbookSettings settings, Biff7 dummy) {
super(t);
logger.warn("External sheet record for Biff 7 not supported");
}
public int getNumRecords() {
return (this.xtiArray != null) ? this.xtiArray.length : 0;
}
public int getSupbookIndex(int index) {
return (this.xtiArray[index]).supbookIndex;
}
public int getFirstTabIndex(int index) {
return (this.xtiArray[index]).firstTab;
}
public int getLastTabIndex(int index) {
return (this.xtiArray[index]).lastTab;
}
public byte[] getData() {
return getRecord().getData();
}
}

View file

@ -0,0 +1,134 @@
package jxl.read.biff;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import jxl.WorkbookSettings;
import jxl.biff.BaseCompoundFile;
import jxl.biff.IntegerHelper;
import jxl.biff.Type;
import jxl.common.Logger;
public class File {
private static Logger logger = Logger.getLogger(File.class);
private byte[] data;
private int filePos;
private int oldPos;
private int initialFileSize;
private int arrayGrowSize;
private CompoundFile compoundFile;
private WorkbookSettings workbookSettings;
public File(InputStream is, WorkbookSettings ws) throws IOException, BiffException {
this.workbookSettings = ws;
this.initialFileSize = this.workbookSettings.getInitialFileSize();
this.arrayGrowSize = this.workbookSettings.getArrayGrowSize();
byte[] d = new byte[this.initialFileSize];
int bytesRead = is.read(d);
int pos = bytesRead;
if (Thread.currentThread().isInterrupted())
throw new InterruptedIOException();
while (bytesRead != -1) {
if (pos >= d.length) {
byte[] newArray = new byte[d.length + this.arrayGrowSize];
System.arraycopy(d, 0, newArray, 0, d.length);
d = newArray;
}
bytesRead = is.read(d, pos, d.length - pos);
pos += bytesRead;
if (Thread.currentThread().isInterrupted())
throw new InterruptedIOException();
}
bytesRead = pos + 1;
if (bytesRead == 0)
throw new BiffException(BiffException.excelFileNotFound);
CompoundFile cf = new CompoundFile(d, ws);
try {
this.data = cf.getStream("workbook");
} catch (BiffException e) {
this.data = cf.getStream("book");
}
if (!this.workbookSettings.getPropertySetsDisabled() && cf.getNumberOfPropertySets() > BaseCompoundFile.STANDARD_PROPERTY_SETS.length)
this.compoundFile = cf;
cf = null;
if (!this.workbookSettings.getGCDisabled())
System.gc();
}
public File(byte[] d) {
this.data = d;
}
Record next() {
Record r = new Record(this.data, this.filePos, this);
return r;
}
Record peek() {
int tempPos = this.filePos;
Record r = new Record(this.data, this.filePos, this);
this.filePos = tempPos;
return r;
}
public void skip(int bytes) {
this.filePos += bytes;
}
public byte[] read(int pos, int length) {
byte[] ret = new byte[length];
try {
System.arraycopy(this.data, pos, ret, 0, length);
} catch (ArrayIndexOutOfBoundsException e) {
logger.error("Array index out of bounds at position " + pos + " record length " + length);
throw e;
}
return ret;
}
public int getPos() {
return this.filePos;
}
public void setPos(int p) {
this.oldPos = this.filePos;
this.filePos = p;
}
public void restorePos() {
this.filePos = this.oldPos;
}
private void moveToFirstBof() {
boolean bofFound = false;
while (!bofFound) {
int code = IntegerHelper.getInt(this.data[this.filePos], this.data[this.filePos + 1]);
if (code == Type.BOF.value) {
bofFound = true;
continue;
}
skip(128);
}
}
public void close() {}
public void clear() {
this.data = null;
}
public boolean hasNext() {
return (this.filePos < this.data.length - 4);
}
CompoundFile getCompoundFile() {
return this.compoundFile;
}
}

View file

@ -0,0 +1,43 @@
package jxl.read.biff;
import jxl.WorkbookSettings;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.StringHelper;
public class FooterRecord extends RecordData {
private String footer;
private static class Biff7 {
private Biff7() {}
}
public static Biff7 biff7 = new Biff7();
FooterRecord(Record t, WorkbookSettings ws) {
super(t);
byte[] data = getRecord().getData();
if (data.length == 0)
return;
int chars = IntegerHelper.getInt(data[0], data[1]);
boolean unicode = (data[2] == 1);
if (unicode) {
this.footer = StringHelper.getUnicodeString(data, chars, 3);
} else {
this.footer = StringHelper.getString(data, chars, 3, ws);
}
}
FooterRecord(Record t, WorkbookSettings ws, Biff7 dummy) {
super(t);
byte[] data = getRecord().getData();
if (data.length == 0)
return;
int chars = data[0];
this.footer = StringHelper.getString(data, chars, 1, ws);
}
String getFooter() {
return this.footer;
}
}

View file

@ -0,0 +1,7 @@
package jxl.read.biff;
import jxl.Cell;
public interface Formula extends Cell {
byte[] getFormulaData();
}

View file

@ -0,0 +1,96 @@
package jxl.read.biff;
import jxl.CellType;
import jxl.WorkbookSettings;
import jxl.biff.DoubleHelper;
import jxl.biff.FormattingRecords;
import jxl.biff.IntegerHelper;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.common.Assert;
import jxl.common.Logger;
class FormulaRecord extends CellValue {
private static Logger logger = Logger.getLogger(FormulaRecord.class);
private CellValue formula;
private boolean shared;
private static class IgnoreSharedFormula {
private IgnoreSharedFormula() {}
}
public static final IgnoreSharedFormula ignoreSharedFormula = new IgnoreSharedFormula();
public FormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si, WorkbookSettings ws) {
super(t, fr, si);
byte[] data = getRecord().getData();
this.shared = false;
int grbit = IntegerHelper.getInt(data[14], data[15]);
if ((grbit & 0x8) != 0) {
this.shared = true;
if (data[6] == 0 && data[12] == -1 && data[13] == -1) {
this.formula = new SharedStringFormulaRecord(t, excelFile, fr, es, nt, si, ws);
} else if (data[6] == 3 && data[12] == -1 && data[13] == -1) {
this.formula = new SharedStringFormulaRecord(t, excelFile, fr, es, nt, si, SharedStringFormulaRecord.EMPTY_STRING);
} else if (data[6] == 2 && data[12] == -1 && data[13] == -1) {
int errorCode = data[8];
this.formula = new SharedErrorFormulaRecord(t, excelFile, errorCode, fr, es, nt, si);
} else if (data[6] == 1 && data[12] == -1 && data[13] == -1) {
boolean value = (data[8] == 1);
this.formula = new SharedBooleanFormulaRecord(t, excelFile, value, fr, es, nt, si);
} else {
double value = DoubleHelper.getIEEEDouble(data, 6);
SharedNumberFormulaRecord snfr = new SharedNumberFormulaRecord(t, excelFile, value, fr, es, nt, si);
snfr.setNumberFormat(fr.getNumberFormat(getXFIndex()));
this.formula = snfr;
}
return;
}
if (data[6] == 0 && data[12] == -1 && data[13] == -1) {
this.formula = new StringFormulaRecord(t, excelFile, fr, es, nt, si, ws);
} else if (data[6] == 1 && data[12] == -1 && data[13] == -1) {
this.formula = new BooleanFormulaRecord(t, fr, es, nt, si);
} else if (data[6] == 2 && data[12] == -1 && data[13] == -1) {
this.formula = new ErrorFormulaRecord(t, fr, es, nt, si);
} else if (data[6] == 3 && data[12] == -1 && data[13] == -1) {
this.formula = new StringFormulaRecord(t, fr, es, nt, si);
} else {
this.formula = new NumberFormulaRecord(t, fr, es, nt, si);
}
}
public FormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, IgnoreSharedFormula i, SheetImpl si, WorkbookSettings ws) {
super(t, fr, si);
byte[] data = getRecord().getData();
this.shared = false;
if (data[6] == 0 && data[12] == -1 && data[13] == -1) {
this.formula = new StringFormulaRecord(t, excelFile, fr, es, nt, si, ws);
} else if (data[6] == 1 && data[12] == -1 && data[13] == -1) {
this.formula = new BooleanFormulaRecord(t, fr, es, nt, si);
} else if (data[6] == 2 && data[12] == -1 && data[13] == -1) {
this.formula = new ErrorFormulaRecord(t, fr, es, nt, si);
} else {
this.formula = new NumberFormulaRecord(t, fr, es, nt, si);
}
}
public String getContents() {
Assert.verify(false);
return "";
}
public CellType getType() {
Assert.verify(false);
return CellType.EMPTY;
}
final CellValue getFormula() {
return this.formula;
}
final boolean isShared() {
return this.shared;
}
}

View file

@ -0,0 +1,31 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
public class GuttersRecord extends RecordData {
private int width;
private int height;
private int rowOutlineLevel;
private int columnOutlineLevel;
public GuttersRecord(Record r) {
super(r);
byte[] data = getRecord().getData();
this.width = IntegerHelper.getInt(data[0], data[1]);
this.height = IntegerHelper.getInt(data[2], data[3]);
this.rowOutlineLevel = IntegerHelper.getInt(data[4], data[5]);
this.columnOutlineLevel = IntegerHelper.getInt(data[6], data[7]);
}
int getRowOutlineLevel() {
return this.rowOutlineLevel;
}
int getColumnOutlineLevel() {
return this.columnOutlineLevel;
}
}

View file

@ -0,0 +1,46 @@
package jxl.read.biff;
import jxl.WorkbookSettings;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.StringHelper;
import jxl.common.Logger;
public class HeaderRecord extends RecordData {
private static Logger logger = Logger.getLogger(HeaderRecord.class);
private String header;
private static class Biff7 {
private Biff7() {}
}
public static Biff7 biff7 = new Biff7();
HeaderRecord(Record t, WorkbookSettings ws) {
super(t);
byte[] data = getRecord().getData();
if (data.length == 0)
return;
int chars = IntegerHelper.getInt(data[0], data[1]);
boolean unicode = (data[2] == 1);
if (unicode) {
this.header = StringHelper.getUnicodeString(data, chars, 3);
} else {
this.header = StringHelper.getString(data, chars, 3, ws);
}
}
HeaderRecord(Record t, WorkbookSettings ws, Biff7 dummy) {
super(t);
byte[] data = getRecord().getData();
if (data.length == 0)
return;
int chars = data[0];
this.header = StringHelper.getString(data, chars, 1, ws);
}
String getHeader() {
return this.header;
}
}

View file

@ -0,0 +1,21 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class HideobjRecord extends RecordData {
private static Logger logger = Logger.getLogger(HideobjRecord.class);
private int hidemode;
public HideobjRecord(Record t) {
super(t);
byte[] data = t.getData();
this.hidemode = IntegerHelper.getInt(data[0], data[1]);
}
public int getHideMode() {
return this.hidemode;
}
}

View file

@ -0,0 +1,45 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class HorizontalPageBreaksRecord extends RecordData {
private final Logger logger = Logger.getLogger(HorizontalPageBreaksRecord.class);
private int[] rowBreaks;
private static class Biff7 {
private Biff7() {}
}
public static Biff7 biff7 = new Biff7();
public HorizontalPageBreaksRecord(Record t) {
super(t);
byte[] data = t.getData();
int numbreaks = IntegerHelper.getInt(data[0], data[1]);
int pos = 2;
this.rowBreaks = new int[numbreaks];
for (int i = 0; i < numbreaks; i++) {
this.rowBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
pos += 6;
}
}
public HorizontalPageBreaksRecord(Record t, Biff7 biff7) {
super(t);
byte[] data = t.getData();
int numbreaks = IntegerHelper.getInt(data[0], data[1]);
int pos = 2;
this.rowBreaks = new int[numbreaks];
for (int i = 0; i < numbreaks; i++) {
this.rowBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
pos += 2;
}
}
public int[] getRowBreaks() {
return this.rowBreaks;
}
}

View file

@ -0,0 +1,186 @@
package jxl.read.biff;
import java.net.MalformedURLException;
import java.net.URL;
import jxl.CellReferenceHelper;
import jxl.Hyperlink;
import jxl.Range;
import jxl.Sheet;
import jxl.WorkbookSettings;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.SheetRangeImpl;
import jxl.biff.StringHelper;
import jxl.common.Logger;
public class HyperlinkRecord extends RecordData implements Hyperlink {
private static Logger logger = Logger.getLogger(HyperlinkRecord.class);
private static class LinkType {
private LinkType() {}
}
private static final LinkType urlLink = new LinkType();
private static final LinkType fileLink = new LinkType();
private static final LinkType workbookLink = new LinkType();
private static final LinkType unknown = new LinkType();
HyperlinkRecord(Record t, Sheet s, WorkbookSettings ws) {
super(t);
byte[] data = getRecord().getData();
this.firstRow = IntegerHelper.getInt(data[0], data[1]);
this.lastRow = IntegerHelper.getInt(data[2], data[3]);
this.firstColumn = IntegerHelper.getInt(data[4], data[5]);
this.lastColumn = IntegerHelper.getInt(data[6], data[7]);
this.range = new SheetRangeImpl(s, this.firstColumn, this.firstRow, this.lastColumn, this.lastRow);
int options = IntegerHelper.getInt(data[28], data[29], data[30], data[31]);
boolean description = ((options & 0x14) != 0);
int startpos = 32;
int descbytes = 0;
if (description) {
int descchars = IntegerHelper.getInt(data[startpos], data[startpos + 1], data[startpos + 2], data[startpos + 3]);
descbytes = descchars * 2 + 4;
}
startpos += descbytes;
boolean targetFrame = ((options & 0x80) != 0);
int targetbytes = 0;
if (targetFrame) {
int targetchars = IntegerHelper.getInt(data[startpos], data[startpos + 1], data[startpos + 2], data[startpos + 3]);
targetbytes = targetchars * 2 + 4;
}
startpos += targetbytes;
if ((options & 0x3) == 3) {
this.linkType = urlLink;
if (data[startpos] == 3)
this.linkType = fileLink;
} else if ((options & 0x1) != 0) {
this.linkType = fileLink;
if (data[startpos] == -32)
this.linkType = urlLink;
} else if ((options & 0x8) != 0) {
this.linkType = workbookLink;
}
if (this.linkType == urlLink) {
String urlString = null;
try {
startpos += 16;
int bytes = IntegerHelper.getInt(data[startpos], data[startpos + 1], data[startpos + 2], data[startpos + 3]);
urlString = StringHelper.getUnicodeString(data, bytes / 2 - 1, startpos + 4);
this.url = new URL(urlString);
} catch (MalformedURLException e) {
logger.warn("URL " + urlString + " is malformed. Trying a file");
try {
this.linkType = fileLink;
this.file = new java.io.File(urlString);
} catch (Exception e3) {
logger.warn("Cannot set to file. Setting a default URL");
try {
this.linkType = urlLink;
this.url = new URL("http://www.andykhan.com/jexcelapi/index.html");
} catch (MalformedURLException e2) {}
}
} catch (Throwable e) {
StringBuffer sb1 = new StringBuffer();
StringBuffer sb2 = new StringBuffer();
CellReferenceHelper.getCellReference(this.firstColumn, this.firstRow, sb1);
CellReferenceHelper.getCellReference(this.lastColumn, this.lastRow, sb2);
sb1.insert(0, "Exception when parsing URL ");
sb1.append('"').append(sb2.toString()).append("\". Using default.");
logger.warn(sb1, e);
try {
this.url = new URL("http://www.andykhan.com/jexcelapi/index.html");
} catch (MalformedURLException e2) {}
}
} else if (this.linkType == fileLink) {
try {
startpos += 16;
int upLevelCount = IntegerHelper.getInt(data[startpos], data[startpos + 1]);
int chars = IntegerHelper.getInt(data[startpos + 2], data[startpos + 3], data[startpos + 4], data[startpos + 5]);
String fileName = StringHelper.getString(data, chars - 1, startpos + 6, ws);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < upLevelCount; i++)
sb.append("..\\");
sb.append(fileName);
this.file = new java.io.File(sb.toString());
} catch (Throwable e) {
logger.warn("Exception when parsing file " + e.getClass().getName() + ".");
this.file = new java.io.File(".");
}
} else if (this.linkType == workbookLink) {
int chars = IntegerHelper.getInt(data[32], data[33], data[34], data[35]);
this.location = StringHelper.getUnicodeString(data, chars - 1, 36);
} else {
logger.warn("Cannot determine link type");
return;
}
}
private LinkType linkType = unknown;
private int firstRow;
private int lastRow;
private int firstColumn;
private int lastColumn;
private URL url;
private java.io.File file;
private String location;
private SheetRangeImpl range;
public boolean isFile() {
return (this.linkType == fileLink);
}
public boolean isURL() {
return (this.linkType == urlLink);
}
public boolean isLocation() {
return (this.linkType == workbookLink);
}
public int getRow() {
return this.firstRow;
}
public int getColumn() {
return this.firstColumn;
}
public int getLastRow() {
return this.lastRow;
}
public int getLastColumn() {
return this.lastColumn;
}
public URL getURL() {
return this.url;
}
public java.io.File getFile() {
return this.file;
}
public Record getRecord() {
return super.getRecord();
}
public Range getRange() {
return this.range;
}
public String getLocation() {
return this.location;
}
}

View file

@ -0,0 +1,50 @@
package jxl.read.biff;
import jxl.CellType;
import jxl.LabelCell;
import jxl.WorkbookSettings;
import jxl.biff.FormattingRecords;
import jxl.biff.IntegerHelper;
import jxl.biff.StringHelper;
class LabelRecord extends CellValue implements LabelCell {
private int length;
private String string;
private static class Biff7 {
private Biff7() {}
}
public static Biff7 biff7 = new Biff7();
public LabelRecord(Record t, FormattingRecords fr, SheetImpl si, WorkbookSettings ws) {
super(t, fr, si);
byte[] data = getRecord().getData();
this.length = IntegerHelper.getInt(data[6], data[7]);
if (data[8] == 0) {
this.string = StringHelper.getString(data, this.length, 9, ws);
} else {
this.string = StringHelper.getUnicodeString(data, this.length, 9);
}
}
public LabelRecord(Record t, FormattingRecords fr, SheetImpl si, WorkbookSettings ws, Biff7 dummy) {
super(t, fr, si);
byte[] data = getRecord().getData();
this.length = IntegerHelper.getInt(data[6], data[7]);
this.string = StringHelper.getString(data, this.length, 8, ws);
}
public String getString() {
return this.string;
}
public String getContents() {
return this.string;
}
public CellType getType() {
return CellType.LABEL;
}
}

View file

@ -0,0 +1,31 @@
package jxl.read.biff;
import jxl.CellType;
import jxl.LabelCell;
import jxl.biff.FormattingRecords;
import jxl.biff.IntegerHelper;
class LabelSSTRecord extends CellValue implements LabelCell {
private int index;
private String string;
public LabelSSTRecord(Record t, SSTRecord stringTable, FormattingRecords fr, SheetImpl si) {
super(t, fr, si);
byte[] data = getRecord().getData();
this.index = IntegerHelper.getInt(data[6], data[7], data[8], data[9]);
this.string = stringTable.getString(this.index);
}
public String getString() {
return this.string;
}
public String getContents() {
return this.string;
}
public CellType getType() {
return CellType.LABEL;
}
}

View file

@ -0,0 +1,9 @@
package jxl.read.biff;
import jxl.biff.Type;
class LeftMarginRecord extends MarginRecord {
LeftMarginRecord(Record r) {
super(Type.LEFTMARGIN, r);
}
}

View file

@ -0,0 +1,19 @@
package jxl.read.biff;
import jxl.biff.DoubleHelper;
import jxl.biff.RecordData;
import jxl.biff.Type;
abstract class MarginRecord extends RecordData {
private double margin;
protected MarginRecord(Type t, Record r) {
super(t);
byte[] data = r.getData();
this.margin = DoubleHelper.getIEEEDouble(data, 0);
}
double getMargin() {
return this.margin;
}
}

View file

@ -0,0 +1,35 @@
package jxl.read.biff;
import jxl.Range;
import jxl.Sheet;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.SheetRangeImpl;
public class MergedCellsRecord extends RecordData {
private Range[] ranges;
MergedCellsRecord(Record t, Sheet s) {
super(t);
byte[] data = getRecord().getData();
int numRanges = IntegerHelper.getInt(data[0], data[1]);
this.ranges = new Range[numRanges];
int pos = 2;
int firstRow = 0;
int lastRow = 0;
int firstCol = 0;
int lastCol = 0;
for (int i = 0; i < numRanges; i++) {
firstRow = IntegerHelper.getInt(data[pos], data[pos + 1]);
lastRow = IntegerHelper.getInt(data[pos + 2], data[pos + 3]);
firstCol = IntegerHelper.getInt(data[pos + 4], data[pos + 5]);
lastCol = IntegerHelper.getInt(data[pos + 6], data[pos + 7]);
this.ranges[i] = new SheetRangeImpl(s, firstCol, firstRow, lastCol, lastRow);
pos += 8;
}
}
public Range[] getRanges() {
return this.ranges;
}
}

View file

@ -0,0 +1,81 @@
package jxl.read.biff;
import jxl.Cell;
import jxl.CellFeatures;
import jxl.CellType;
import jxl.biff.FormattingRecords;
import jxl.common.Logger;
import jxl.format.CellFormat;
class MulBlankCell implements Cell, CellFeaturesAccessor {
private static Logger logger = Logger.getLogger(MulBlankCell.class);
private int row;
private int column;
private CellFormat cellFormat;
private int xfIndex;
private FormattingRecords formattingRecords;
private boolean initialized;
private SheetImpl sheet;
private CellFeatures features;
public MulBlankCell(int r, int c, int xfi, FormattingRecords fr, SheetImpl si) {
this.row = r;
this.column = c;
this.xfIndex = xfi;
this.formattingRecords = fr;
this.sheet = si;
this.initialized = false;
}
public final int getRow() {
return this.row;
}
public final int getColumn() {
return this.column;
}
public String getContents() {
return "";
}
public CellType getType() {
return CellType.EMPTY;
}
public CellFormat getCellFormat() {
if (!this.initialized) {
this.cellFormat = this.formattingRecords.getXFRecord(this.xfIndex);
this.initialized = true;
}
return this.cellFormat;
}
public boolean isHidden() {
ColumnInfoRecord cir = this.sheet.getColumnInfo(this.column);
if (cir != null && cir.getWidth() == 0)
return true;
RowRecord rr = this.sheet.getRowInfo(this.row);
if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed()))
return true;
return false;
}
public CellFeatures getCellFeatures() {
return this.features;
}
public void setCellFeatures(CellFeatures cf) {
if (this.features != null)
logger.warn("current cell features not null - overwriting");
this.features = cf;
}
}

View file

@ -0,0 +1,55 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class MulBlankRecord extends RecordData {
private static Logger logger = Logger.getLogger(MulBlankRecord.class);
private int row;
private int colFirst;
private int colLast;
private int numblanks;
private int[] xfIndices;
public MulBlankRecord(Record t) {
super(t);
byte[] data = getRecord().getData();
int length = getRecord().getLength();
this.row = IntegerHelper.getInt(data[0], data[1]);
this.colFirst = IntegerHelper.getInt(data[2], data[3]);
this.colLast = IntegerHelper.getInt(data[length - 2], data[length - 1]);
this.numblanks = this.colLast - this.colFirst + 1;
this.xfIndices = new int[this.numblanks];
readBlanks(data);
}
private void readBlanks(byte[] data) {
int pos = 4;
for (int i = 0; i < this.numblanks; i++) {
this.xfIndices[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
pos += 2;
}
}
public int getRow() {
return this.row;
}
public int getFirstColumn() {
return this.colFirst;
}
public int getNumberOfColumns() {
return this.numblanks;
}
public int getXFIndex(int index) {
return this.xfIndices[index];
}
}

View file

@ -0,0 +1,64 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class MulRKRecord extends RecordData {
private static Logger logger = Logger.getLogger(MulRKRecord.class);
private int row;
private int colFirst;
private int colLast;
private int numrks;
private int[] rknumbers;
private int[] xfIndices;
public MulRKRecord(Record t) {
super(t);
byte[] data = getRecord().getData();
int length = getRecord().getLength();
this.row = IntegerHelper.getInt(data[0], data[1]);
this.colFirst = IntegerHelper.getInt(data[2], data[3]);
this.colLast = IntegerHelper.getInt(data[length - 2], data[length - 1]);
this.numrks = this.colLast - this.colFirst + 1;
this.rknumbers = new int[this.numrks];
this.xfIndices = new int[this.numrks];
readRks(data);
}
private void readRks(byte[] data) {
int pos = 4;
for (int i = 0; i < this.numrks; i++) {
this.xfIndices[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
int rk = IntegerHelper.getInt(data[pos + 2], data[pos + 3], data[pos + 4], data[pos + 5]);
this.rknumbers[i] = rk;
pos += 6;
}
}
public int getRow() {
return this.row;
}
public int getFirstColumn() {
return this.colFirst;
}
public int getNumberOfColumns() {
return this.numrks;
}
public int getRKNumber(int index) {
return this.rknumbers[index];
}
public int getXFIndex(int index) {
return this.xfIndices[index];
}
}

View file

@ -0,0 +1,292 @@
package jxl.read.biff;
import java.util.ArrayList;
import jxl.WorkbookSettings;
import jxl.biff.BuiltInName;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.StringHelper;
import jxl.common.Assert;
import jxl.common.Logger;
public class NameRecord extends RecordData {
private static Logger logger = Logger.getLogger(NameRecord.class);
private String name;
private BuiltInName builtInName;
private int index;
private int sheetRef = 0;
private boolean isbiff8;
private static class Biff7 {
private Biff7() {}
}
public static Biff7 biff7 = new Biff7();
private static final int commandMacro = 12;
private static final int builtIn = 32;
private static final int cellReference = 58;
private static final int areaReference = 59;
private static final int subExpression = 41;
private static final int union = 16;
private ArrayList ranges;
public class NameRange {
private int columnFirst;
private int rowFirst;
private int columnLast;
private int rowLast;
private int externalSheet;
NameRange(int s1, int c1, int r1, int c2, int r2) {
this.columnFirst = c1;
this.rowFirst = r1;
this.columnLast = c2;
this.rowLast = r2;
this.externalSheet = s1;
}
public int getFirstColumn() {
return this.columnFirst;
}
public int getFirstRow() {
return this.rowFirst;
}
public int getLastColumn() {
return this.columnLast;
}
public int getLastRow() {
return this.rowLast;
}
public int getExternalSheet() {
return this.externalSheet;
}
}
NameRecord(Record t, WorkbookSettings ws, int ind) {
super(t);
this.index = ind;
this.isbiff8 = true;
try {
this.ranges = new ArrayList();
byte[] data = getRecord().getData();
int option = IntegerHelper.getInt(data[0], data[1]);
int length = data[3];
this.sheetRef = IntegerHelper.getInt(data[8], data[9]);
if ((option & 0x20) != 0) {
this.builtInName = BuiltInName.getBuiltInName(data[15]);
} else {
this.name = StringHelper.getString(data, length, 15, ws);
}
if ((option & 0xC) != 0)
return;
int pos = length + 15;
if (data[pos] == 58) {
int sheet = IntegerHelper.getInt(data[pos + 1], data[pos + 2]);
int row = IntegerHelper.getInt(data[pos + 3], data[pos + 4]);
int columnMask = IntegerHelper.getInt(data[pos + 5], data[pos + 6]);
int column = columnMask & 0xFF;
Assert.verify(((columnMask & 0xC0000) == 0));
NameRange r = new NameRange(sheet, column, row, column, row);
this.ranges.add(r);
} else if (data[pos] == 59) {
int sheet1 = 0;
int r1 = 0;
int columnMask = 0;
int c1 = 0;
int r2 = 0;
int c2 = 0;
NameRange range = null;
while (pos < data.length) {
sheet1 = IntegerHelper.getInt(data[pos + 1], data[pos + 2]);
r1 = IntegerHelper.getInt(data[pos + 3], data[pos + 4]);
r2 = IntegerHelper.getInt(data[pos + 5], data[pos + 6]);
columnMask = IntegerHelper.getInt(data[pos + 7], data[pos + 8]);
c1 = columnMask & 0xFF;
Assert.verify(((columnMask & 0xC0000) == 0));
columnMask = IntegerHelper.getInt(data[pos + 9], data[pos + 10]);
c2 = columnMask & 0xFF;
Assert.verify(((columnMask & 0xC0000) == 0));
range = new NameRange(sheet1, c1, r1, c2, r2);
this.ranges.add(range);
pos += 11;
}
} else if (data[pos] == 41) {
int sheet1 = 0;
int r1 = 0;
int columnMask = 0;
int c1 = 0;
int r2 = 0;
int c2 = 0;
NameRange range = null;
if (pos < data.length && data[pos] != 58 && data[pos] != 59)
if (data[pos] == 41) {
pos += 3;
} else if (data[pos] == 16) {
pos++;
}
while (pos < data.length) {
sheet1 = IntegerHelper.getInt(data[pos + 1], data[pos + 2]);
r1 = IntegerHelper.getInt(data[pos + 3], data[pos + 4]);
r2 = IntegerHelper.getInt(data[pos + 5], data[pos + 6]);
columnMask = IntegerHelper.getInt(data[pos + 7], data[pos + 8]);
c1 = columnMask & 0xFF;
Assert.verify(((columnMask & 0xC0000) == 0));
columnMask = IntegerHelper.getInt(data[pos + 9], data[pos + 10]);
c2 = columnMask & 0xFF;
Assert.verify(((columnMask & 0xC0000) == 0));
range = new NameRange(sheet1, c1, r1, c2, r2);
this.ranges.add(range);
pos += 11;
if (pos < data.length && data[pos] != 58 && data[pos] != 59) {
if (data[pos] == 41) {
pos += 3;
continue;
}
if (data[pos] == 16)
pos++;
}
}
} else {
String n = (this.name != null) ? this.name : this.builtInName.getName();
logger.warn("Cannot read name ranges for " + n + " - setting to empty");
NameRange range = new NameRange(0, 0, 0, 0, 0);
this.ranges.add(range);
}
} catch (Throwable t1) {
logger.warn("Cannot read name");
this.name = "ERROR";
}
}
NameRecord(Record t, WorkbookSettings ws, int ind, Biff7 dummy) {
super(t);
this.index = ind;
this.isbiff8 = false;
try {
this.ranges = new ArrayList();
byte[] data = getRecord().getData();
int length = data[3];
this.sheetRef = IntegerHelper.getInt(data[8], data[9]);
this.name = StringHelper.getString(data, length, 14, ws);
int pos = length + 14;
if (pos >= data.length)
return;
if (data[pos] == 58) {
int sheet = IntegerHelper.getInt(data[pos + 11], data[pos + 12]);
int row = IntegerHelper.getInt(data[pos + 15], data[pos + 16]);
int column = data[pos + 17];
NameRange r = new NameRange(sheet, column, row, column, row);
this.ranges.add(r);
} else if (data[pos] == 59) {
int sheet1 = 0;
int r1 = 0;
int c1 = 0;
int r2 = 0;
int c2 = 0;
NameRange range = null;
while (pos < data.length) {
sheet1 = IntegerHelper.getInt(data[pos + 11], data[pos + 12]);
r1 = IntegerHelper.getInt(data[pos + 15], data[pos + 16]);
r2 = IntegerHelper.getInt(data[pos + 17], data[pos + 18]);
c1 = data[pos + 19];
c2 = data[pos + 20];
range = new NameRange(sheet1, c1, r1, c2, r2);
this.ranges.add(range);
pos += 21;
}
} else if (data[pos] == 41) {
int sheet1 = 0;
int sheet2 = 0;
int r1 = 0;
int c1 = 0;
int r2 = 0;
int c2 = 0;
NameRange range = null;
if (pos < data.length && data[pos] != 58 && data[pos] != 59)
if (data[pos] == 41) {
pos += 3;
} else if (data[pos] == 16) {
pos++;
}
while (pos < data.length) {
sheet1 = IntegerHelper.getInt(data[pos + 11], data[pos + 12]);
r1 = IntegerHelper.getInt(data[pos + 15], data[pos + 16]);
r2 = IntegerHelper.getInt(data[pos + 17], data[pos + 18]);
c1 = data[pos + 19];
c2 = data[pos + 20];
range = new NameRange(sheet1, c1, r1, c2, r2);
this.ranges.add(range);
pos += 21;
if (pos < data.length && data[pos] != 58 && data[pos] != 59) {
if (data[pos] == 41) {
pos += 3;
continue;
}
if (data[pos] == 16)
pos++;
}
}
}
} catch (Throwable t1) {
logger.warn("Cannot read name.");
this.name = "ERROR";
}
}
public String getName() {
return this.name;
}
public BuiltInName getBuiltInName() {
return this.builtInName;
}
public NameRange[] getRanges() {
NameRange[] nr = new NameRange[this.ranges.size()];
return (NameRange[])this.ranges.toArray(nr);
}
int getIndex() {
return this.index;
}
public int getSheetRef() {
return this.sheetRef;
}
public void setSheetRef(int i) {
this.sheetRef = i;
}
public byte[] getData() {
return getRecord().getData();
}
public boolean isBiff8() {
return this.isbiff8;
}
public boolean isGlobal() {
return (this.sheetRef == 0);
}
}

View file

@ -0,0 +1,17 @@
package jxl.read.biff;
import jxl.biff.RecordData;
class NineteenFourRecord extends RecordData {
private boolean nineteenFour;
public NineteenFourRecord(Record t) {
super(t);
byte[] data = getRecord().getData();
this.nineteenFour = (data[0] == 1);
}
public boolean is1904() {
return this.nineteenFour;
}
}

View file

@ -0,0 +1,79 @@
package jxl.read.biff;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import jxl.CellType;
import jxl.NumberCell;
import jxl.NumberFormulaCell;
import jxl.biff.DoubleHelper;
import jxl.biff.FormattingRecords;
import jxl.biff.FormulaData;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.biff.formula.FormulaException;
import jxl.biff.formula.FormulaParser;
import jxl.common.Logger;
class NumberFormulaRecord extends CellValue implements NumberCell, FormulaData, NumberFormulaCell {
private static Logger logger = Logger.getLogger(NumberFormulaRecord.class);
private double value;
private NumberFormat format;
private static final DecimalFormat defaultFormat = new DecimalFormat("#.###");
private String formulaString;
private ExternalSheet externalSheet;
private WorkbookMethods nameTable;
private byte[] data;
public NumberFormulaRecord(Record t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) {
super(t, fr, si);
this.externalSheet = es;
this.nameTable = nt;
this.data = getRecord().getData();
this.format = fr.getNumberFormat(getXFIndex());
if (this.format == null)
this.format = defaultFormat;
this.value = DoubleHelper.getIEEEDouble(this.data, 6);
}
public double getValue() {
return this.value;
}
public String getContents() {
return !Double.isNaN(this.value) ? this.format.format(this.value) : "";
}
public CellType getType() {
return CellType.NUMBER_FORMULA;
}
public byte[] getFormulaData() throws FormulaException {
if (!getSheet().getWorkbookBof().isBiff8())
throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
byte[] d = new byte[this.data.length - 6];
System.arraycopy(this.data, 6, d, 0, this.data.length - 6);
return d;
}
public String getFormula() throws FormulaException {
if (this.formulaString == null) {
byte[] tokens = new byte[this.data.length - 22];
System.arraycopy(this.data, 22, tokens, 0, tokens.length);
FormulaParser fp = new FormulaParser(tokens, this, this.externalSheet, this.nameTable, getSheet().getWorkbook().getSettings());
fp.parse();
this.formulaString = fp.getFormula();
}
return this.formulaString;
}
public NumberFormat getNumberFormat() {
return this.format;
}
}

View file

@ -0,0 +1,44 @@
package jxl.read.biff;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import jxl.CellType;
import jxl.NumberCell;
import jxl.biff.DoubleHelper;
import jxl.biff.FormattingRecords;
import jxl.common.Logger;
class NumberRecord extends CellValue implements NumberCell {
private static Logger logger = Logger.getLogger(NumberRecord.class);
private double value;
private NumberFormat format;
private static DecimalFormat defaultFormat = new DecimalFormat("#.###");
public NumberRecord(Record t, FormattingRecords fr, SheetImpl si) {
super(t, fr, si);
byte[] data = getRecord().getData();
this.value = DoubleHelper.getIEEEDouble(data, 6);
this.format = fr.getNumberFormat(getXFIndex());
if (this.format == null)
this.format = defaultFormat;
}
public double getValue() {
return this.value;
}
public String getContents() {
return this.format.format(this.value);
}
public CellType getType() {
return CellType.NUMBER;
}
public NumberFormat getNumberFormat() {
return this.format;
}
}

View file

@ -0,0 +1,99 @@
package jxl.read.biff;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import jxl.CellFeatures;
import jxl.CellType;
import jxl.NumberCell;
import jxl.biff.FormattingRecords;
import jxl.format.CellFormat;
class NumberValue implements NumberCell, CellFeaturesAccessor {
private int row;
private int column;
private double value;
private NumberFormat format;
private CellFormat cellFormat;
private CellFeatures features;
private int xfIndex;
private FormattingRecords formattingRecords;
private boolean initialized;
private SheetImpl sheet;
private static DecimalFormat defaultFormat = new DecimalFormat("#.###");
public NumberValue(int r, int c, double val, int xfi, FormattingRecords fr, SheetImpl si) {
this.row = r;
this.column = c;
this.value = val;
this.format = defaultFormat;
this.xfIndex = xfi;
this.formattingRecords = fr;
this.sheet = si;
this.initialized = false;
}
final void setNumberFormat(NumberFormat f) {
if (f != null)
this.format = f;
}
public final int getRow() {
return this.row;
}
public final int getColumn() {
return this.column;
}
public double getValue() {
return this.value;
}
public String getContents() {
return this.format.format(this.value);
}
public CellType getType() {
return CellType.NUMBER;
}
public CellFormat getCellFormat() {
if (!this.initialized) {
this.cellFormat = this.formattingRecords.getXFRecord(this.xfIndex);
this.initialized = true;
}
return this.cellFormat;
}
public boolean isHidden() {
ColumnInfoRecord cir = this.sheet.getColumnInfo(this.column);
if (cir != null && cir.getWidth() == 0)
return true;
RowRecord rr = this.sheet.getRowInfo(this.row);
if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed()))
return true;
return false;
}
public NumberFormat getNumberFormat() {
return this.format;
}
public CellFeatures getCellFeatures() {
return this.features;
}
public void setCellFeatures(CellFeatures cf) {
this.features = cf;
}
}

View file

@ -0,0 +1,13 @@
package jxl.read.biff;
import jxl.biff.RecordData;
public class PLSRecord extends RecordData {
public PLSRecord(Record r) {
super(r);
}
public byte[] getData() {
return getRecord().getData();
}
}

View file

@ -0,0 +1,13 @@
package jxl.read.biff;
import jxl.biff.RecordData;
public class PaletteRecord extends RecordData {
PaletteRecord(Record t) {
super(t);
}
public byte[] getData() {
return getRecord().getData();
}
}

View file

@ -0,0 +1,28 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class PaneRecord extends RecordData {
private static Logger logger = Logger.getLogger(PaneRecord.class);
private int rowsVisible;
private int columnsVisible;
public PaneRecord(Record t) {
super(t);
byte[] data = t.getData();
this.columnsVisible = IntegerHelper.getInt(data[0], data[1]);
this.rowsVisible = IntegerHelper.getInt(data[2], data[3]);
}
public final int getRowsVisible() {
return this.rowsVisible;
}
public final int getColumnsVisible() {
return this.columnsVisible;
}
}

View file

@ -0,0 +1,7 @@
package jxl.read.biff;
public class PasswordException extends BiffException {
public PasswordException() {
super(passwordProtected);
}
}

View file

@ -0,0 +1,21 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.Type;
class PasswordRecord extends RecordData {
private String password;
private int passwordHash;
public PasswordRecord(Record t) {
super(Type.PASSWORD);
byte[] data = t.getData();
this.passwordHash = IntegerHelper.getInt(data[0], data[1]);
}
public int getPasswordHash() {
return this.passwordHash;
}
}

View file

@ -0,0 +1,17 @@
package jxl.read.biff;
import jxl.biff.RecordData;
class PrintGridLinesRecord extends RecordData {
private boolean printGridLines;
public PrintGridLinesRecord(Record pgl) {
super(pgl);
byte[] data = pgl.getData();
this.printGridLines = (data[0] == 1);
}
public boolean getPrintGridLines() {
return this.printGridLines;
}
}

View file

@ -0,0 +1,17 @@
package jxl.read.biff;
import jxl.biff.RecordData;
class PrintHeadersRecord extends RecordData {
private boolean printHeaders;
public PrintHeadersRecord(Record ph) {
super(ph);
byte[] data = ph.getData();
this.printHeaders = (data[0] == 1);
}
public boolean getPrintHeaders() {
return this.printHeaders;
}
}

View file

@ -0,0 +1,19 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
class ProtectRecord extends RecordData {
private boolean prot;
ProtectRecord(Record t) {
super(t);
byte[] data = getRecord().getData();
int protflag = IntegerHelper.getInt(data[0], data[1]);
this.prot = (protflag == 1);
}
boolean isProtected() {
return this.prot;
}
}

View file

@ -0,0 +1,19 @@
package jxl.read.biff;
final class RKHelper {
public static double getDouble(int rk) {
if ((rk & 0x2) != 0) {
int intval = rk >> 2;
double d = (double)intval;
if ((rk & 0x1) != 0)
d /= 100.0D;
return d;
}
long valbits = (long)(rk & 0xFFFFFFFC);
valbits <<= 32L;
double value = Double.longBitsToDouble(valbits);
if ((rk & 0x1) != 0)
value /= 100.0D;
return value;
}
}

View file

@ -0,0 +1,45 @@
package jxl.read.biff;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import jxl.CellType;
import jxl.NumberCell;
import jxl.biff.FormattingRecords;
import jxl.biff.IntegerHelper;
import jxl.common.Logger;
class RKRecord extends CellValue implements NumberCell {
private static Logger logger = Logger.getLogger(RKRecord.class);
private double value;
private NumberFormat format;
private static DecimalFormat defaultFormat = new DecimalFormat("#.###");
public RKRecord(Record t, FormattingRecords fr, SheetImpl si) {
super(t, fr, si);
byte[] data = getRecord().getData();
int rknum = IntegerHelper.getInt(data[6], data[7], data[8], data[9]);
this.value = RKHelper.getDouble(rknum);
this.format = fr.getNumberFormat(getXFIndex());
if (this.format == null)
this.format = defaultFormat;
}
public double getValue() {
return this.value;
}
public String getContents() {
return this.format.format(this.value);
}
public CellType getType() {
return CellType.NUMBER;
}
public NumberFormat getNumberFormat() {
return this.format;
}
}

View file

@ -0,0 +1,39 @@
package jxl.read.biff;
import jxl.CellType;
import jxl.LabelCell;
import jxl.WorkbookSettings;
import jxl.biff.FormattingRecords;
import jxl.biff.IntegerHelper;
import jxl.biff.StringHelper;
class RStringRecord extends CellValue implements LabelCell {
private int length;
private String string;
private static class Biff7 {
private Biff7() {}
}
public static Biff7 biff7 = new Biff7();
public RStringRecord(Record t, FormattingRecords fr, SheetImpl si, WorkbookSettings ws, Biff7 dummy) {
super(t, fr, si);
byte[] data = getRecord().getData();
this.length = IntegerHelper.getInt(data[6], data[7]);
this.string = StringHelper.getString(data, this.length, 8, ws);
}
public String getString() {
return this.string;
}
public String getContents() {
return this.string;
}
public CellType getType() {
return CellType.LABEL;
}
}

View file

@ -0,0 +1,81 @@
package jxl.read.biff;
import java.util.ArrayList;
import jxl.biff.IntegerHelper;
import jxl.biff.Type;
import jxl.common.Logger;
public final class Record {
private static final Logger logger = Logger.getLogger(Record.class);
private int code;
private Type type;
private int length;
private int dataPos;
private File file;
private byte[] data;
private ArrayList continueRecords;
Record(byte[] d, int offset, File f) {
this.code = IntegerHelper.getInt(d[offset], d[offset + 1]);
this.length = IntegerHelper.getInt(d[offset + 2], d[offset + 3]);
this.file = f;
this.file.skip(4);
this.dataPos = f.getPos();
this.file.skip(this.length);
this.type = Type.getType(this.code);
}
public Type getType() {
return this.type;
}
public int getLength() {
return this.length;
}
public byte[] getData() {
if (this.data == null)
this.data = this.file.read(this.dataPos, this.length);
if (this.continueRecords != null) {
int size = 0;
byte[][] contData = new byte[this.continueRecords.size()][];
for (int i = 0; i < this.continueRecords.size(); i++) {
Record r = this.continueRecords.get(i);
contData[i] = r.getData();
byte[] d2 = contData[i];
size += d2.length;
}
byte[] d3 = new byte[this.data.length + size];
System.arraycopy(this.data, 0, d3, 0, this.data.length);
int pos = this.data.length;
for (int j = 0; j < contData.length; j++) {
byte[] d2 = contData[j];
System.arraycopy(d2, 0, d3, pos, d2.length);
pos += d2.length;
}
this.data = d3;
}
return this.data;
}
public int getCode() {
return this.code;
}
void setType(Type t) {
this.type = t;
}
public void addContinueRecord(Record d) {
if (this.continueRecords == null)
this.continueRecords = new ArrayList();
this.continueRecords.add(d);
}
}

View file

@ -0,0 +1,22 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class RefreshAllRecord extends RecordData {
private static Logger logger = Logger.getLogger(RefreshAllRecord.class);
private boolean refreshAll;
public RefreshAllRecord(Record t) {
super(t);
byte[] data = t.getData();
int mode = IntegerHelper.getInt(data[0], data[1]);
this.refreshAll = (mode == 1);
}
public boolean getRefreshAll() {
return this.refreshAll;
}
}

View file

@ -0,0 +1,9 @@
package jxl.read.biff;
import jxl.biff.Type;
class RightMarginRecord extends MarginRecord {
RightMarginRecord(Record r) {
super(Type.RIGHTMARGIN, r);
}
}

View file

@ -0,0 +1,77 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
public class RowRecord extends RecordData {
private static Logger logger = Logger.getLogger(RowRecord.class);
private int rowNumber;
private int rowHeight;
private boolean collapsed;
private boolean defaultFormat;
private boolean matchesDefFontHeight;
private int xfIndex;
private int outlineLevel;
private boolean groupStart;
private static final int defaultHeightIndicator = 255;
RowRecord(Record t) {
super(t);
byte[] data = getRecord().getData();
this.rowNumber = IntegerHelper.getInt(data[0], data[1]);
this.rowHeight = IntegerHelper.getInt(data[6], data[7]);
int options = IntegerHelper.getInt(data[12], data[13], data[14], data[15]);
this.outlineLevel = options & 0x7;
this.groupStart = ((options & 0x10) != 0);
this.collapsed = ((options & 0x20) != 0);
this.matchesDefFontHeight = ((options & 0x40) == 0);
this.defaultFormat = ((options & 0x80) != 0);
this.xfIndex = (options & 0xFFF0000) >> 16;
}
boolean isDefaultHeight() {
return (this.rowHeight == 255);
}
public boolean matchesDefaultFontHeight() {
return this.matchesDefFontHeight;
}
public int getRowNumber() {
return this.rowNumber;
}
public int getOutlineLevel() {
return this.outlineLevel;
}
public boolean getGroupStart() {
return this.groupStart;
}
public int getRowHeight() {
return this.rowHeight;
}
public boolean isCollapsed() {
return this.collapsed;
}
public int getXFIndex() {
return this.xfIndex;
}
public boolean hasDefaultFormat() {
return this.defaultFormat;
}
}

View file

@ -0,0 +1,22 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.Type;
class SCLRecord extends RecordData {
private int numerator;
private int denominator;
protected SCLRecord(Record r) {
super(Type.SCL);
byte[] data = r.getData();
this.numerator = IntegerHelper.getInt(data[0], data[1]);
this.denominator = IntegerHelper.getInt(data[2], data[3]);
}
public int getZoomFactor() {
return this.numerator * 100 / this.denominator;
}
}

View file

@ -0,0 +1,180 @@
package jxl.read.biff;
import jxl.WorkbookSettings;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.StringHelper;
import jxl.common.Assert;
class SSTRecord extends RecordData {
private int totalStrings;
private int uniqueStrings;
private String[] strings;
private int[] continuationBreaks;
private static class ByteArrayHolder {
public byte[] bytes;
private ByteArrayHolder() {}
}
private static class BooleanHolder {
public boolean value;
private BooleanHolder() {}
}
public SSTRecord(Record t, Record[] continuations, WorkbookSettings ws) {
super(t);
int totalRecordLength = 0;
for (int i = 0; i < continuations.length; i++)
totalRecordLength += continuations[i].getLength();
totalRecordLength += getRecord().getLength();
byte[] data = new byte[totalRecordLength];
int pos = 0;
System.arraycopy(getRecord().getData(), 0, data, 0, getRecord().getLength());
pos += getRecord().getLength();
this.continuationBreaks = new int[continuations.length];
Record r = null;
for (int j = 0; j < continuations.length; j++) {
r = continuations[j];
System.arraycopy(r.getData(), 0, data, pos, r.getLength());
this.continuationBreaks[j] = pos;
pos += r.getLength();
}
this.totalStrings = IntegerHelper.getInt(data[0], data[1], data[2], data[3]);
this.uniqueStrings = IntegerHelper.getInt(data[4], data[5], data[6], data[7]);
this.strings = new String[this.uniqueStrings];
readStrings(data, 8, ws);
}
private void readStrings(byte[] data, int offset, WorkbookSettings ws) {
int pos = offset;
String s = null;
boolean asciiEncoding = false;
boolean richString = false;
boolean extendedString = false;
int formattingRuns = 0;
int extendedRunLength = 0;
for (int i = 0; i < this.uniqueStrings; i++) {
int numChars = IntegerHelper.getInt(data[pos], data[pos + 1]);
pos += 2;
byte optionFlags = data[pos];
pos++;
extendedString = ((optionFlags & 0x4) != 0);
richString = ((optionFlags & 0x8) != 0);
if (richString) {
formattingRuns = IntegerHelper.getInt(data[pos], data[pos + 1]);
pos += 2;
}
if (extendedString) {
extendedRunLength = IntegerHelper.getInt(data[pos], data[pos + 1], data[pos + 2], data[pos + 3]);
pos += 4;
}
asciiEncoding = ((optionFlags & 0x1) == 0);
ByteArrayHolder bah = new ByteArrayHolder();
BooleanHolder bh = new BooleanHolder();
bh.value = asciiEncoding;
pos += getChars(data, bah, pos, bh, numChars);
asciiEncoding = bh.value;
if (asciiEncoding) {
s = StringHelper.getString(bah.bytes, numChars, 0, ws);
} else {
s = StringHelper.getUnicodeString(bah.bytes, numChars, 0);
}
this.strings[i] = s;
if (richString)
pos += 4 * formattingRuns;
if (extendedString)
pos += extendedRunLength;
if (pos > data.length)
Assert.verify(false, "pos exceeds record length");
}
}
private int getChars(byte[] source, ByteArrayHolder bah, int pos, BooleanHolder ascii, int numChars) {
int charsRead;
int i = 0;
boolean spansBreak = false;
if (ascii.value) {
bah.bytes = new byte[numChars];
} else {
bah.bytes = new byte[numChars * 2];
}
while (i < this.continuationBreaks.length && !spansBreak) {
spansBreak = (pos <= this.continuationBreaks[i] && pos + bah.bytes.length > this.continuationBreaks[i]);
if (!spansBreak)
i++;
}
if (!spansBreak) {
System.arraycopy(source, pos, bah.bytes, 0, bah.bytes.length);
return bah.bytes.length;
}
int breakpos = this.continuationBreaks[i];
System.arraycopy(source, pos, bah.bytes, 0, breakpos - pos);
int bytesRead = breakpos - pos;
if (ascii.value) {
charsRead = bytesRead;
} else {
charsRead = bytesRead / 2;
}
bytesRead += getContinuedString(source, bah, bytesRead, i, ascii, numChars - charsRead);
return bytesRead;
}
private int getContinuedString(byte[] source, ByteArrayHolder bah, int destPos, int contBreakIndex, BooleanHolder ascii, int charsLeft) {
int breakpos = this.continuationBreaks[contBreakIndex];
int bytesRead = 0;
while (charsLeft > 0) {
Assert.verify((contBreakIndex < this.continuationBreaks.length), "continuation break index");
if (ascii.value && source[breakpos] == 0) {
int length = (contBreakIndex == this.continuationBreaks.length - 1) ? charsLeft : Math.min(charsLeft, this.continuationBreaks[contBreakIndex + 1] - breakpos - 1);
System.arraycopy(source, breakpos + 1, bah.bytes, destPos, length);
destPos += length;
bytesRead += length + 1;
charsLeft -= length;
ascii.value = true;
} else if (!ascii.value && source[breakpos] != 0) {
int length = (contBreakIndex == this.continuationBreaks.length - 1) ? (charsLeft * 2) : Math.min(charsLeft * 2, this.continuationBreaks[contBreakIndex + 1] - breakpos - 1);
System.arraycopy(source, breakpos + 1, bah.bytes, destPos, length);
destPos += length;
bytesRead += length + 1;
charsLeft -= length / 2;
ascii.value = false;
} else if (!ascii.value && source[breakpos] == 0) {
int chars = (contBreakIndex == this.continuationBreaks.length - 1) ? charsLeft : Math.min(charsLeft, this.continuationBreaks[contBreakIndex + 1] - breakpos - 1);
for (int j = 0; j < chars; j++) {
bah.bytes[destPos] = source[breakpos + j + 1];
destPos += 2;
}
bytesRead += chars + 1;
charsLeft -= chars;
ascii.value = false;
} else {
byte[] oldBytes = bah.bytes;
bah.bytes = new byte[destPos * 2 + charsLeft * 2];
for (int j = 0; j < destPos; j++)
bah.bytes[j * 2] = oldBytes[j];
destPos *= 2;
int length = (contBreakIndex == this.continuationBreaks.length - 1) ? (charsLeft * 2) : Math.min(charsLeft * 2, this.continuationBreaks[contBreakIndex + 1] - breakpos - 1);
System.arraycopy(source, breakpos + 1, bah.bytes, destPos, length);
destPos += length;
bytesRead += length + 1;
charsLeft -= length / 2;
ascii.value = false;
}
contBreakIndex++;
if (contBreakIndex < this.continuationBreaks.length)
breakpos = this.continuationBreaks[contBreakIndex];
}
return bytesRead;
}
public String getString(int index) {
Assert.verify((index < this.uniqueStrings));
return this.strings[index];
}
}

View file

@ -0,0 +1,22 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class SaveRecalcRecord extends RecordData {
private static Logger logger = Logger.getLogger(SaveRecalcRecord.class);
private boolean recalculateOnSave;
public SaveRecalcRecord(Record t) {
super(t);
byte[] data = t.getData();
int mode = IntegerHelper.getInt(data[0], data[1]);
this.recalculateOnSave = (mode == 1);
}
public boolean getRecalculateOnSave() {
return this.recalculateOnSave;
}
}

View file

@ -0,0 +1,110 @@
package jxl.read.biff;
import jxl.biff.DoubleHelper;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.Type;
import jxl.common.Logger;
public class SetupRecord extends RecordData {
private static Logger logger = Logger.getLogger(SetupRecord.class);
private byte[] data;
private boolean portraitOrientation;
private boolean pageOrder;
private double headerMargin;
private double footerMargin;
private int paperSize;
private int scaleFactor;
private int pageStart;
private int fitWidth;
private int fitHeight;
private int horizontalPrintResolution;
private int verticalPrintResolution;
private int copies;
private boolean initialized;
SetupRecord(Record t) {
super(Type.SETUP);
this.data = t.getData();
this.paperSize = IntegerHelper.getInt(this.data[0], this.data[1]);
this.scaleFactor = IntegerHelper.getInt(this.data[2], this.data[3]);
this.pageStart = IntegerHelper.getInt(this.data[4], this.data[5]);
this.fitWidth = IntegerHelper.getInt(this.data[6], this.data[7]);
this.fitHeight = IntegerHelper.getInt(this.data[8], this.data[9]);
this.horizontalPrintResolution = IntegerHelper.getInt(this.data[12], this.data[13]);
this.verticalPrintResolution = IntegerHelper.getInt(this.data[14], this.data[15]);
this.copies = IntegerHelper.getInt(this.data[32], this.data[33]);
this.headerMargin = DoubleHelper.getIEEEDouble(this.data, 16);
this.footerMargin = DoubleHelper.getIEEEDouble(this.data, 24);
int grbit = IntegerHelper.getInt(this.data[10], this.data[11]);
this.pageOrder = ((grbit & 0x1) != 0);
this.portraitOrientation = ((grbit & 0x2) != 0);
this.initialized = ((grbit & 0x4) == 0);
}
public boolean isPortrait() {
return this.portraitOrientation;
}
public boolean isRightDown() {
return this.pageOrder;
}
public double getHeaderMargin() {
return this.headerMargin;
}
public double getFooterMargin() {
return this.footerMargin;
}
public int getPaperSize() {
return this.paperSize;
}
public int getScaleFactor() {
return this.scaleFactor;
}
public int getPageStart() {
return this.pageStart;
}
public int getFitWidth() {
return this.fitWidth;
}
public int getFitHeight() {
return this.fitHeight;
}
public int getHorizontalPrintResolution() {
return this.horizontalPrintResolution;
}
public int getVerticalPrintResolution() {
return this.verticalPrintResolution;
}
public int getCopies() {
return this.copies;
}
public boolean getInitialized() {
return this.initialized;
}
}

View file

@ -0,0 +1,57 @@
package jxl.read.biff;
import jxl.BooleanCell;
import jxl.BooleanFormulaCell;
import jxl.CellType;
import jxl.biff.FormattingRecords;
import jxl.biff.FormulaData;
import jxl.biff.IntegerHelper;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.biff.formula.FormulaException;
import jxl.biff.formula.FormulaParser;
import jxl.common.Logger;
public class SharedBooleanFormulaRecord extends BaseSharedFormulaRecord implements BooleanCell, FormulaData, BooleanFormulaCell {
private static Logger logger = Logger.getLogger(SharedBooleanFormulaRecord.class);
private boolean value;
public SharedBooleanFormulaRecord(Record t, File excelFile, boolean v, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) {
super(t, fr, es, nt, si, excelFile.getPos());
this.value = v;
}
public boolean getValue() {
return this.value;
}
public String getContents() {
return new Boolean(this.value).toString();
}
public CellType getType() {
return CellType.BOOLEAN_FORMULA;
}
public byte[] getFormulaData() throws FormulaException {
if (!getSheet().getWorkbookBof().isBiff8())
throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
FormulaParser fp = new FormulaParser(getTokens(), this, getExternalSheet(), getNameTable(), getSheet().getWorkbook().getSettings());
fp.parse();
byte[] rpnTokens = fp.getBytes();
byte[] data = new byte[rpnTokens.length + 22];
IntegerHelper.getTwoBytes(getRow(), data, 0);
IntegerHelper.getTwoBytes(getColumn(), data, 2);
IntegerHelper.getTwoBytes(getXFIndex(), data, 4);
data[6] = 1;
data[8] = (byte)((this.value == true) ? 1 : 0);
data[12] = -1;
data[13] = -1;
System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length);
IntegerHelper.getTwoBytes(rpnTokens.length, data, 20);
byte[] d = new byte[data.length - 6];
System.arraycopy(data, 6, d, 0, data.length - 6);
return d;
}
}

View file

@ -0,0 +1,67 @@
package jxl.read.biff;
import java.text.DateFormat;
import java.util.Date;
import jxl.CellType;
import jxl.DateCell;
import jxl.DateFormulaCell;
import jxl.biff.DoubleHelper;
import jxl.biff.FormattingRecords;
import jxl.biff.FormulaData;
import jxl.biff.IntegerHelper;
import jxl.biff.formula.FormulaException;
import jxl.biff.formula.FormulaParser;
public class SharedDateFormulaRecord extends BaseSharedFormulaRecord implements DateCell, FormulaData, DateFormulaCell {
private DateRecord dateRecord;
private double value;
public SharedDateFormulaRecord(SharedNumberFormulaRecord nfr, FormattingRecords fr, boolean nf, SheetImpl si, int pos) {
super(nfr.getRecord(), fr, nfr.getExternalSheet(), nfr.getNameTable(), si, pos);
this.dateRecord = new DateRecord(nfr, nfr.getXFIndex(), fr, nf, si);
this.value = nfr.getValue();
}
public double getValue() {
return this.value;
}
public String getContents() {
return this.dateRecord.getContents();
}
public CellType getType() {
return CellType.DATE_FORMULA;
}
public byte[] getFormulaData() throws FormulaException {
if (!getSheet().getWorkbookBof().isBiff8())
throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
FormulaParser fp = new FormulaParser(getTokens(), this, getExternalSheet(), getNameTable(), getSheet().getWorkbook().getSettings());
fp.parse();
byte[] rpnTokens = fp.getBytes();
byte[] data = new byte[rpnTokens.length + 22];
IntegerHelper.getTwoBytes(getRow(), data, 0);
IntegerHelper.getTwoBytes(getColumn(), data, 2);
IntegerHelper.getTwoBytes(getXFIndex(), data, 4);
DoubleHelper.getIEEEBytes(this.value, data, 6);
System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length);
IntegerHelper.getTwoBytes(rpnTokens.length, data, 20);
byte[] d = new byte[data.length - 6];
System.arraycopy(data, 6, d, 0, data.length - 6);
return d;
}
public Date getDate() {
return this.dateRecord.getDate();
}
public boolean isTime() {
return this.dateRecord.isTime();
}
public DateFormat getDateFormat() {
return this.dateRecord.getDateFormat();
}
}

View file

@ -0,0 +1,64 @@
package jxl.read.biff;
import jxl.CellType;
import jxl.ErrorCell;
import jxl.ErrorFormulaCell;
import jxl.biff.FormattingRecords;
import jxl.biff.FormulaData;
import jxl.biff.IntegerHelper;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.biff.formula.FormulaErrorCode;
import jxl.biff.formula.FormulaException;
import jxl.biff.formula.FormulaParser;
import jxl.common.Logger;
public class SharedErrorFormulaRecord extends BaseSharedFormulaRecord implements ErrorCell, FormulaData, ErrorFormulaCell {
private static Logger logger = Logger.getLogger(SharedErrorFormulaRecord.class);
private int errorCode;
private byte[] data;
private FormulaErrorCode error;
public SharedErrorFormulaRecord(Record t, File excelFile, int ec, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) {
super(t, fr, es, nt, si, excelFile.getPos());
this.errorCode = ec;
}
public int getErrorCode() {
return this.errorCode;
}
public String getContents() {
if (this.error == null)
this.error = FormulaErrorCode.getErrorCode(this.errorCode);
return (this.error != FormulaErrorCode.UNKNOWN) ? this.error.getDescription() : ("ERROR " + this.errorCode);
}
public CellType getType() {
return CellType.FORMULA_ERROR;
}
public byte[] getFormulaData() throws FormulaException {
if (!getSheet().getWorkbookBof().isBiff8())
throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
FormulaParser fp = new FormulaParser(getTokens(), this, getExternalSheet(), getNameTable(), getSheet().getWorkbook().getSettings());
fp.parse();
byte[] rpnTokens = fp.getBytes();
byte[] data = new byte[rpnTokens.length + 22];
IntegerHelper.getTwoBytes(getRow(), data, 0);
IntegerHelper.getTwoBytes(getColumn(), data, 2);
IntegerHelper.getTwoBytes(getXFIndex(), data, 4);
data[6] = 2;
data[8] = (byte)this.errorCode;
data[12] = -1;
data[13] = -1;
System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length);
IntegerHelper.getTwoBytes(rpnTokens.length, data, 20);
byte[] d = new byte[data.length - 6];
System.arraycopy(data, 6, d, 0, data.length - 6);
return d;
}
}

View file

@ -0,0 +1,94 @@
package jxl.read.biff;
import java.text.NumberFormat;
import java.util.ArrayList;
import jxl.Cell;
import jxl.CellType;
import jxl.biff.FormattingRecords;
import jxl.biff.IntegerHelper;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.common.Logger;
class SharedFormulaRecord {
private static Logger logger = Logger.getLogger(SharedFormulaRecord.class);
private int firstRow;
private int lastRow;
private int firstCol;
private int lastCol;
private BaseSharedFormulaRecord templateFormula;
private ArrayList formulas;
private byte[] tokens;
private ExternalSheet externalSheet;
private SheetImpl sheet;
public SharedFormulaRecord(Record t, BaseSharedFormulaRecord fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) {
this.sheet = si;
byte[] data = t.getData();
this.firstRow = IntegerHelper.getInt(data[0], data[1]);
this.lastRow = IntegerHelper.getInt(data[2], data[3]);
this.firstCol = data[4] & 0xFF;
this.lastCol = data[5] & 0xFF;
this.formulas = new ArrayList();
this.templateFormula = fr;
this.tokens = new byte[data.length - 10];
System.arraycopy(data, 10, this.tokens, 0, this.tokens.length);
}
public boolean add(BaseSharedFormulaRecord fr) {
boolean added = false;
int r = fr.getRow();
if (r >= this.firstRow && r <= this.lastRow) {
int c = fr.getColumn();
if (c >= this.firstCol && c <= this.lastCol) {
this.formulas.add(fr);
added = true;
}
}
return added;
}
Cell[] getFormulas(FormattingRecords fr, boolean nf) {
Cell[] sfs = new Cell[this.formulas.size() + 1];
if (this.templateFormula == null) {
logger.warn("Shared formula template formula is null");
return new Cell[0];
}
this.templateFormula.setTokens(this.tokens);
NumberFormat templateNumberFormat = null;
if (this.templateFormula.getType() == CellType.NUMBER_FORMULA) {
SharedNumberFormulaRecord snfr = (SharedNumberFormulaRecord)this.templateFormula;
templateNumberFormat = snfr.getNumberFormat();
if (fr.isDate(this.templateFormula.getXFIndex())) {
this.templateFormula = new SharedDateFormulaRecord(snfr, fr, nf, this.sheet, snfr.getFilePos());
this.templateFormula.setTokens(snfr.getTokens());
}
}
sfs[0] = this.templateFormula;
BaseSharedFormulaRecord f = null;
for (int i = 0; i < this.formulas.size(); i++) {
f = this.formulas.get(i);
if (f.getType() == CellType.NUMBER_FORMULA) {
SharedNumberFormulaRecord snfr = (SharedNumberFormulaRecord)f;
if (fr.isDate(f.getXFIndex()))
f = new SharedDateFormulaRecord(snfr, fr, nf, this.sheet, snfr.getFilePos());
}
f.setTokens(this.tokens);
sfs[i + 1] = f;
}
return sfs;
}
BaseSharedFormulaRecord getTemplateFormula() {
return this.templateFormula;
}
}

View file

@ -0,0 +1,73 @@
package jxl.read.biff;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import jxl.CellType;
import jxl.NumberCell;
import jxl.NumberFormulaCell;
import jxl.biff.DoubleHelper;
import jxl.biff.FormattingRecords;
import jxl.biff.FormulaData;
import jxl.biff.IntegerHelper;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.biff.formula.FormulaException;
import jxl.biff.formula.FormulaParser;
import jxl.common.Logger;
public class SharedNumberFormulaRecord extends BaseSharedFormulaRecord implements NumberCell, FormulaData, NumberFormulaCell {
private static Logger logger = Logger.getLogger(SharedNumberFormulaRecord.class);
private double value;
private NumberFormat format;
private FormattingRecords formattingRecords;
private static DecimalFormat defaultFormat = new DecimalFormat("#.###");
public SharedNumberFormulaRecord(Record t, File excelFile, double v, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) {
super(t, fr, es, nt, si, excelFile.getPos());
this.value = v;
this.format = defaultFormat;
}
final void setNumberFormat(NumberFormat f) {
if (f != null)
this.format = f;
}
public double getValue() {
return this.value;
}
public String getContents() {
return !Double.isNaN(this.value) ? this.format.format(this.value) : "";
}
public CellType getType() {
return CellType.NUMBER_FORMULA;
}
public byte[] getFormulaData() throws FormulaException {
if (!getSheet().getWorkbookBof().isBiff8())
throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
FormulaParser fp = new FormulaParser(getTokens(), this, getExternalSheet(), getNameTable(), getSheet().getWorkbook().getSettings());
fp.parse();
byte[] rpnTokens = fp.getBytes();
byte[] data = new byte[rpnTokens.length + 22];
IntegerHelper.getTwoBytes(getRow(), data, 0);
IntegerHelper.getTwoBytes(getColumn(), data, 2);
IntegerHelper.getTwoBytes(getXFIndex(), data, 4);
DoubleHelper.getIEEEBytes(this.value, data, 6);
System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length);
IntegerHelper.getTwoBytes(rpnTokens.length, data, 20);
byte[] d = new byte[data.length - 6];
System.arraycopy(data, 6, d, 0, data.length - 6);
return d;
}
public NumberFormat getNumberFormat() {
return this.format;
}
}

View file

@ -0,0 +1,108 @@
package jxl.read.biff;
import jxl.CellType;
import jxl.LabelCell;
import jxl.StringFormulaCell;
import jxl.WorkbookSettings;
import jxl.biff.FormattingRecords;
import jxl.biff.FormulaData;
import jxl.biff.IntegerHelper;
import jxl.biff.StringHelper;
import jxl.biff.Type;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.biff.formula.FormulaException;
import jxl.biff.formula.FormulaParser;
import jxl.common.Assert;
import jxl.common.Logger;
public class SharedStringFormulaRecord extends BaseSharedFormulaRecord implements LabelCell, FormulaData, StringFormulaCell {
private static Logger logger = Logger.getLogger(SharedStringFormulaRecord.class);
private String value;
private static final class EmptyString {
private EmptyString() {}
}
protected static final EmptyString EMPTY_STRING = new EmptyString();
public SharedStringFormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si, WorkbookSettings ws) {
super(t, fr, es, nt, si, excelFile.getPos());
int pos = excelFile.getPos();
int filepos = excelFile.getPos();
Record nextRecord = excelFile.next();
int count = 0;
while (nextRecord.getType() != Type.STRING && count < 4) {
nextRecord = excelFile.next();
count++;
}
Assert.verify((count < 4), " @ " + pos);
byte[] stringData = nextRecord.getData();
nextRecord = excelFile.peek();
while (nextRecord.getType() == Type.CONTINUE) {
nextRecord = excelFile.next();
byte[] d = new byte[stringData.length + nextRecord.getLength() - 1];
System.arraycopy(stringData, 0, d, 0, stringData.length);
System.arraycopy(nextRecord.getData(), 1, d, stringData.length, nextRecord.getLength() - 1);
stringData = d;
nextRecord = excelFile.peek();
}
int chars = IntegerHelper.getInt(stringData[0], stringData[1]);
boolean unicode = false;
int startpos = 3;
if (stringData.length == chars + 2) {
startpos = 2;
unicode = false;
} else if (stringData[2] == 1) {
startpos = 3;
unicode = true;
} else {
startpos = 3;
unicode = false;
}
if (!unicode) {
this.value = StringHelper.getString(stringData, chars, startpos, ws);
} else {
this.value = StringHelper.getUnicodeString(stringData, chars, startpos);
}
excelFile.setPos(filepos);
}
public SharedStringFormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si, EmptyString dummy) {
super(t, fr, es, nt, si, excelFile.getPos());
this.value = "";
}
public String getString() {
return this.value;
}
public String getContents() {
return this.value;
}
public CellType getType() {
return CellType.STRING_FORMULA;
}
public byte[] getFormulaData() throws FormulaException {
if (!getSheet().getWorkbookBof().isBiff8())
throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
FormulaParser fp = new FormulaParser(getTokens(), this, getExternalSheet(), getNameTable(), getSheet().getWorkbook().getSettings());
fp.parse();
byte[] rpnTokens = fp.getBytes();
byte[] data = new byte[rpnTokens.length + 22];
IntegerHelper.getTwoBytes(getRow(), data, 0);
IntegerHelper.getTwoBytes(getColumn(), data, 2);
IntegerHelper.getTwoBytes(getXFIndex(), data, 4);
data[6] = 0;
data[12] = -1;
data[13] = -1;
System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length);
IntegerHelper.getTwoBytes(rpnTokens.length, data, 20);
byte[] d = new byte[data.length - 6];
System.arraycopy(data, 6, d, 0, data.length - 6);
return d;
}
}

View file

@ -0,0 +1,523 @@
package jxl.read.biff;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.regex.Pattern;
import jxl.Cell;
import jxl.CellView;
import jxl.Hyperlink;
import jxl.Image;
import jxl.LabelCell;
import jxl.Range;
import jxl.Sheet;
import jxl.SheetSettings;
import jxl.WorkbookSettings;
import jxl.biff.AutoFilter;
import jxl.biff.BuiltInName;
import jxl.biff.CellFinder;
import jxl.biff.CellReferenceHelper;
import jxl.biff.ConditionalFormat;
import jxl.biff.DataValidation;
import jxl.biff.EmptyCell;
import jxl.biff.FormattingRecords;
import jxl.biff.Type;
import jxl.biff.WorkspaceInformationRecord;
import jxl.biff.drawing.Chart;
import jxl.biff.drawing.DrawingData;
import jxl.biff.drawing.DrawingGroupObject;
import jxl.common.Logger;
import jxl.format.CellFormat;
public class SheetImpl implements Sheet {
private static Logger logger = Logger.getLogger(SheetImpl.class);
private File excelFile;
private SSTRecord sharedStrings;
private BOFRecord sheetBof;
private BOFRecord workbookBof;
private FormattingRecords formattingRecords;
private String name;
private int numRows;
private int numCols;
private Cell[][] cells;
private int startPosition;
private ColumnInfoRecord[] columnInfos;
private RowRecord[] rowRecords;
private ArrayList rowProperties;
private ArrayList columnInfosArray;
private ArrayList sharedFormulas;
private ArrayList hyperlinks;
private ArrayList charts;
private ArrayList drawings;
private ArrayList images;
private DataValidation dataValidation;
private Range[] mergedCells;
private boolean columnInfosInitialized;
private boolean rowRecordsInitialized;
private boolean nineteenFour;
private WorkspaceInformationRecord workspaceOptions;
private boolean hidden;
private PLSRecord plsRecord;
private ButtonPropertySetRecord buttonPropertySet;
private SheetSettings settings;
private int[] rowBreaks;
private int[] columnBreaks;
private int maxRowOutlineLevel;
private int maxColumnOutlineLevel;
private ArrayList localNames;
private ArrayList conditionalFormats;
private AutoFilter autoFilter;
private WorkbookParser workbook;
private WorkbookSettings workbookSettings;
SheetImpl(File f, SSTRecord sst, FormattingRecords fr, BOFRecord sb, BOFRecord wb, boolean nf, WorkbookParser wp) throws BiffException {
this.excelFile = f;
this.sharedStrings = sst;
this.formattingRecords = fr;
this.sheetBof = sb;
this.workbookBof = wb;
this.columnInfosArray = new ArrayList();
this.sharedFormulas = new ArrayList();
this.hyperlinks = new ArrayList();
this.rowProperties = new ArrayList(10);
this.columnInfosInitialized = false;
this.rowRecordsInitialized = false;
this.nineteenFour = nf;
this.workbook = wp;
this.workbookSettings = this.workbook.getSettings();
this.startPosition = f.getPos();
if (this.sheetBof.isChart())
this.startPosition -= this.sheetBof.getLength() + 4;
Record r = null;
int bofs = 1;
while (bofs >= 1) {
r = f.next();
if (r.getCode() == Type.EOF.value)
bofs--;
if (r.getCode() == Type.BOF.value)
bofs++;
}
}
public Cell getCell(String loc) {
return getCell(CellReferenceHelper.getColumn(loc), CellReferenceHelper.getRow(loc));
}
public Cell getCell(int column, int row) {
if (this.cells == null)
readSheet();
Cell c = this.cells[row][column];
if (c == null) {
c = new EmptyCell(column, row);
this.cells[row][column] = c;
}
return c;
}
public Cell findCell(String contents) {
CellFinder cellFinder = new CellFinder(this);
return cellFinder.findCell(contents);
}
public Cell findCell(String contents, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) {
CellFinder cellFinder = new CellFinder(this);
return cellFinder.findCell(contents, firstCol, firstRow, lastCol, lastRow, reverse);
}
public Cell findCell(Pattern pattern, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) {
CellFinder cellFinder = new CellFinder(this);
return cellFinder.findCell(pattern, firstCol, firstRow, lastCol, lastRow, reverse);
}
public LabelCell findLabelCell(String contents) {
CellFinder cellFinder = new CellFinder(this);
return cellFinder.findLabelCell(contents);
}
public int getRows() {
if (this.cells == null)
readSheet();
return this.numRows;
}
public int getColumns() {
if (this.cells == null)
readSheet();
return this.numCols;
}
public Cell[] getRow(int row) {
if (this.cells == null)
readSheet();
boolean found = false;
int col = this.numCols - 1;
while (col >= 0 && !found) {
if (this.cells[row][col] != null) {
found = true;
continue;
}
col--;
}
Cell[] c = new Cell[col + 1];
for (int i = 0; i <= col; i++)
c[i] = getCell(i, row);
return c;
}
public Cell[] getColumn(int col) {
if (this.cells == null)
readSheet();
boolean found = false;
int row = this.numRows - 1;
while (row >= 0 && !found) {
if (this.cells[row][col] != null) {
found = true;
continue;
}
row--;
}
Cell[] c = new Cell[row + 1];
for (int i = 0; i <= row; i++)
c[i] = getCell(col, i);
return c;
}
public String getName() {
return this.name;
}
final void setName(String s) {
this.name = s;
}
public boolean isHidden() {
return this.hidden;
}
public ColumnInfoRecord getColumnInfo(int col) {
if (!this.columnInfosInitialized) {
Iterator<ColumnInfoRecord> i = this.columnInfosArray.iterator();
ColumnInfoRecord cir = null;
while (i.hasNext()) {
cir = i.next();
int startcol = Math.max(0, cir.getStartColumn());
int endcol = Math.min(this.columnInfos.length - 1, cir.getEndColumn());
for (int c = startcol; c <= endcol; c++)
this.columnInfos[c] = cir;
if (endcol < startcol)
this.columnInfos[startcol] = cir;
}
this.columnInfosInitialized = true;
}
return (col < this.columnInfos.length) ? this.columnInfos[col] : null;
}
public ColumnInfoRecord[] getColumnInfos() {
ColumnInfoRecord[] infos = new ColumnInfoRecord[this.columnInfosArray.size()];
for (int i = 0; i < this.columnInfosArray.size(); i++)
infos[i] = this.columnInfosArray.get(i);
return infos;
}
final void setHidden(boolean h) {
this.hidden = h;
}
final void clear() {
this.cells = null;
this.mergedCells = null;
this.columnInfosArray.clear();
this.sharedFormulas.clear();
this.hyperlinks.clear();
this.columnInfosInitialized = false;
if (!this.workbookSettings.getGCDisabled())
System.gc();
}
final void readSheet() {
if (!this.sheetBof.isWorksheet()) {
this.numRows = 0;
this.numCols = 0;
this.cells = new Cell[0][0];
}
SheetReader reader = new SheetReader(this.excelFile, this.sharedStrings, this.formattingRecords, this.sheetBof, this.workbookBof, this.nineteenFour, this.workbook, this.startPosition, this);
reader.read();
this.numRows = reader.getNumRows();
this.numCols = reader.getNumCols();
this.cells = reader.getCells();
this.rowProperties = reader.getRowProperties();
this.columnInfosArray = reader.getColumnInfosArray();
this.hyperlinks = reader.getHyperlinks();
this.conditionalFormats = reader.getConditionalFormats();
this.autoFilter = reader.getAutoFilter();
this.charts = reader.getCharts();
this.drawings = reader.getDrawings();
this.dataValidation = reader.getDataValidation();
this.mergedCells = reader.getMergedCells();
this.settings = reader.getSettings();
this.settings.setHidden(this.hidden);
this.rowBreaks = reader.getRowBreaks();
this.columnBreaks = reader.getColumnBreaks();
this.workspaceOptions = reader.getWorkspaceOptions();
this.plsRecord = reader.getPLS();
this.buttonPropertySet = reader.getButtonPropertySet();
this.maxRowOutlineLevel = reader.getMaxRowOutlineLevel();
this.maxColumnOutlineLevel = reader.getMaxColumnOutlineLevel();
reader = null;
if (!this.workbookSettings.getGCDisabled())
System.gc();
if (this.columnInfosArray.size() > 0) {
ColumnInfoRecord cir = this.columnInfosArray.get(this.columnInfosArray.size() - 1);
this.columnInfos = new ColumnInfoRecord[cir.getEndColumn() + 1];
} else {
this.columnInfos = new ColumnInfoRecord[0];
}
if (this.localNames != null)
for (NameRecord nr : (Iterable<NameRecord>)this.localNames) {
if (nr.getBuiltInName() == BuiltInName.PRINT_AREA) {
if ((nr.getRanges()).length > 0) {
NameRecord.NameRange rng = nr.getRanges()[0];
this.settings.setPrintArea(rng.getFirstColumn(), rng.getFirstRow(), rng.getLastColumn(), rng.getLastRow());
}
continue;
}
if (nr.getBuiltInName() == BuiltInName.PRINT_TITLES)
for (int i = 0; i < (nr.getRanges()).length; i++) {
NameRecord.NameRange rng = nr.getRanges()[i];
if (rng.getFirstColumn() == 0 && rng.getLastColumn() == 255) {
this.settings.setPrintTitlesRow(rng.getFirstRow(), rng.getLastRow());
} else {
this.settings.setPrintTitlesCol(rng.getFirstColumn(), rng.getLastColumn());
}
}
}
}
public Hyperlink[] getHyperlinks() {
Hyperlink[] hl = new Hyperlink[this.hyperlinks.size()];
for (int i = 0; i < this.hyperlinks.size(); i++)
hl[i] = this.hyperlinks.get(i);
return hl;
}
public Range[] getMergedCells() {
if (this.mergedCells == null)
return new Range[0];
return this.mergedCells;
}
public RowRecord[] getRowProperties() {
RowRecord[] rp = new RowRecord[this.rowProperties.size()];
for (int i = 0; i < rp.length; i++)
rp[i] = this.rowProperties.get(i);
return rp;
}
public DataValidation getDataValidation() {
return this.dataValidation;
}
RowRecord getRowInfo(int r) {
if (!this.rowRecordsInitialized) {
this.rowRecords = new RowRecord[getRows()];
Iterator<RowRecord> i = this.rowProperties.iterator();
int rownum = 0;
RowRecord rr = null;
while (i.hasNext()) {
rr = i.next();
rownum = rr.getRowNumber();
if (rownum < this.rowRecords.length)
this.rowRecords[rownum] = rr;
}
this.rowRecordsInitialized = true;
}
return (r < this.rowRecords.length) ? this.rowRecords[r] : null;
}
public final int[] getRowPageBreaks() {
return this.rowBreaks;
}
public final int[] getColumnPageBreaks() {
return this.columnBreaks;
}
public final Chart[] getCharts() {
Chart[] ch = new Chart[this.charts.size()];
for (int i = 0; i < ch.length; i++)
ch[i] = this.charts.get(i);
return ch;
}
public final DrawingGroupObject[] getDrawings() {
DrawingGroupObject[] dr = new DrawingGroupObject[this.drawings.size()];
dr = (DrawingGroupObject[])this.drawings.toArray(dr);
return dr;
}
public boolean isProtected() {
return this.settings.isProtected();
}
public WorkspaceInformationRecord getWorkspaceOptions() {
return this.workspaceOptions;
}
public SheetSettings getSettings() {
return this.settings;
}
public WorkbookParser getWorkbook() {
return this.workbook;
}
public CellFormat getColumnFormat(int col) {
CellView cv = getColumnView(col);
return cv.getFormat();
}
public int getColumnWidth(int col) {
return getColumnView(col).getSize() / 256;
}
public CellView getColumnView(int col) {
ColumnInfoRecord cir = getColumnInfo(col);
CellView cv = new CellView();
if (cir != null) {
cv.setDimension(cir.getWidth() / 256);
cv.setSize(cir.getWidth());
cv.setHidden(cir.getHidden());
cv.setFormat(this.formattingRecords.getXFRecord(cir.getXFIndex()));
} else {
cv.setDimension(this.settings.getDefaultColumnWidth());
cv.setSize(this.settings.getDefaultColumnWidth() * 256);
}
return cv;
}
public int getRowHeight(int row) {
return getRowView(row).getDimension();
}
public CellView getRowView(int row) {
RowRecord rr = getRowInfo(row);
CellView cv = new CellView();
if (rr != null) {
cv.setDimension(rr.getRowHeight());
cv.setSize(rr.getRowHeight());
cv.setHidden(rr.isCollapsed());
if (rr.hasDefaultFormat())
cv.setFormat(this.formattingRecords.getXFRecord(rr.getXFIndex()));
} else {
cv.setDimension(this.settings.getDefaultRowHeight());
cv.setSize(this.settings.getDefaultRowHeight());
}
return cv;
}
public BOFRecord getSheetBof() {
return this.sheetBof;
}
public BOFRecord getWorkbookBof() {
return this.workbookBof;
}
public PLSRecord getPLS() {
return this.plsRecord;
}
public ButtonPropertySetRecord getButtonPropertySet() {
return this.buttonPropertySet;
}
public int getNumberOfImages() {
if (this.images == null)
initializeImages();
return this.images.size();
}
public Image getDrawing(int i) {
if (this.images == null)
initializeImages();
return this.images.get(i);
}
private void initializeImages() {
if (this.images != null)
return;
this.images = new ArrayList();
DrawingGroupObject[] dgos = getDrawings();
for (int i = 0; i < dgos.length; i++) {
if (dgos[i] instanceof jxl.biff.drawing.Drawing)
this.images.add(dgos[i]);
}
}
public DrawingData getDrawingData() {
SheetReader reader = new SheetReader(this.excelFile, this.sharedStrings, this.formattingRecords, this.sheetBof, this.workbookBof, this.nineteenFour, this.workbook, this.startPosition, this);
reader.read();
return reader.getDrawingData();
}
void addLocalName(NameRecord nr) {
if (this.localNames == null)
this.localNames = new ArrayList();
this.localNames.add(nr);
}
public ConditionalFormat[] getConditionalFormats() {
ConditionalFormat[] formats = new ConditionalFormat[this.conditionalFormats.size()];
formats = (ConditionalFormat[])this.conditionalFormats.toArray(formats);
return formats;
}
public AutoFilter getAutoFilter() {
return this.autoFilter;
}
public int getMaxColumnOutlineLevel() {
return this.maxColumnOutlineLevel;
}
public int getMaxRowOutlineLevel() {
return this.maxRowOutlineLevel;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,107 @@
package jxl.read.biff;
import jxl.biff.RecordData;
import jxl.biff.StringHelper;
import jxl.biff.Type;
public class SortRecord extends RecordData {
private int col1Size;
private int col2Size;
private int col3Size;
private String col1Name;
private String col2Name;
private String col3Name;
private byte optionFlags;
private boolean sortColumns = false;
private boolean sortKey1Desc = false;
private boolean sortKey2Desc = false;
private boolean sortKey3Desc = false;
private boolean sortCaseSensitive = false;
public SortRecord(Record r) {
super(Type.SORT);
byte[] data = r.getData();
this.optionFlags = data[0];
this.sortColumns = ((this.optionFlags & 0x1) != 0);
this.sortKey1Desc = ((this.optionFlags & 0x2) != 0);
this.sortKey2Desc = ((this.optionFlags & 0x4) != 0);
this.sortKey3Desc = ((this.optionFlags & 0x8) != 0);
this.sortCaseSensitive = ((this.optionFlags & 0x10) != 0);
this.col1Size = data[2];
this.col2Size = data[3];
this.col3Size = data[4];
int curPos = 5;
if (data[curPos++] == 0) {
this.col1Name = new String(data, curPos, this.col1Size);
curPos += this.col1Size;
} else {
this.col1Name = StringHelper.getUnicodeString(data, this.col1Size, curPos);
curPos += this.col1Size * 2;
}
if (this.col2Size > 0) {
if (data[curPos++] == 0) {
this.col2Name = new String(data, curPos, this.col2Size);
curPos += this.col2Size;
} else {
this.col2Name = StringHelper.getUnicodeString(data, this.col2Size, curPos);
curPos += this.col2Size * 2;
}
} else {
this.col2Name = "";
}
if (this.col3Size > 0) {
if (data[curPos++] == 0) {
this.col3Name = new String(data, curPos, this.col3Size);
curPos += this.col3Size;
} else {
this.col3Name = StringHelper.getUnicodeString(data, this.col3Size, curPos);
curPos += this.col3Size * 2;
}
} else {
this.col3Name = "";
}
}
public String getSortCol1Name() {
return this.col1Name;
}
public String getSortCol2Name() {
return this.col2Name;
}
public String getSortCol3Name() {
return this.col3Name;
}
public boolean getSortColumns() {
return this.sortColumns;
}
public boolean getSortKey1Desc() {
return this.sortKey1Desc;
}
public boolean getSortKey2Desc() {
return this.sortKey2Desc;
}
public boolean getSortKey3Desc() {
return this.sortKey3Desc;
}
public boolean getSortCaseSensitive() {
return this.sortCaseSensitive;
}
}

View file

@ -0,0 +1,126 @@
package jxl.read.biff;
import jxl.CellType;
import jxl.LabelCell;
import jxl.StringFormulaCell;
import jxl.WorkbookSettings;
import jxl.biff.FormattingRecords;
import jxl.biff.FormulaData;
import jxl.biff.IntegerHelper;
import jxl.biff.StringHelper;
import jxl.biff.Type;
import jxl.biff.WorkbookMethods;
import jxl.biff.formula.ExternalSheet;
import jxl.biff.formula.FormulaException;
import jxl.biff.formula.FormulaParser;
import jxl.common.Assert;
import jxl.common.Logger;
class StringFormulaRecord extends CellValue implements LabelCell, FormulaData, StringFormulaCell {
private static Logger logger = Logger.getLogger(StringFormulaRecord.class);
private String value;
private ExternalSheet externalSheet;
private WorkbookMethods nameTable;
private String formulaString;
private byte[] data;
public StringFormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si, WorkbookSettings ws) {
super(t, fr, si);
this.externalSheet = es;
this.nameTable = nt;
this.data = getRecord().getData();
int pos = excelFile.getPos();
Record nextRecord = excelFile.next();
int count = 0;
while (nextRecord.getType() != Type.STRING && count < 4) {
nextRecord = excelFile.next();
count++;
}
Assert.verify((count < 4), " @ " + pos);
byte[] stringData = nextRecord.getData();
nextRecord = excelFile.peek();
while (nextRecord.getType() == Type.CONTINUE) {
nextRecord = excelFile.next();
byte[] d = new byte[stringData.length + nextRecord.getLength() - 1];
System.arraycopy(stringData, 0, d, 0, stringData.length);
System.arraycopy(nextRecord.getData(), 1, d, stringData.length, nextRecord.getLength() - 1);
stringData = d;
nextRecord = excelFile.peek();
}
readString(stringData, ws);
}
public StringFormulaRecord(Record t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) {
super(t, fr, si);
this.externalSheet = es;
this.nameTable = nt;
this.data = getRecord().getData();
this.value = "";
}
private void readString(byte[] d, WorkbookSettings ws) {
int pos = 0;
int chars = IntegerHelper.getInt(d[0], d[1]);
if (chars == 0) {
this.value = "";
return;
}
pos += 2;
int optionFlags = d[pos];
pos++;
if ((optionFlags & 0xF) != optionFlags) {
pos = 0;
chars = IntegerHelper.getInt(d[0], (byte)0);
optionFlags = d[1];
pos = 2;
}
boolean extendedString = ((optionFlags & 0x4) != 0);
boolean richString = ((optionFlags & 0x8) != 0);
if (richString)
pos += 2;
if (extendedString)
pos += 4;
boolean asciiEncoding = ((optionFlags & 0x1) == 0);
if (asciiEncoding) {
this.value = StringHelper.getString(d, chars, pos, ws);
} else {
this.value = StringHelper.getUnicodeString(d, chars, pos);
}
}
public String getContents() {
return this.value;
}
public String getString() {
return this.value;
}
public CellType getType() {
return CellType.STRING_FORMULA;
}
public byte[] getFormulaData() throws FormulaException {
if (!getSheet().getWorkbook().getWorkbookBof().isBiff8())
throw new FormulaException(FormulaException.BIFF8_SUPPORTED);
byte[] d = new byte[this.data.length - 6];
System.arraycopy(this.data, 6, d, 0, this.data.length - 6);
return d;
}
public String getFormula() throws FormulaException {
if (this.formulaString == null) {
byte[] tokens = new byte[this.data.length - 22];
System.arraycopy(this.data, 22, tokens, 0, tokens.length);
FormulaParser fp = new FormulaParser(tokens, this, this.externalSheet, this.nameTable, getSheet().getWorkbook().getSettings());
fp.parse();
this.formulaString = fp.getFormula();
}
return this.formulaString;
}
}

View file

@ -0,0 +1,161 @@
package jxl.read.biff;
import jxl.WorkbookSettings;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.biff.StringHelper;
import jxl.common.Logger;
public class SupbookRecord extends RecordData {
private static Logger logger = Logger.getLogger(SupbookRecord.class);
private Type type;
private int numSheets;
private String fileName;
private String[] sheetNames;
private static class Type {
private 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();
SupbookRecord(Record t, WorkbookSettings ws) {
super(t);
byte[] data = getRecord().getData();
if (data.length == 4) {
if (data[2] == 1 && data[3] == 4) {
this.type = INTERNAL;
} else if (data[2] == 1 && data[3] == 58) {
this.type = ADDIN;
} else {
this.type = UNKNOWN;
}
} else if (data[0] == 0 && data[1] == 0) {
this.type = LINK;
} else {
this.type = EXTERNAL;
}
if (this.type == INTERNAL)
this.numSheets = IntegerHelper.getInt(data[0], data[1]);
if (this.type == EXTERNAL)
readExternal(data, ws);
}
private void readExternal(byte[] data, WorkbookSettings ws) {
this.numSheets = IntegerHelper.getInt(data[0], data[1]);
int ln = IntegerHelper.getInt(data[2], data[3]) - 1;
int pos = 0;
if (data[4] == 0) {
int encoding = data[5];
pos = 6;
if (encoding == 0) {
this.fileName = StringHelper.getString(data, ln, pos, ws);
pos += ln;
} else {
this.fileName = getEncodedFilename(data, ln, pos);
pos += ln;
}
} else {
int encoding = IntegerHelper.getInt(data[5], data[6]);
pos = 7;
if (encoding == 0) {
this.fileName = StringHelper.getUnicodeString(data, ln, pos);
pos += ln * 2;
} else {
this.fileName = getUnicodeEncodedFilename(data, ln, pos);
pos += ln * 2;
}
}
this.sheetNames = new String[this.numSheets];
for (int i = 0; i < this.sheetNames.length; i++) {
ln = IntegerHelper.getInt(data[pos], data[pos + 1]);
if (data[pos + 2] == 0) {
this.sheetNames[i] = StringHelper.getString(data, ln, pos + 3, ws);
pos += ln + 3;
} else if (data[pos + 2] == 1) {
this.sheetNames[i] = StringHelper.getUnicodeString(data, ln, pos + 3);
pos += ln * 2 + 3;
}
}
}
public Type getType() {
return this.type;
}
public int getNumberOfSheets() {
return this.numSheets;
}
public String getFileName() {
return this.fileName;
}
public String getSheetName(int i) {
return this.sheetNames[i];
}
public byte[] getData() {
return getRecord().getData();
}
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 == '\001') {
pos++;
c = (char)data[pos];
buf.append(c);
buf.append(":\\\\");
} else if (c == '\002') {
buf.append('\\');
} else if (c == '\003') {
buf.append('\\');
} else if (c == '\004') {
buf.append("..\\");
} else {
buf.append(c);
}
pos++;
}
return buf.toString();
}
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 == '\001') {
pos += 2;
c = (char)IntegerHelper.getInt(data[pos], data[pos + 1]);
buf.append(c);
buf.append(":\\\\");
} else if (c == '\002') {
buf.append('\\');
} else if (c == '\003') {
buf.append('\\');
} else if (c == '\004') {
buf.append("..\\");
} else {
buf.append(c);
}
pos += 2;
}
return buf.toString();
}
}

View file

@ -0,0 +1,19 @@
package jxl.read.biff;
import jxl.biff.RecordData;
import jxl.common.Logger;
class TemplateRecord extends RecordData {
private static Logger logger = Logger.getLogger(TemplateRecord.class);
private boolean template;
public TemplateRecord(Record t) {
super(t);
this.template = true;
}
public boolean getTemplate() {
return this.template;
}
}

View file

@ -0,0 +1,9 @@
package jxl.read.biff;
import jxl.biff.Type;
class TopMarginRecord extends MarginRecord {
TopMarginRecord(Record r) {
super(Type.TOPMARGIN, r);
}
}

View file

@ -0,0 +1,45 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class VerticalPageBreaksRecord extends RecordData {
private final Logger logger = Logger.getLogger(VerticalPageBreaksRecord.class);
private int[] columnBreaks;
private static class Biff7 {
private Biff7() {}
}
public static Biff7 biff7 = new Biff7();
public VerticalPageBreaksRecord(Record t) {
super(t);
byte[] data = t.getData();
int numbreaks = IntegerHelper.getInt(data[0], data[1]);
int pos = 2;
this.columnBreaks = new int[numbreaks];
for (int i = 0; i < numbreaks; i++) {
this.columnBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
pos += 6;
}
}
public VerticalPageBreaksRecord(Record t, Biff7 biff7) {
super(t);
byte[] data = t.getData();
int numbreaks = IntegerHelper.getInt(data[0], data[1]);
int pos = 2;
this.columnBreaks = new int[numbreaks];
for (int i = 0; i < numbreaks; i++) {
this.columnBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]);
pos += 2;
}
}
public int[] getColumnBreaks() {
return this.columnBreaks;
}
}

View file

@ -0,0 +1,89 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class Window2Record extends RecordData {
private static Logger logger = Logger.getLogger(Window2Record.class);
private boolean selected;
private boolean showGridLines;
private boolean displayZeroValues;
private boolean frozenPanes;
private boolean frozenNotSplit;
private boolean pageBreakPreviewMode;
private int pageBreakPreviewMagnification;
private int normalMagnification;
private static class Biff7 {
private Biff7() {}
}
public static final Biff7 biff7 = new Biff7();
public Window2Record(Record t) {
super(t);
byte[] data = t.getData();
int options = IntegerHelper.getInt(data[0], data[1]);
this.selected = ((options & 0x200) != 0);
this.showGridLines = ((options & 0x2) != 0);
this.frozenPanes = ((options & 0x8) != 0);
this.displayZeroValues = ((options & 0x10) != 0);
this.frozenNotSplit = ((options & 0x100) != 0);
this.pageBreakPreviewMode = ((options & 0x800) != 0);
this.pageBreakPreviewMagnification = IntegerHelper.getInt(data[10], data[11]);
this.normalMagnification = IntegerHelper.getInt(data[12], data[13]);
}
public Window2Record(Record t, Biff7 biff7) {
super(t);
byte[] data = t.getData();
int options = IntegerHelper.getInt(data[0], data[1]);
this.selected = ((options & 0x200) != 0);
this.showGridLines = ((options & 0x2) != 0);
this.frozenPanes = ((options & 0x8) != 0);
this.displayZeroValues = ((options & 0x10) != 0);
this.frozenNotSplit = ((options & 0x100) != 0);
this.pageBreakPreviewMode = ((options & 0x800) != 0);
}
public boolean isSelected() {
return this.selected;
}
public boolean getShowGridLines() {
return this.showGridLines;
}
public boolean getDisplayZeroValues() {
return this.displayZeroValues;
}
public boolean getFrozen() {
return this.frozenPanes;
}
public boolean getFrozenNotSplit() {
return this.frozenNotSplit;
}
public boolean isPageBreakPreview() {
return this.pageBreakPreviewMode;
}
public int getPageBreakPreviewMagnificaiton() {
return this.pageBreakPreviewMagnification;
}
public int getNormalMagnificaiton() {
return this.normalMagnification;
}
}

View file

@ -0,0 +1,22 @@
package jxl.read.biff;
import jxl.biff.IntegerHelper;
import jxl.biff.RecordData;
import jxl.common.Logger;
class WindowProtectedRecord extends RecordData {
private static Logger logger = Logger.getLogger(WindowProtectedRecord.class);
private boolean windowProtected;
public WindowProtectedRecord(Record t) {
super(t);
byte[] data = t.getData();
int mode = IntegerHelper.getInt(data[0], data[1]);
this.windowProtected = (mode == 1);
}
public boolean getWindowProtected() {
return this.windowProtected;
}
}

View file

@ -0,0 +1,645 @@
package jxl.read.biff;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import jxl.Cell;
import jxl.Range;
import jxl.Sheet;
import jxl.Workbook;
import jxl.WorkbookSettings;
import jxl.biff.BuiltInName;
import jxl.biff.CellReferenceHelper;
import jxl.biff.EmptyCell;
import jxl.biff.FontRecord;
import jxl.biff.Fonts;
import jxl.biff.FormatRecord;
import jxl.biff.FormattingRecords;
import jxl.biff.NameRangeException;
import jxl.biff.NumFormatRecordsException;
import jxl.biff.RangeImpl;
import jxl.biff.StringHelper;
import jxl.biff.Type;
import jxl.biff.WorkbookMethods;
import jxl.biff.XCTRecord;
import jxl.biff.XFRecord;
import jxl.biff.drawing.DrawingGroup;
import jxl.biff.drawing.MsoDrawingGroupRecord;
import jxl.biff.drawing.Origin;
import jxl.biff.formula.ExternalSheet;
import jxl.common.Assert;
import jxl.common.Logger;
public class WorkbookParser extends Workbook implements ExternalSheet, WorkbookMethods {
private static Logger logger = Logger.getLogger(WorkbookParser.class);
private File excelFile;
private int bofs;
private boolean nineteenFour;
private SSTRecord sharedStrings;
private ArrayList boundsheets;
private FormattingRecords formattingRecords;
private Fonts fonts;
private ArrayList sheets;
private SheetImpl lastSheet;
private int lastSheetIndex;
private HashMap namedRecords;
private ArrayList nameTable;
private ArrayList addInFunctions;
private ExternalSheetRecord externSheet;
private ArrayList supbooks;
private BOFRecord workbookBof;
private MsoDrawingGroupRecord msoDrawingGroup;
private ButtonPropertySetRecord buttonPropertySet;
private boolean wbProtected;
private boolean containsMacros;
private WorkbookSettings settings;
private DrawingGroup drawingGroup;
private CountryRecord countryRecord;
private ArrayList xctRecords;
public WorkbookParser(File f, WorkbookSettings s) {
this.excelFile = f;
this.boundsheets = new ArrayList(10);
this.fonts = new Fonts();
this.formattingRecords = new FormattingRecords(this.fonts);
this.sheets = new ArrayList(10);
this.supbooks = new ArrayList(10);
this.namedRecords = new HashMap();
this.lastSheetIndex = -1;
this.wbProtected = false;
this.containsMacros = false;
this.settings = s;
this.xctRecords = new ArrayList(10);
}
public Sheet[] getSheets() {
Sheet[] sheetArray = new Sheet[getNumberOfSheets()];
return (Sheet[])this.sheets.toArray(sheetArray);
}
public Sheet getReadSheet(int index) {
return getSheet(index);
}
public Sheet getSheet(int index) {
if (this.lastSheet != null && this.lastSheetIndex == index)
return this.lastSheet;
if (this.lastSheet != null) {
this.lastSheet.clear();
if (!this.settings.getGCDisabled())
System.gc();
}
this.lastSheet = this.sheets.get(index);
this.lastSheetIndex = index;
this.lastSheet.readSheet();
return this.lastSheet;
}
public Sheet getSheet(String name) {
int pos = 0;
boolean found = false;
Iterator<BoundsheetRecord> i = this.boundsheets.iterator();
BoundsheetRecord br = null;
while (i.hasNext() && !found) {
br = i.next();
if (br.getName().equals(name)) {
found = true;
continue;
}
pos++;
}
return found ? getSheet(pos) : null;
}
public String[] getSheetNames() {
String[] names = new String[this.boundsheets.size()];
BoundsheetRecord br = null;
for (int i = 0; i < names.length; i++) {
br = this.boundsheets.get(i);
names[i] = br.getName();
}
return names;
}
public int getExternalSheetIndex(int index) {
if (this.workbookBof.isBiff7())
return index;
Assert.verify((this.externSheet != null));
int firstTab = this.externSheet.getFirstTabIndex(index);
return firstTab;
}
public int getLastExternalSheetIndex(int index) {
if (this.workbookBof.isBiff7())
return index;
Assert.verify((this.externSheet != null));
int lastTab = this.externSheet.getLastTabIndex(index);
return lastTab;
}
public String getExternalSheetName(int index) {
if (this.workbookBof.isBiff7()) {
BoundsheetRecord br = this.boundsheets.get(index);
return br.getName();
}
int supbookIndex = this.externSheet.getSupbookIndex(index);
SupbookRecord sr = this.supbooks.get(supbookIndex);
int firstTab = this.externSheet.getFirstTabIndex(index);
int lastTab = this.externSheet.getLastTabIndex(index);
String firstTabName = "";
String lastTabName = "";
if (sr.getType() == SupbookRecord.INTERNAL) {
if (firstTab == 65535) {
firstTabName = "#REF";
} else {
BoundsheetRecord br = this.boundsheets.get(firstTab);
firstTabName = br.getName();
}
if (lastTab == 65535) {
lastTabName = "#REF";
} else {
BoundsheetRecord br = this.boundsheets.get(lastTab);
lastTabName = br.getName();
}
String sheetName = (firstTab == lastTab) ? firstTabName : (firstTabName + ':' + lastTabName);
sheetName = (sheetName.indexOf('\'') == -1) ? sheetName : StringHelper.replace(sheetName, "'", "''");
return (sheetName.indexOf(' ') == -1) ? sheetName : ('\'' + sheetName + '\'');
}
if (sr.getType() == SupbookRecord.EXTERNAL) {
StringBuffer sb = new StringBuffer();
java.io.File fl = new java.io.File(sr.getFileName());
sb.append("'");
sb.append(fl.getAbsolutePath());
sb.append("[");
sb.append(fl.getName());
sb.append("]");
sb.append((firstTab == 65535) ? "#REF" : sr.getSheetName(firstTab));
if (lastTab != firstTab)
sb.append(sr.getSheetName(lastTab));
sb.append("'");
return sb.toString();
}
logger.warn("Unknown Supbook 3");
return "[UNKNOWN]";
}
public String getLastExternalSheetName(int index) {
if (this.workbookBof.isBiff7()) {
BoundsheetRecord br = this.boundsheets.get(index);
return br.getName();
}
int supbookIndex = this.externSheet.getSupbookIndex(index);
SupbookRecord sr = this.supbooks.get(supbookIndex);
int lastTab = this.externSheet.getLastTabIndex(index);
if (sr.getType() == SupbookRecord.INTERNAL) {
if (lastTab == 65535)
return "#REF";
BoundsheetRecord br = this.boundsheets.get(lastTab);
return br.getName();
}
if (sr.getType() == SupbookRecord.EXTERNAL) {
StringBuffer sb = new StringBuffer();
java.io.File fl = new java.io.File(sr.getFileName());
sb.append("'");
sb.append(fl.getAbsolutePath());
sb.append("[");
sb.append(fl.getName());
sb.append("]");
sb.append((lastTab == 65535) ? "#REF" : sr.getSheetName(lastTab));
sb.append("'");
return sb.toString();
}
logger.warn("Unknown Supbook 4");
return "[UNKNOWN]";
}
public int getNumberOfSheets() {
return this.sheets.size();
}
public void close() {
if (this.lastSheet != null)
this.lastSheet.clear();
this.excelFile.clear();
if (!this.settings.getGCDisabled())
System.gc();
}
final void addSheet(Sheet s) {
this.sheets.add(s);
}
protected void parse() throws BiffException, PasswordException {
Record r = null;
BOFRecord bof = new BOFRecord(this.excelFile.next());
this.workbookBof = bof;
this.bofs++;
if (!bof.isBiff8() && !bof.isBiff7())
throw new BiffException(BiffException.unrecognizedBiffVersion);
if (!bof.isWorkbookGlobals())
throw new BiffException(BiffException.expectedGlobals);
ArrayList<Record> continueRecords = new ArrayList();
ArrayList<NameRecord> localNames = new ArrayList();
this.nameTable = new ArrayList();
this.addInFunctions = new ArrayList();
while (this.bofs == 1) {
r = this.excelFile.next();
if (r.getType() == Type.SST) {
continueRecords.clear();
Record nextrec = this.excelFile.peek();
while (nextrec.getType() == Type.CONTINUE) {
continueRecords.add(this.excelFile.next());
nextrec = this.excelFile.peek();
}
Record[] records = new Record[continueRecords.size()];
records = continueRecords.<Record>toArray(records);
this.sharedStrings = new SSTRecord(r, records, this.settings);
continue;
}
if (r.getType() == Type.FILEPASS)
throw new PasswordException();
if (r.getType() == Type.NAME) {
NameRecord nr = null;
if (bof.isBiff8()) {
nr = new NameRecord(r, this.settings, this.nameTable.size());
} else {
nr = new NameRecord(r, this.settings, this.nameTable.size(), NameRecord.biff7);
}
this.nameTable.add(nr);
if (nr.isGlobal()) {
this.namedRecords.put(nr.getName(), nr);
continue;
}
localNames.add(nr);
continue;
}
if (r.getType() == Type.FONT) {
FontRecord fr = null;
if (bof.isBiff8()) {
fr = new FontRecord(r, this.settings);
} else {
fr = new FontRecord(r, this.settings, FontRecord.biff7);
}
this.fonts.addFont(fr);
continue;
}
if (r.getType() == Type.PALETTE) {
jxl.biff.PaletteRecord palette = new jxl.biff.PaletteRecord(r);
this.formattingRecords.setPalette(palette);
continue;
}
if (r.getType() == Type.NINETEENFOUR) {
NineteenFourRecord nr = new NineteenFourRecord(r);
this.nineteenFour = nr.is1904();
continue;
}
if (r.getType() == Type.FORMAT) {
FormatRecord fr = null;
if (bof.isBiff8()) {
fr = new FormatRecord(r, this.settings, FormatRecord.biff8);
} else {
fr = new FormatRecord(r, this.settings, FormatRecord.biff7);
}
try {
this.formattingRecords.addFormat(fr);
} catch (NumFormatRecordsException e) {
Assert.verify(false, e.getMessage());
}
continue;
}
if (r.getType() == Type.XF) {
XFRecord xfr = null;
if (bof.isBiff8()) {
xfr = new XFRecord(r, this.settings, XFRecord.biff8);
} else {
xfr = new XFRecord(r, this.settings, XFRecord.biff7);
}
try {
this.formattingRecords.addStyle(xfr);
} catch (NumFormatRecordsException e) {
Assert.verify(false, e.getMessage());
}
continue;
}
if (r.getType() == Type.BOUNDSHEET) {
BoundsheetRecord br = null;
if (bof.isBiff8()) {
br = new BoundsheetRecord(r, this.settings);
} else {
br = new BoundsheetRecord(r, BoundsheetRecord.biff7);
}
if (br.isSheet()) {
this.boundsheets.add(br);
continue;
}
if (br.isChart() && !this.settings.getDrawingsDisabled())
this.boundsheets.add(br);
continue;
}
if (r.getType() == Type.EXTERNSHEET) {
if (bof.isBiff8()) {
this.externSheet = new ExternalSheetRecord(r, this.settings);
continue;
}
this.externSheet = new ExternalSheetRecord(r, this.settings, ExternalSheetRecord.biff7);
continue;
}
if (r.getType() == Type.XCT) {
XCTRecord xctr = new XCTRecord(r);
this.xctRecords.add(xctr);
continue;
}
if (r.getType() == Type.CODEPAGE) {
CodepageRecord cr = new CodepageRecord(r);
this.settings.setCharacterSet(cr.getCharacterSet());
continue;
}
if (r.getType() == Type.SUPBOOK) {
Record nextrec = this.excelFile.peek();
while (nextrec.getType() == Type.CONTINUE) {
r.addContinueRecord(this.excelFile.next());
nextrec = this.excelFile.peek();
}
SupbookRecord sr = new SupbookRecord(r, this.settings);
this.supbooks.add(sr);
continue;
}
if (r.getType() == Type.EXTERNNAME) {
ExternalNameRecord enr = new ExternalNameRecord(r, this.settings);
if (enr.isAddInFunction())
this.addInFunctions.add(enr.getName());
continue;
}
if (r.getType() == Type.PROTECT) {
ProtectRecord pr = new ProtectRecord(r);
this.wbProtected = pr.isProtected();
continue;
}
if (r.getType() == Type.OBJPROJ) {
this.containsMacros = true;
continue;
}
if (r.getType() == Type.COUNTRY) {
this.countryRecord = new CountryRecord(r);
continue;
}
if (r.getType() == Type.MSODRAWINGGROUP) {
if (!this.settings.getDrawingsDisabled()) {
this.msoDrawingGroup = new MsoDrawingGroupRecord(r);
if (this.drawingGroup == null)
this.drawingGroup = new DrawingGroup(Origin.READ);
this.drawingGroup.add(this.msoDrawingGroup);
Record nextrec = this.excelFile.peek();
while (nextrec.getType() == Type.CONTINUE) {
this.drawingGroup.add(this.excelFile.next());
nextrec = this.excelFile.peek();
}
}
continue;
}
if (r.getType() == Type.BUTTONPROPERTYSET) {
this.buttonPropertySet = new ButtonPropertySetRecord(r);
continue;
}
if (r.getType() == Type.EOF) {
this.bofs--;
continue;
}
if (r.getType() == Type.REFRESHALL) {
RefreshAllRecord rfm = new RefreshAllRecord(r);
this.settings.setRefreshAll(rfm.getRefreshAll());
continue;
}
if (r.getType() == Type.TEMPLATE) {
TemplateRecord rfm = new TemplateRecord(r);
this.settings.setTemplate(rfm.getTemplate());
continue;
}
if (r.getType() == Type.EXCEL9FILE) {
Excel9FileRecord e9f = new Excel9FileRecord(r);
this.settings.setExcel9File(e9f.getExcel9File());
continue;
}
if (r.getType() == Type.WINDOWPROTECT) {
WindowProtectedRecord winp = new WindowProtectedRecord(r);
this.settings.setWindowProtected(winp.getWindowProtected());
continue;
}
if (r.getType() == Type.HIDEOBJ) {
HideobjRecord hobj = new HideobjRecord(r);
this.settings.setHideobj(hobj.getHideMode());
continue;
}
if (r.getType() == Type.WRITEACCESS) {
WriteAccessRecord war = new WriteAccessRecord(r, bof.isBiff8(), this.settings);
this.settings.setWriteAccess(war.getWriteAccess());
}
}
bof = null;
if (this.excelFile.hasNext()) {
r = this.excelFile.next();
if (r.getType() == Type.BOF)
bof = new BOFRecord(r);
}
while (bof != null && getNumberOfSheets() < this.boundsheets.size()) {
if (!bof.isBiff8() && !bof.isBiff7())
throw new BiffException(BiffException.unrecognizedBiffVersion);
if (bof.isWorksheet()) {
SheetImpl s = new SheetImpl(this.excelFile, this.sharedStrings, this.formattingRecords, bof, this.workbookBof, this.nineteenFour, this);
BoundsheetRecord br = this.boundsheets.get(getNumberOfSheets());
s.setName(br.getName());
s.setHidden(br.isHidden());
addSheet(s);
} else if (bof.isChart()) {
SheetImpl s = new SheetImpl(this.excelFile, this.sharedStrings, this.formattingRecords, bof, this.workbookBof, this.nineteenFour, this);
BoundsheetRecord br = this.boundsheets.get(getNumberOfSheets());
s.setName(br.getName());
s.setHidden(br.isHidden());
addSheet(s);
} else {
logger.warn("BOF is unrecognized");
while (this.excelFile.hasNext() && r.getType() != Type.EOF)
r = this.excelFile.next();
}
bof = null;
if (this.excelFile.hasNext()) {
r = this.excelFile.next();
if (r.getType() == Type.BOF)
bof = new BOFRecord(r);
}
}
for (NameRecord nr : localNames) {
if (nr.getBuiltInName() == null) {
logger.warn("Usage of a local non-builtin name");
continue;
}
if (nr.getBuiltInName() == BuiltInName.PRINT_AREA || nr.getBuiltInName() == BuiltInName.PRINT_TITLES) {
SheetImpl s = this.sheets.get(nr.getSheetRef() - 1);
s.addLocalName(nr);
}
}
}
public FormattingRecords getFormattingRecords() {
return this.formattingRecords;
}
public ExternalSheetRecord getExternalSheetRecord() {
return this.externSheet;
}
public MsoDrawingGroupRecord getMsoDrawingGroupRecord() {
return this.msoDrawingGroup;
}
public SupbookRecord[] getSupbookRecords() {
SupbookRecord[] sr = new SupbookRecord[this.supbooks.size()];
return (SupbookRecord[])this.supbooks.toArray(sr);
}
public NameRecord[] getNameRecords() {
NameRecord[] na = new NameRecord[this.nameTable.size()];
return (NameRecord[])this.nameTable.toArray(na);
}
public Fonts getFonts() {
return this.fonts;
}
public Cell getCell(String loc) {
Sheet s = getSheet(CellReferenceHelper.getSheet(loc));
return s.getCell(loc);
}
public Cell findCellByName(String name) {
NameRecord nr = (NameRecord)this.namedRecords.get(name);
if (nr == null)
return null;
NameRecord.NameRange[] ranges = nr.getRanges();
Sheet s = getSheet(getExternalSheetIndex(ranges[0].getExternalSheet()));
int col = ranges[0].getFirstColumn();
int row = ranges[0].getFirstRow();
if (col > s.getColumns() || row > s.getRows())
return new EmptyCell(col, row);
Cell cell = s.getCell(col, row);
return cell;
}
public Range[] findByName(String name) {
NameRecord nr = (NameRecord)this.namedRecords.get(name);
if (nr == null)
return null;
NameRecord.NameRange[] ranges = nr.getRanges();
Range[] cellRanges = new Range[ranges.length];
for (int i = 0; i < ranges.length; i++)
cellRanges[i] = new RangeImpl(this, getExternalSheetIndex(ranges[i].getExternalSheet()), ranges[i].getFirstColumn(), ranges[i].getFirstRow(), getLastExternalSheetIndex(ranges[i].getExternalSheet()), ranges[i].getLastColumn(), ranges[i].getLastRow());
return cellRanges;
}
public String[] getRangeNames() {
Object[] keys = this.namedRecords.keySet().toArray();
String[] names = new String[keys.length];
System.arraycopy(keys, 0, names, 0, keys.length);
return names;
}
public BOFRecord getWorkbookBof() {
return this.workbookBof;
}
public boolean isProtected() {
return this.wbProtected;
}
public WorkbookSettings getSettings() {
return this.settings;
}
public int getExternalSheetIndex(String sheetName) {
return 0;
}
public int getLastExternalSheetIndex(String sheetName) {
return 0;
}
public String getName(int index) throws NameRangeException {
if (index < 0 || index >= this.nameTable.size())
throw new NameRangeException();
return this.nameTable.get(index).getName();
}
public int getNameIndex(String name) {
NameRecord nr = (NameRecord)this.namedRecords.get(name);
return (nr != null) ? nr.getIndex() : 0;
}
public DrawingGroup getDrawingGroup() {
return this.drawingGroup;
}
public CompoundFile getCompoundFile() {
return this.excelFile.getCompoundFile();
}
public boolean containsMacros() {
return this.containsMacros;
}
public ButtonPropertySetRecord getButtonPropertySet() {
return this.buttonPropertySet;
}
public CountryRecord getCountryRecord() {
return this.countryRecord;
}
public String[] getAddInFunctionNames() {
String[] addins = new String[0];
return (String[])this.addInFunctions.toArray(addins);
}
public int getIndex(Sheet sheet) {
String name = sheet.getName();
int index = -1;
int pos = 0;
for (Iterator<BoundsheetRecord> i = this.boundsheets.iterator(); i.hasNext() && index == -1; ) {
BoundsheetRecord br = i.next();
if (br.getName().equals(name)) {
index = pos;
continue;
}
pos++;
}
return index;
}
public XCTRecord[] getXCTRecords() {
XCTRecord[] xctr = new XCTRecord[0];
return (XCTRecord[])this.xctRecords.toArray(xctr);
}
}

View file

@ -0,0 +1,25 @@
package jxl.read.biff;
import jxl.WorkbookSettings;
import jxl.biff.RecordData;
import jxl.biff.StringHelper;
import jxl.biff.Type;
class WriteAccessRecord extends RecordData {
private String wauser;
public WriteAccessRecord(Record t, boolean isBiff8, WorkbookSettings ws) {
super(Type.WRITEACCESS);
byte[] data = t.getData();
if (isBiff8) {
this.wauser = StringHelper.getUnicodeString(data, 56, 0);
} else {
int length = data[1];
this.wauser = StringHelper.getString(data, length, 1, ws);
}
}
public String getWriteAccess() {
return this.wauser;
}
}