1044 lines
33 KiB
Java
1044 lines
33 KiB
Java
package jxl.write.biff;
|
|
|
|
import common.Assert;
|
|
import common.Logger;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.Comparator;
|
|
import java.util.Iterator;
|
|
import java.util.TreeSet;
|
|
import jxl.BooleanCell;
|
|
import jxl.Cell;
|
|
import jxl.CellType;
|
|
import jxl.CellView;
|
|
import jxl.DateCell;
|
|
import jxl.HeaderFooter;
|
|
import jxl.Hyperlink;
|
|
import jxl.Image;
|
|
import jxl.LabelCell;
|
|
import jxl.NumberCell;
|
|
import jxl.Range;
|
|
import jxl.Sheet;
|
|
import jxl.SheetSettings;
|
|
import jxl.WorkbookSettings;
|
|
import jxl.biff.CellReferenceHelper;
|
|
import jxl.biff.EmptyCell;
|
|
import jxl.biff.FormattingRecords;
|
|
import jxl.biff.FormulaData;
|
|
import jxl.biff.IndexMapping;
|
|
import jxl.biff.NumFormatRecordsException;
|
|
import jxl.biff.SheetRangeImpl;
|
|
import jxl.biff.WorkspaceInformationRecord;
|
|
import jxl.biff.XFRecord;
|
|
import jxl.biff.drawing.Button;
|
|
import jxl.biff.drawing.Chart;
|
|
import jxl.biff.drawing.Comment;
|
|
import jxl.biff.drawing.Drawing;
|
|
import jxl.biff.drawing.DrawingGroupObject;
|
|
import jxl.format.CellFormat;
|
|
import jxl.format.PageOrientation;
|
|
import jxl.format.PaperSize;
|
|
import jxl.read.biff.ColumnInfoRecord;
|
|
import jxl.read.biff.DataValidation;
|
|
import jxl.read.biff.RowRecord;
|
|
import jxl.read.biff.SheetImpl;
|
|
import jxl.write.Blank;
|
|
import jxl.write.Boolean;
|
|
import jxl.write.DateTime;
|
|
import jxl.write.Label;
|
|
import jxl.write.Number;
|
|
import jxl.write.WritableCell;
|
|
import jxl.write.WritableCellFormat;
|
|
import jxl.write.WritableHyperlink;
|
|
import jxl.write.WritableImage;
|
|
import jxl.write.WritableSheet;
|
|
import jxl.write.WritableWorkbook;
|
|
import jxl.write.WriteException;
|
|
|
|
class WritableSheetImpl implements WritableSheet {
|
|
private static Logger logger = Logger.getLogger(WritableSheetImpl.class);
|
|
|
|
private String name;
|
|
|
|
private File outputFile;
|
|
|
|
private RowRecord[] rows;
|
|
|
|
private FormattingRecords formatRecords;
|
|
|
|
private SharedStrings sharedStrings;
|
|
|
|
private TreeSet columnFormats;
|
|
|
|
private ArrayList hyperlinks;
|
|
|
|
private MergedCells mergedCells;
|
|
|
|
private int numRows;
|
|
|
|
private int numColumns;
|
|
|
|
private PLSRecord plsRecord;
|
|
|
|
private ButtonPropertySetRecord buttonPropertySet;
|
|
|
|
private boolean chartOnly;
|
|
|
|
private DataValidation dataValidation;
|
|
|
|
private ArrayList rowBreaks;
|
|
|
|
private ArrayList drawings;
|
|
|
|
private ArrayList images;
|
|
|
|
private boolean drawingsModified;
|
|
|
|
private SheetSettings settings;
|
|
|
|
private SheetWriter sheetWriter;
|
|
|
|
private WorkbookSettings workbookSettings;
|
|
|
|
private WritableWorkbookImpl workbook;
|
|
|
|
private static final int rowGrowSize = 10;
|
|
|
|
private static final int numRowsPerSheet = 65536;
|
|
|
|
private static final int maxSheetNameLength = 31;
|
|
|
|
private static final char[] illegalSheetNameCharacters = new char[] { '*', ':', '?', '\\' };
|
|
|
|
private static final String[] imageTypes = new String[] { "png" };
|
|
|
|
private static class ColumnInfoComparator implements Comparator {
|
|
private ColumnInfoComparator() {}
|
|
|
|
public boolean equals(Object o) {
|
|
return (o == this);
|
|
}
|
|
|
|
public int compare(Object o1, Object o2) {
|
|
if (o1 == o2)
|
|
return 0;
|
|
Assert.verify(o1 instanceof ColumnInfoRecord);
|
|
Assert.verify(o2 instanceof ColumnInfoRecord);
|
|
ColumnInfoRecord ci1 = (ColumnInfoRecord)o1;
|
|
ColumnInfoRecord ci2 = (ColumnInfoRecord)o2;
|
|
return ci1.getColumn() - ci2.getColumn();
|
|
}
|
|
}
|
|
|
|
public WritableSheetImpl(String n, File of, FormattingRecords fr, SharedStrings ss, WorkbookSettings ws, WritableWorkbookImpl ww) {
|
|
this.name = validateName(n);
|
|
this.outputFile = of;
|
|
this.rows = new RowRecord[0];
|
|
this.numRows = 0;
|
|
this.numColumns = 0;
|
|
this.chartOnly = false;
|
|
this.workbook = ww;
|
|
this.formatRecords = fr;
|
|
this.sharedStrings = ss;
|
|
this.workbookSettings = ws;
|
|
this.drawingsModified = false;
|
|
this.columnFormats = new TreeSet(new ColumnInfoComparator());
|
|
this.hyperlinks = new ArrayList();
|
|
this.mergedCells = new MergedCells(this);
|
|
this.rowBreaks = new ArrayList();
|
|
this.drawings = new ArrayList();
|
|
this.images = new ArrayList();
|
|
this.settings = new SheetSettings();
|
|
this.sheetWriter = new SheetWriter(this.outputFile, this, this.workbookSettings);
|
|
}
|
|
|
|
public Cell getCell(String loc) {
|
|
return getCell(CellReferenceHelper.getColumn(loc), CellReferenceHelper.getRow(loc));
|
|
}
|
|
|
|
public Cell getCell(int column, int row) {
|
|
return (Cell)getWritableCell(column, row);
|
|
}
|
|
|
|
public WritableCell getWritableCell(String loc) {
|
|
return getWritableCell(CellReferenceHelper.getColumn(loc), CellReferenceHelper.getRow(loc));
|
|
}
|
|
|
|
public WritableCell getWritableCell(int column, int row) {
|
|
EmptyCell emptyCell;
|
|
WritableCell c = null;
|
|
if (row < this.rows.length && this.rows[row] != null)
|
|
c = this.rows[row].getCell(column);
|
|
if (c == null)
|
|
emptyCell = new EmptyCell(column, row);
|
|
return (WritableCell)emptyCell;
|
|
}
|
|
|
|
public int getRows() {
|
|
return this.numRows;
|
|
}
|
|
|
|
public int getColumns() {
|
|
return this.numColumns;
|
|
}
|
|
|
|
public Cell findCell(String contents) {
|
|
Cell cell = null;
|
|
boolean found = false;
|
|
for (int i = 0; i < getRows() && !found; i++) {
|
|
Cell[] row = getRow(i);
|
|
for (int j = 0; j < row.length && !found; j++) {
|
|
if (row[j].getContents().equals(contents)) {
|
|
cell = row[j];
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
return cell;
|
|
}
|
|
|
|
public LabelCell findLabelCell(String contents) {
|
|
LabelCell cell = null;
|
|
boolean found = false;
|
|
for (int i = 0; i < getRows() && !found; i++) {
|
|
Cell[] row = getRow(i);
|
|
for (int j = 0; j < row.length && !found; j++) {
|
|
if ((row[j].getType() == CellType.LABEL || row[j].getType() == CellType.STRING_FORMULA) && row[j].getContents().equals(contents)) {
|
|
cell = (LabelCell)row[j];
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
return cell;
|
|
}
|
|
|
|
public Cell[] getRow(int row) {
|
|
boolean found = false;
|
|
int col = this.numColumns - 1;
|
|
while (col >= 0 && !found) {
|
|
if (getCell(col, row).getType() != CellType.EMPTY) {
|
|
found = true;
|
|
continue;
|
|
}
|
|
col--;
|
|
}
|
|
Cell[] cells = new Cell[col + 1];
|
|
for (int i = 0; i <= col; i++)
|
|
cells[i] = getCell(i, row);
|
|
return cells;
|
|
}
|
|
|
|
public Cell[] getColumn(int col) {
|
|
boolean found = false;
|
|
int row = this.numRows - 1;
|
|
while (row >= 0 && !found) {
|
|
if (getCell(col, row).getType() != CellType.EMPTY) {
|
|
found = true;
|
|
continue;
|
|
}
|
|
row--;
|
|
}
|
|
Cell[] cells = new Cell[row + 1];
|
|
for (int i = 0; i <= row; i++)
|
|
cells[i] = getCell(col, i);
|
|
return cells;
|
|
}
|
|
|
|
public String getName() {
|
|
return this.name;
|
|
}
|
|
|
|
public void insertRow(int row) {
|
|
if (row < 0 || row >= this.numRows)
|
|
return;
|
|
RowRecord[] oldRows = this.rows;
|
|
if (this.numRows == this.rows.length) {
|
|
this.rows = new RowRecord[oldRows.length + 10];
|
|
} else {
|
|
this.rows = new RowRecord[oldRows.length];
|
|
}
|
|
System.arraycopy(oldRows, 0, this.rows, 0, row);
|
|
System.arraycopy(oldRows, row, this.rows, row + 1, this.numRows - row);
|
|
for (int i = row + 1; i <= this.numRows; i++) {
|
|
if (this.rows[i] != null)
|
|
this.rows[i].incrementRow();
|
|
}
|
|
HyperlinkRecord hr = null;
|
|
Iterator iterator = this.hyperlinks.iterator();
|
|
while (iterator.hasNext()) {
|
|
hr = iterator.next();
|
|
hr.insertRow(row);
|
|
}
|
|
if (this.dataValidation != null)
|
|
this.dataValidation.insertRow(row);
|
|
this.mergedCells.insertRow(row);
|
|
ArrayList newRowBreaks = new ArrayList();
|
|
Iterator ri = this.rowBreaks.iterator();
|
|
while (ri.hasNext()) {
|
|
int val = ((Integer)ri.next()).intValue();
|
|
if (val >= row)
|
|
val++;
|
|
newRowBreaks.add(new Integer(val));
|
|
}
|
|
this.rowBreaks = newRowBreaks;
|
|
if (this.workbookSettings.getFormulaAdjust())
|
|
this.workbook.rowInserted(this, row);
|
|
this.numRows++;
|
|
}
|
|
|
|
public void insertColumn(int col) {
|
|
if (col < 0 || col >= this.numColumns)
|
|
return;
|
|
for (int i = 0; i < this.numRows; i++) {
|
|
if (this.rows[i] != null)
|
|
this.rows[i].insertColumn(col);
|
|
}
|
|
HyperlinkRecord hr = null;
|
|
Iterator iterator = this.hyperlinks.iterator();
|
|
while (iterator.hasNext()) {
|
|
hr = iterator.next();
|
|
hr.insertColumn(col);
|
|
}
|
|
iterator = this.columnFormats.iterator();
|
|
while (iterator.hasNext()) {
|
|
ColumnInfoRecord cir = (ColumnInfoRecord)iterator.next();
|
|
if (cir.getColumn() >= col)
|
|
cir.incrementColumn();
|
|
}
|
|
if (this.dataValidation != null)
|
|
this.dataValidation.insertColumn(col);
|
|
this.mergedCells.insertColumn(col);
|
|
if (this.workbookSettings.getFormulaAdjust())
|
|
this.workbook.columnInserted(this, col);
|
|
this.numColumns++;
|
|
}
|
|
|
|
public void removeColumn(int col) {
|
|
if (col < 0 || col >= this.numColumns)
|
|
return;
|
|
for (int i = 0; i < this.numRows; i++) {
|
|
if (this.rows[i] != null)
|
|
this.rows[i].removeColumn(col);
|
|
}
|
|
HyperlinkRecord hr = null;
|
|
Iterator iterator = this.hyperlinks.iterator();
|
|
while (iterator.hasNext()) {
|
|
hr = iterator.next();
|
|
if (hr.getColumn() == col && hr.getLastColumn() == col) {
|
|
this.hyperlinks.remove(this.hyperlinks.indexOf(hr));
|
|
continue;
|
|
}
|
|
hr.removeColumn(col);
|
|
}
|
|
if (this.dataValidation != null)
|
|
this.dataValidation.removeColumn(col);
|
|
this.mergedCells.removeColumn(col);
|
|
iterator = this.columnFormats.iterator();
|
|
ColumnInfoRecord removeColumn = null;
|
|
while (iterator.hasNext()) {
|
|
ColumnInfoRecord cir = (ColumnInfoRecord)iterator.next();
|
|
if (cir.getColumn() == col) {
|
|
removeColumn = cir;
|
|
continue;
|
|
}
|
|
if (cir.getColumn() > col)
|
|
cir.decrementColumn();
|
|
}
|
|
if (removeColumn != null)
|
|
this.columnFormats.remove(removeColumn);
|
|
if (this.workbookSettings.getFormulaAdjust())
|
|
this.workbook.columnRemoved(this, col);
|
|
this.numColumns--;
|
|
}
|
|
|
|
public void removeRow(int row) {
|
|
if (row < 0 || row >= this.numRows)
|
|
return;
|
|
RowRecord[] oldRows = this.rows;
|
|
this.rows = new RowRecord[oldRows.length];
|
|
System.arraycopy(oldRows, 0, this.rows, 0, row);
|
|
System.arraycopy(oldRows, row + 1, this.rows, row, this.numRows - row + 1);
|
|
for (int i = row; i < this.numRows; i++) {
|
|
if (this.rows[i] != null)
|
|
this.rows[i].decrementRow();
|
|
}
|
|
HyperlinkRecord hr = null;
|
|
Iterator iterator = this.hyperlinks.iterator();
|
|
while (iterator.hasNext()) {
|
|
hr = iterator.next();
|
|
if (hr.getRow() == row && hr.getLastRow() == row) {
|
|
iterator.remove();
|
|
continue;
|
|
}
|
|
hr.removeRow(row);
|
|
}
|
|
if (this.dataValidation != null)
|
|
this.dataValidation.removeRow(row);
|
|
this.mergedCells.removeRow(row);
|
|
ArrayList newRowBreaks = new ArrayList();
|
|
Iterator ri = this.rowBreaks.iterator();
|
|
while (ri.hasNext()) {
|
|
int val = ((Integer)ri.next()).intValue();
|
|
if (val != row) {
|
|
if (val > row)
|
|
val--;
|
|
newRowBreaks.add(new Integer(val));
|
|
}
|
|
}
|
|
this.rowBreaks = newRowBreaks;
|
|
if (this.workbookSettings.getFormulaAdjust())
|
|
this.workbook.rowRemoved(this, row);
|
|
this.numRows--;
|
|
}
|
|
|
|
public void addCell(WritableCell cell) throws WriteException, RowsExceededException {
|
|
if (cell.getType() == CellType.EMPTY)
|
|
if (cell != null && cell.getCellFormat() == null)
|
|
return;
|
|
CellValue cv = (CellValue)cell;
|
|
if (cv.isReferenced())
|
|
throw new JxlWriteException(JxlWriteException.cellReferenced);
|
|
int row = cell.getRow();
|
|
RowRecord rowrec = getRowRecord(row);
|
|
rowrec.addCell(cv);
|
|
this.numRows = Math.max(row + 1, this.numRows);
|
|
this.numColumns = Math.max(this.numColumns, rowrec.getMaxColumn());
|
|
cv.setCellDetails(this.formatRecords, this.sharedStrings, this);
|
|
}
|
|
|
|
private RowRecord getRowRecord(int row) throws RowsExceededException {
|
|
if (row >= 65536)
|
|
throw new RowsExceededException();
|
|
if (row >= this.rows.length) {
|
|
RowRecord[] oldRows = this.rows;
|
|
this.rows = new RowRecord[Math.max(oldRows.length + 10, row + 1)];
|
|
System.arraycopy(oldRows, 0, this.rows, 0, oldRows.length);
|
|
oldRows = null;
|
|
}
|
|
RowRecord rowrec = this.rows[row];
|
|
if (rowrec == null) {
|
|
rowrec = new RowRecord(row);
|
|
this.rows[row] = rowrec;
|
|
}
|
|
return rowrec;
|
|
}
|
|
|
|
RowRecord getRowInfo(int r) {
|
|
if (r < 0 || r > this.rows.length)
|
|
return null;
|
|
return this.rows[r];
|
|
}
|
|
|
|
ColumnInfoRecord getColumnInfo(int c) {
|
|
Iterator i = this.columnFormats.iterator();
|
|
ColumnInfoRecord cir = null;
|
|
boolean stop = false;
|
|
while (i.hasNext() && !stop) {
|
|
cir = i.next();
|
|
if (cir.getColumn() >= c)
|
|
stop = true;
|
|
}
|
|
if (!stop)
|
|
return null;
|
|
return (cir.getColumn() == c) ? cir : null;
|
|
}
|
|
|
|
public void setName(String n) {
|
|
this.name = n;
|
|
}
|
|
|
|
public void setHidden(boolean h) {
|
|
this.settings.setHidden(h);
|
|
}
|
|
|
|
public void setProtected(boolean prot) {
|
|
this.settings.setProtected(prot);
|
|
}
|
|
|
|
public void setSelected() {
|
|
this.settings.setSelected();
|
|
}
|
|
|
|
public boolean isHidden() {
|
|
return this.settings.isHidden();
|
|
}
|
|
|
|
public void setColumnView(int col, int width) {
|
|
CellView cv = new CellView();
|
|
cv.setSize(width * 256);
|
|
setColumnView(col, cv);
|
|
}
|
|
|
|
public void setColumnView(int col, int width, CellFormat format) {
|
|
CellView cv = new CellView();
|
|
cv.setSize(width * 256);
|
|
cv.setFormat(format);
|
|
setColumnView(col, cv);
|
|
}
|
|
|
|
public void setColumnView(int col, CellView view) {
|
|
WritableCellFormat writableCellFormat;
|
|
XFRecord xfr = (XFRecord)view.getFormat();
|
|
if (xfr == null) {
|
|
Styles styles = getWorkbook().getStyles();
|
|
writableCellFormat = styles.getNormalStyle();
|
|
}
|
|
try {
|
|
if (!writableCellFormat.isInitialized())
|
|
this.formatRecords.addStyle((XFRecord)writableCellFormat);
|
|
int width = view.depUsed() ? (view.getDimension() * 256) : view.getSize();
|
|
ColumnInfoRecord cir = new ColumnInfoRecord(col, width, (XFRecord)writableCellFormat);
|
|
if (view.isHidden())
|
|
cir.setHidden(true);
|
|
if (!this.columnFormats.contains(cir)) {
|
|
this.columnFormats.add(cir);
|
|
} else {
|
|
this.columnFormats.remove(cir);
|
|
this.columnFormats.add(cir);
|
|
}
|
|
} catch (NumFormatRecordsException e) {
|
|
logger.warn("Maximum number of format records exceeded. Using default format.");
|
|
ColumnInfoRecord cir = new ColumnInfoRecord(col, view.getDimension() * 256, (XFRecord)WritableWorkbook.NORMAL_STYLE);
|
|
if (!this.columnFormats.contains(cir))
|
|
this.columnFormats.add(cir);
|
|
}
|
|
}
|
|
|
|
public void setRowView(int row, int height) throws RowsExceededException {
|
|
setRowView(row, height, false);
|
|
}
|
|
|
|
public void setRowView(int row, boolean collapsed) throws RowsExceededException {
|
|
RowRecord rowrec = getRowRecord(row);
|
|
rowrec.setCollapsed(collapsed);
|
|
}
|
|
|
|
public void setRowView(int row, int height, boolean collapsed) throws RowsExceededException {
|
|
RowRecord rowrec = getRowRecord(row);
|
|
rowrec.setRowHeight(height);
|
|
rowrec.setCollapsed(collapsed);
|
|
}
|
|
|
|
public void write() throws IOException {
|
|
boolean dmod = this.drawingsModified;
|
|
if (this.workbook.getDrawingGroup() != null)
|
|
dmod |= this.workbook.getDrawingGroup().hasDrawingsOmitted();
|
|
this.sheetWriter.setWriteData(this.rows, this.rowBreaks, this.hyperlinks, this.mergedCells, this.columnFormats);
|
|
this.sheetWriter.setDimensions(getRows(), getColumns());
|
|
this.sheetWriter.setSettings(this.settings);
|
|
this.sheetWriter.setPLS(this.plsRecord);
|
|
this.sheetWriter.setDrawings(this.drawings, dmod);
|
|
this.sheetWriter.setButtonPropertySet(this.buttonPropertySet);
|
|
this.sheetWriter.setDataValidation(this.dataValidation);
|
|
this.sheetWriter.write();
|
|
}
|
|
|
|
private void copyCells(Sheet s) {
|
|
int cells = s.getRows();
|
|
Cell[] row = null;
|
|
Cell cell = null;
|
|
for (int i = 0; i < cells; i++) {
|
|
row = s.getRow(i);
|
|
for (int j = 0; j < row.length; j++) {
|
|
cell = row[j];
|
|
CellType ct = cell.getType();
|
|
try {
|
|
if (ct == CellType.LABEL) {
|
|
Label l = new Label((LabelCell)cell);
|
|
addCell((WritableCell)l);
|
|
} else if (ct == CellType.NUMBER) {
|
|
Number n = new Number((NumberCell)cell);
|
|
addCell((WritableCell)n);
|
|
} else if (ct == CellType.DATE) {
|
|
DateTime dt = new DateTime((DateCell)cell);
|
|
addCell((WritableCell)dt);
|
|
} else if (ct == CellType.BOOLEAN) {
|
|
Boolean b = new Boolean((BooleanCell)cell);
|
|
addCell((WritableCell)b);
|
|
} else if (ct == CellType.NUMBER_FORMULA) {
|
|
ReadNumberFormulaRecord fr = new ReadNumberFormulaRecord((FormulaData)cell);
|
|
addCell(fr);
|
|
} else if (ct == CellType.STRING_FORMULA) {
|
|
ReadStringFormulaRecord fr = new ReadStringFormulaRecord((FormulaData)cell);
|
|
addCell(fr);
|
|
} else if (ct == CellType.BOOLEAN_FORMULA) {
|
|
ReadBooleanFormulaRecord fr = new ReadBooleanFormulaRecord((FormulaData)cell);
|
|
addCell(fr);
|
|
} else if (ct == CellType.DATE_FORMULA) {
|
|
ReadDateFormulaRecord fr = new ReadDateFormulaRecord((FormulaData)cell);
|
|
addCell(fr);
|
|
} else if (ct == CellType.FORMULA_ERROR) {
|
|
ReadErrorFormulaRecord fr = new ReadErrorFormulaRecord((FormulaData)cell);
|
|
addCell(fr);
|
|
} else if (ct == CellType.EMPTY) {
|
|
if (cell.getCellFormat() != null) {
|
|
Blank b = new Blank(cell);
|
|
addCell((WritableCell)b);
|
|
}
|
|
}
|
|
} catch (WriteException e) {
|
|
Assert.verify(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void copyCells(WritableSheet s) {
|
|
int cells = s.getRows();
|
|
Cell[] row = null;
|
|
Cell cell = null;
|
|
for (int i = 0; i < cells; i++) {
|
|
row = s.getRow(i);
|
|
for (int j = 0; j < row.length; j++) {
|
|
cell = row[j];
|
|
try {
|
|
WritableCell wc = ((WritableCell)cell).copyTo(cell.getColumn(), cell.getRow());
|
|
addCell(wc);
|
|
} catch (WriteException e) {
|
|
Assert.verify(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void copy(Sheet s) {
|
|
this.settings = new SheetSettings(s.getSettings());
|
|
copyCells(s);
|
|
SheetImpl si = (SheetImpl)s;
|
|
ColumnInfoRecord[] readCirs = si.getColumnInfos();
|
|
for (int i = 0; i < readCirs.length; i++) {
|
|
ColumnInfoRecord rcir = readCirs[i];
|
|
for (int n = rcir.getStartColumn(); n <= rcir.getEndColumn(); n++) {
|
|
ColumnInfoRecord cir = new ColumnInfoRecord(rcir, n, this.formatRecords);
|
|
cir.setHidden(rcir.getHidden());
|
|
this.columnFormats.add(cir);
|
|
}
|
|
}
|
|
Hyperlink[] hls = s.getHyperlinks();
|
|
for (int j = 0; j < hls.length; j++) {
|
|
WritableHyperlink hr = new WritableHyperlink(hls[j], this);
|
|
this.hyperlinks.add(hr);
|
|
}
|
|
Range[] merged = s.getMergedCells();
|
|
for (int k = 0; k < merged.length; k++)
|
|
this.mergedCells.add((Range)new SheetRangeImpl((SheetRangeImpl)merged[k], (Sheet)this));
|
|
try {
|
|
RowRecord[] rowprops = si.getRowProperties();
|
|
for (int n = 0; n < rowprops.length; n++) {
|
|
RowRecord rr = getRowRecord(rowprops[n].getRowNumber());
|
|
XFRecord format = rowprops[n].hasDefaultFormat() ? this.formatRecords.getXFRecord(rowprops[n].getXFIndex()) : null;
|
|
rr.setRowDetails(rowprops[n].getRowHeight(), rowprops[n].matchesDefaultFontHeight(), rowprops[n].isCollapsed(), format);
|
|
}
|
|
} catch (RowsExceededException e) {
|
|
Assert.verify(false);
|
|
}
|
|
int[] rowbreaks = si.getRowPageBreaks();
|
|
if (rowbreaks != null)
|
|
for (int n = 0; n < rowbreaks.length; n++)
|
|
this.rowBreaks.add(new Integer(rowbreaks[n]));
|
|
DataValidation rdv = si.getDataValidation();
|
|
if (rdv != null)
|
|
this.dataValidation = new DataValidation(rdv, this.workbook, this.workbookSettings);
|
|
this.sheetWriter.setCharts(si.getCharts());
|
|
DrawingGroupObject[] dr = si.getDrawings();
|
|
for (int m = 0; m < dr.length; m++) {
|
|
if (dr[m] instanceof Drawing) {
|
|
WritableImage wi = new WritableImage(dr[m], this.workbook.getDrawingGroup());
|
|
this.drawings.add(wi);
|
|
this.images.add(wi);
|
|
} else if (dr[m] instanceof Comment) {
|
|
Comment c = new Comment(dr[m], this.workbook.getDrawingGroup(), this.workbookSettings);
|
|
this.drawings.add(c);
|
|
CellValue cv = (CellValue)getWritableCell(c.getColumn(), c.getRow());
|
|
Assert.verify((cv.getCellFeatures() != null));
|
|
cv.getWritableCellFeatures().setCommentDrawing(c);
|
|
} else if (dr[m] instanceof Button) {
|
|
Button b = new Button(dr[m], this.workbook.getDrawingGroup(), this.workbookSettings);
|
|
this.drawings.add(b);
|
|
}
|
|
}
|
|
this.sheetWriter.setWorkspaceOptions(si.getWorkspaceOptions());
|
|
if (si.getSheetBof().isChart()) {
|
|
this.chartOnly = true;
|
|
this.sheetWriter.setChartOnly();
|
|
}
|
|
if (si.getPLS() != null)
|
|
if (si.getWorkbookBof().isBiff7()) {
|
|
logger.warn("Cannot copy Biff7 print settings record - ignoring");
|
|
} else {
|
|
this.plsRecord = new PLSRecord(si.getPLS());
|
|
}
|
|
if (si.getButtonPropertySet() != null)
|
|
this.buttonPropertySet = new ButtonPropertySetRecord(si.getButtonPropertySet());
|
|
}
|
|
|
|
void copy(WritableSheet s) {
|
|
this.settings = new SheetSettings(s.getSettings());
|
|
copyCells(s);
|
|
this.columnFormats = ((WritableSheetImpl)s).columnFormats;
|
|
Range[] merged = s.getMergedCells();
|
|
for (int i = 0; i < merged.length; i++)
|
|
this.mergedCells.add((Range)new SheetRangeImpl((SheetRangeImpl)merged[i], (Sheet)this));
|
|
try {
|
|
RowRecord[] copyRows = ((WritableSheetImpl)s).rows;
|
|
RowRecord row = null;
|
|
for (int k = 0; k < copyRows.length; k++) {
|
|
row = copyRows[k];
|
|
if (row != null && (!row.isDefaultHeight() || row.isCollapsed())) {
|
|
RowRecord rr = getRowRecord(k);
|
|
rr.setRowDetails(row.getRowHeight(), row.matchesDefaultFontHeight(), row.isCollapsed(), row.getStyle());
|
|
}
|
|
}
|
|
} catch (RowsExceededException e) {
|
|
Assert.verify(false);
|
|
}
|
|
WritableSheetImpl si = (WritableSheetImpl)s;
|
|
this.rowBreaks = new ArrayList(si.rowBreaks);
|
|
DataValidation rdv = si.dataValidation;
|
|
if (rdv != null)
|
|
this.dataValidation = new DataValidation(rdv, this.workbook, this.workbookSettings);
|
|
this.sheetWriter.setCharts(si.getCharts());
|
|
DrawingGroupObject[] dr = si.getDrawings();
|
|
for (int j = 0; j < dr.length; j++) {
|
|
if (dr[j] instanceof Drawing) {
|
|
WritableImage wi = new WritableImage(dr[j], this.workbook.getDrawingGroup());
|
|
this.drawings.add(wi);
|
|
this.images.add(wi);
|
|
}
|
|
}
|
|
this.sheetWriter.setWorkspaceOptions(si.getWorkspaceOptions());
|
|
if (si.plsRecord != null)
|
|
this.plsRecord = new PLSRecord(si.plsRecord);
|
|
if (si.buttonPropertySet != null)
|
|
this.buttonPropertySet = new ButtonPropertySetRecord(si.buttonPropertySet);
|
|
}
|
|
|
|
final HeaderRecord getHeader() {
|
|
return this.sheetWriter.getHeader();
|
|
}
|
|
|
|
final FooterRecord getFooter() {
|
|
return this.sheetWriter.getFooter();
|
|
}
|
|
|
|
public boolean isProtected() {
|
|
return this.settings.isProtected();
|
|
}
|
|
|
|
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() {
|
|
return this.mergedCells.getMergedCells();
|
|
}
|
|
|
|
public WritableHyperlink[] getWritableHyperlinks() {
|
|
WritableHyperlink[] hl = new WritableHyperlink[this.hyperlinks.size()];
|
|
for (int i = 0; i < this.hyperlinks.size(); i++)
|
|
hl[i] = this.hyperlinks.get(i);
|
|
return hl;
|
|
}
|
|
|
|
public void removeHyperlink(WritableHyperlink h) {
|
|
removeHyperlink(h, false);
|
|
}
|
|
|
|
public void removeHyperlink(WritableHyperlink h, boolean preserveLabel) {
|
|
this.hyperlinks.remove(this.hyperlinks.indexOf(h));
|
|
if (!preserveLabel) {
|
|
Assert.verify((this.rows.length > h.getRow() && this.rows[h.getRow()] != null));
|
|
this.rows[h.getRow()].removeCell(h.getColumn());
|
|
}
|
|
}
|
|
|
|
public void addHyperlink(WritableHyperlink h) throws WriteException, RowsExceededException {
|
|
Cell c = getCell(h.getColumn(), h.getRow());
|
|
String contents = null;
|
|
if (h.isFile() || h.isUNC()) {
|
|
String cnts = h.getContents();
|
|
if (cnts == null) {
|
|
contents = h.getFile().getPath();
|
|
} else {
|
|
contents = cnts;
|
|
}
|
|
} else if (h.isURL()) {
|
|
String cnts = h.getContents();
|
|
if (cnts == null) {
|
|
contents = h.getURL().toString();
|
|
} else {
|
|
contents = cnts;
|
|
}
|
|
} else if (h.isLocation()) {
|
|
contents = h.getContents();
|
|
}
|
|
if (c.getType() == CellType.LABEL) {
|
|
Label l = (Label)c;
|
|
l.setString(contents);
|
|
l.setCellFormat((CellFormat)WritableWorkbook.HYPERLINK_STYLE);
|
|
} else {
|
|
Label l = new Label(h.getColumn(), h.getRow(), contents, (CellFormat)WritableWorkbook.HYPERLINK_STYLE);
|
|
addCell((WritableCell)l);
|
|
}
|
|
for (int i = h.getRow(); i <= h.getLastRow(); i++) {
|
|
for (int j = h.getColumn(); j <= h.getLastColumn(); j++) {
|
|
if (i != h.getRow() && j != h.getColumn())
|
|
if (this.rows[i] != null)
|
|
this.rows[i].removeCell(j);
|
|
}
|
|
}
|
|
h.initialize(this);
|
|
this.hyperlinks.add(h);
|
|
}
|
|
|
|
public Range mergeCells(int col1, int row1, int col2, int row2) throws WriteException, RowsExceededException {
|
|
if (col2 < col1 || row2 < row1)
|
|
logger.warn("Cannot merge cells - top left and bottom right incorrectly specified");
|
|
if (col2 >= this.numColumns || row2 >= this.numRows)
|
|
addCell((WritableCell)new Blank(col2, row2));
|
|
SheetRangeImpl range = new SheetRangeImpl((Sheet)this, col1, row1, col2, row2);
|
|
this.mergedCells.add((Range)range);
|
|
return (Range)range;
|
|
}
|
|
|
|
public void unmergeCells(Range r) {
|
|
this.mergedCells.unmergeCells(r);
|
|
}
|
|
|
|
public void setHeader(String l, String c, String r) {
|
|
HeaderFooter header = new HeaderFooter();
|
|
header.getLeft().append(l);
|
|
header.getCentre().append(c);
|
|
header.getRight().append(r);
|
|
this.settings.setHeader(header);
|
|
}
|
|
|
|
public void setFooter(String l, String c, String r) {
|
|
HeaderFooter footer = new HeaderFooter();
|
|
footer.getLeft().append(l);
|
|
footer.getCentre().append(c);
|
|
footer.getRight().append(r);
|
|
this.settings.setFooter(footer);
|
|
}
|
|
|
|
public void setPageSetup(PageOrientation p) {
|
|
this.settings.setOrientation(p);
|
|
}
|
|
|
|
public void setPageSetup(PageOrientation p, double hm, double fm) {
|
|
this.settings.setOrientation(p);
|
|
this.settings.setHeaderMargin(hm);
|
|
this.settings.setFooterMargin(fm);
|
|
}
|
|
|
|
public void setPageSetup(PageOrientation p, PaperSize ps, double hm, double fm) {
|
|
this.settings.setPaperSize(ps);
|
|
this.settings.setOrientation(p);
|
|
this.settings.setHeaderMargin(hm);
|
|
this.settings.setFooterMargin(fm);
|
|
}
|
|
|
|
public SheetSettings getSettings() {
|
|
return this.settings;
|
|
}
|
|
|
|
WorkbookSettings getWorkbookSettings() {
|
|
return this.workbookSettings;
|
|
}
|
|
|
|
public void addRowPageBreak(int row) {
|
|
Iterator i = this.rowBreaks.iterator();
|
|
boolean found = false;
|
|
while (i.hasNext() && !found) {
|
|
if (((Integer)i.next()).intValue() == row)
|
|
found = true;
|
|
}
|
|
if (!found)
|
|
this.rowBreaks.add(new Integer(row));
|
|
}
|
|
|
|
private Chart[] getCharts() {
|
|
return this.sheetWriter.getCharts();
|
|
}
|
|
|
|
private DrawingGroupObject[] getDrawings() {
|
|
DrawingGroupObject[] dr = new DrawingGroupObject[this.drawings.size()];
|
|
dr = (DrawingGroupObject[])this.drawings.toArray((Object[])dr);
|
|
return dr;
|
|
}
|
|
|
|
void checkMergedBorders() {
|
|
this.sheetWriter.setWriteData(this.rows, this.rowBreaks, this.hyperlinks, this.mergedCells, this.columnFormats);
|
|
this.sheetWriter.setDimensions(getRows(), getColumns());
|
|
this.sheetWriter.checkMergedBorders();
|
|
}
|
|
|
|
private WorkspaceInformationRecord getWorkspaceOptions() {
|
|
return this.sheetWriter.getWorkspaceOptions();
|
|
}
|
|
|
|
void rationalize(IndexMapping xfMapping, IndexMapping fontMapping, IndexMapping formatMapping) {
|
|
for (Iterator iterator = this.columnFormats.iterator(); iterator.hasNext(); ) {
|
|
ColumnInfoRecord cir = iterator.next();
|
|
cir.rationalize(xfMapping);
|
|
}
|
|
for (int i = 0; i < this.rows.length; i++) {
|
|
if (this.rows[i] != null)
|
|
this.rows[i].rationalize(xfMapping);
|
|
}
|
|
Chart[] charts = getCharts();
|
|
for (int c = 0; c < charts.length; c++)
|
|
charts[c].rationalize(xfMapping, fontMapping, formatMapping);
|
|
}
|
|
|
|
WritableWorkbookImpl getWorkbook() {
|
|
return this.workbook;
|
|
}
|
|
|
|
public CellFormat getColumnFormat(int col) {
|
|
return getColumnView(col).getFormat();
|
|
}
|
|
|
|
public int getColumnWidth(int col) {
|
|
return getColumnView(col).getDimension();
|
|
}
|
|
|
|
public int getRowHeight(int row) {
|
|
return getRowView(row).getDimension();
|
|
}
|
|
|
|
boolean isChartOnly() {
|
|
return this.chartOnly;
|
|
}
|
|
|
|
public CellView getRowView(int row) {
|
|
CellView cv = new CellView();
|
|
try {
|
|
RowRecord rr = getRowRecord(row);
|
|
if (rr == null || rr.isDefaultHeight()) {
|
|
cv.setDimension(this.settings.getDefaultRowHeight());
|
|
cv.setSize(this.settings.getDefaultRowHeight());
|
|
} else if (rr.isCollapsed()) {
|
|
cv.setHidden(true);
|
|
} else {
|
|
cv.setDimension(rr.getRowHeight());
|
|
cv.setSize(rr.getRowHeight());
|
|
}
|
|
return cv;
|
|
} catch (RowsExceededException e) {
|
|
cv.setDimension(this.settings.getDefaultRowHeight());
|
|
cv.setSize(this.settings.getDefaultRowHeight());
|
|
return cv;
|
|
}
|
|
}
|
|
|
|
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((CellFormat)cir.getCellFormat());
|
|
} else {
|
|
cv.setDimension(this.settings.getDefaultColumnWidth() / 256);
|
|
cv.setSize(this.settings.getDefaultColumnWidth());
|
|
}
|
|
return cv;
|
|
}
|
|
|
|
public void addImage(WritableImage image) {
|
|
boolean supported = false;
|
|
File imageFile = image.getImageFile();
|
|
String fileType = "?";
|
|
if (imageFile != null) {
|
|
String fileName = imageFile.getName();
|
|
int fileTypeIndex = fileName.lastIndexOf('.');
|
|
fileType = (fileTypeIndex != -1) ? fileName.substring(fileTypeIndex + 1) : "";
|
|
for (int i = 0; i < imageTypes.length && !supported; i++) {
|
|
if (fileType.equalsIgnoreCase(imageTypes[i]))
|
|
supported = true;
|
|
}
|
|
} else {
|
|
supported = true;
|
|
}
|
|
if (supported) {
|
|
this.workbook.addDrawing((DrawingGroupObject)image);
|
|
this.drawings.add(image);
|
|
this.images.add(image);
|
|
} else {
|
|
StringBuffer message = new StringBuffer("Image type ");
|
|
message.append(fileType);
|
|
message.append(" not supported. Supported types are ");
|
|
message.append(imageTypes[0]);
|
|
for (int i = 1; i < imageTypes.length; i++) {
|
|
message.append(", ");
|
|
message.append(imageTypes[i]);
|
|
}
|
|
logger.warn(message.toString());
|
|
}
|
|
}
|
|
|
|
public int getNumberOfImages() {
|
|
return this.images.size();
|
|
}
|
|
|
|
public WritableImage getImage(int i) {
|
|
return this.images.get(i);
|
|
}
|
|
|
|
public Image getDrawing(int i) {
|
|
return this.images.get(i);
|
|
}
|
|
|
|
public void removeImage(WritableImage wi) {
|
|
this.drawings.remove(wi);
|
|
this.images.remove(wi);
|
|
this.drawingsModified = true;
|
|
this.workbook.removeDrawing((Drawing)wi);
|
|
}
|
|
|
|
private String validateName(String n) {
|
|
if (n.length() > 31) {
|
|
logger.warn("Sheet name " + n + " too long - truncating");
|
|
n = n.substring(0, 31);
|
|
}
|
|
if (n.charAt(0) == '\'') {
|
|
logger.warn("Sheet naming cannot start with ' - removing");
|
|
n = n.substring(1);
|
|
}
|
|
for (int i = 0; i < illegalSheetNameCharacters.length; i++) {
|
|
String newname = n.replace(illegalSheetNameCharacters[i], '@');
|
|
if (n != newname)
|
|
logger.warn(illegalSheetNameCharacters[i] + " is not a valid character within a sheet name - replacing");
|
|
n = newname;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
void addDrawing(DrawingGroupObject o) {
|
|
this.drawings.add(o);
|
|
Assert.verify(!(o instanceof Drawing));
|
|
}
|
|
|
|
void removeDrawing(DrawingGroupObject o) {
|
|
int origSize = this.drawings.size();
|
|
this.drawings.remove(o);
|
|
int newSize = this.drawings.size();
|
|
this.drawingsModified = true;
|
|
Assert.verify((newSize == origSize - 1));
|
|
}
|
|
|
|
public int[] getRowPageBreaks() {
|
|
int[] rb = new int[this.rowBreaks.size()];
|
|
int pos = 0;
|
|
for (Iterator i = this.rowBreaks.iterator(); i.hasNext(); pos++)
|
|
rb[pos] = ((Integer)i.next()).intValue();
|
|
return rb;
|
|
}
|
|
}
|