jxl.write.biff.SheetWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jxl Show documentation
Show all versions of jxl Show documentation
JExcelApi is a java library which provides the ability to read, write, and modify Microsoft Excel spreadsheets.
The newest version!
/*********************************************************************
*
* Copyright (C) 2002 Andrew Khan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
***************************************************************************/
package jxl.write.biff;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeSet;
import jxl.common.Assert;
import jxl.common.Logger;
import jxl.Cell;
import jxl.CellFeatures;
import jxl.CellReferenceHelper;
import jxl.Range;
import jxl.SheetSettings;
import jxl.WorkbookSettings;
import jxl.biff.AutoFilter;
import jxl.biff.ConditionalFormat;
import jxl.biff.DataValidation;
import jxl.biff.DataValiditySettingsRecord;
import jxl.biff.DVParser;
import jxl.biff.WorkspaceInformationRecord;
import jxl.biff.XFRecord;
import jxl.biff.drawing.Chart;
import jxl.biff.drawing.SheetDrawingWriter;
import jxl.biff.formula.FormulaException;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.Colour;
import jxl.write.Blank;
import jxl.write.WritableCell;
import jxl.write.WritableCellFormat;
import jxl.write.WritableHyperlink;
import jxl.write.WriteException;
/**
* Contains the functionality necessary for writing out a sheet. Originally
* this was incorporated in WritableSheetImpl, but was moved out into
* a dedicated class in order to reduce the over bloated nature of that
* class
*/
final class SheetWriter
{
/**
* The logger
*/
private static Logger logger = Logger.getLogger(SheetWriter.class);
/**
* A handle to the output file which the binary data is written to
*/
private File outputFile;
/**
* The rows within this sheet
*/
private RowRecord[] rows;
/**
* A number of rows. This is a count of the maximum row number + 1
*/
private int numRows;
/**
* The number of columns. This is a count of the maximum column number + 1
*/
private int numCols;
/**
* The page header
*/
private HeaderRecord header;
/**
* The page footer
*/
private FooterRecord footer;
/**
* The settings for the sheet
*/
private SheetSettings settings;
/**
* The settings for the workbook
*/
private WorkbookSettings workbookSettings;
/**
* Array of row page breaks
*/
private ArrayList rowBreaks;
/**
* Array of column page breaks
*/
private ArrayList columnBreaks;
/**
* Array of hyperlinks
*/
private ArrayList hyperlinks;
/**
* Array of conditional formats
*/
private ArrayList conditionalFormats;
/**
* The autofilter info
*/
private AutoFilter autoFilter;
/**
* Array of validated cells
*/
private ArrayList validatedCells;
/**
* The data validation validations
*/
private DataValidation dataValidation;
/**
* The list of merged ranges
*/
private MergedCells mergedCells;
/**
* The environment specific print record
*/
private PLSRecord plsRecord;
/**
* The button property ste
*/
private ButtonPropertySetRecord buttonPropertySet;
/**
* The workspace options
*/
private WorkspaceInformationRecord workspaceOptions;
/**
* The column format overrides
*/
private TreeSet columnFormats;
/**
* The list of drawings
*/
private SheetDrawingWriter drawingWriter;
/**
* Flag indicates that this sheet contains just a chart, and nothing
* else
*/
private boolean chartOnly;
/**
* The maximum row outline level
*/
private int maxRowOutlineLevel;
/**
* The maximum column outline level
*/
private int maxColumnOutlineLevel;
/**
* A handle back to the writable sheet, in order for this class
* to invoke the get accessor methods
*/
private WritableSheetImpl sheet;
/**
* Creates a new SheetWriter
instance.
*
* @param of the output file
*/
public SheetWriter(File of,
WritableSheetImpl wsi,
WorkbookSettings ws)
{
outputFile = of;
sheet = wsi;
workspaceOptions = new WorkspaceInformationRecord();
workbookSettings = ws;
chartOnly = false;
drawingWriter = new SheetDrawingWriter(ws);
}
/**
* Writes out this sheet. First writes out the standard sheet
* information then writes out each row in turn.
* Once all the rows have been written out, it retrospectively adjusts
* the offset references in the file
*
* @exception IOException
*/
public void write() throws IOException
{
Assert.verify(rows != null);
// This worksheet consists of just one chart, so write it and return
if (chartOnly)
{
drawingWriter.write(outputFile);
return;
}
BOFRecord bof = new BOFRecord(BOFRecord.sheet);
outputFile.write(bof);
// Compute the number of blocks of 32 rows that will be needed
int numBlocks = numRows / 32;
if (numRows - numBlocks * 32 != 0)
{
numBlocks++;
}
int indexPos = outputFile.getPos();
// Write the index record out now in order to serve as a place holder
// The bof passed in is the bof of the workbook, not this sheet
IndexRecord indexRecord = new IndexRecord(0, numRows, numBlocks);
outputFile.write(indexRecord);
if (settings.getAutomaticFormulaCalculation())
{
CalcModeRecord cmr = new CalcModeRecord(CalcModeRecord.automatic);
outputFile.write(cmr);
}
else
{
CalcModeRecord cmr = new CalcModeRecord(CalcModeRecord.manual);
outputFile.write(cmr);
}
CalcCountRecord ccr = new CalcCountRecord(0x64);
outputFile.write(ccr);
RefModeRecord rmr = new RefModeRecord();
outputFile.write(rmr);
IterationRecord itr = new IterationRecord(false);
outputFile.write(itr);
DeltaRecord dtr = new DeltaRecord(0.001);
outputFile.write(dtr);
SaveRecalcRecord srr = new SaveRecalcRecord
(settings.getRecalculateFormulasBeforeSave());
outputFile.write(srr);
PrintHeadersRecord phr = new PrintHeadersRecord
(settings.getPrintHeaders());
outputFile.write(phr);
PrintGridLinesRecord pglr = new PrintGridLinesRecord
(settings.getPrintGridLines());
outputFile.write(pglr);
GridSetRecord gsr = new GridSetRecord(true);
outputFile.write(gsr);
GuttersRecord gutr = new GuttersRecord();
gutr.setMaxColumnOutline(maxColumnOutlineLevel + 1);
gutr.setMaxRowOutline(maxRowOutlineLevel + 1);
outputFile.write(gutr);
DefaultRowHeightRecord drhr = new DefaultRowHeightRecord
(settings.getDefaultRowHeight(),
settings.getDefaultRowHeight() !=
SheetSettings.DEFAULT_DEFAULT_ROW_HEIGHT);
outputFile.write(drhr);
if (maxRowOutlineLevel > 0)
{
workspaceOptions.setRowOutlines(true);
}
if (maxColumnOutlineLevel > 0)
{
workspaceOptions.setColumnOutlines(true);
}
workspaceOptions.setFitToPages(settings.getFitToPages());
outputFile.write(workspaceOptions);
if (rowBreaks.size() > 0)
{
int[] rb = new int[rowBreaks.size()];
for (int i = 0; i < rb.length; i++)
{
rb[i] = ( (Integer) rowBreaks.get(i)).intValue();
}
HorizontalPageBreaksRecord hpbr = new HorizontalPageBreaksRecord(rb);
outputFile.write(hpbr);
}
if (columnBreaks.size() > 0)
{
int[] rb = new int[columnBreaks.size()];
for (int i = 0; i < rb.length; i++)
{
rb[i] = ( (Integer) columnBreaks.get(i)).intValue();
}
VerticalPageBreaksRecord hpbr = new VerticalPageBreaksRecord(rb);
outputFile.write(hpbr);
}
HeaderRecord header = new HeaderRecord(settings.getHeader().toString());
outputFile.write(header);
FooterRecord footer = new FooterRecord(settings.getFooter().toString());
outputFile.write(footer);
HorizontalCentreRecord hcr = new HorizontalCentreRecord
(settings.isHorizontalCentre());
outputFile.write(hcr);
VerticalCentreRecord vcr = new VerticalCentreRecord
(settings.isVerticalCentre());
outputFile.write(vcr);
// Write out the margins if they don't equal the default
if (settings.getLeftMargin() != settings.getDefaultWidthMargin())
{
MarginRecord mr = new LeftMarginRecord(settings.getLeftMargin());
outputFile.write(mr);
}
if (settings.getRightMargin() != settings.getDefaultWidthMargin())
{
MarginRecord mr = new RightMarginRecord(settings.getRightMargin());
outputFile.write(mr);
}
if (settings.getTopMargin() != settings.getDefaultHeightMargin())
{
MarginRecord mr = new TopMarginRecord(settings.getTopMargin());
outputFile.write(mr);
}
if (settings.getBottomMargin() != settings.getDefaultHeightMargin())
{
MarginRecord mr = new BottomMarginRecord(settings.getBottomMargin());
outputFile.write(mr);
}
if (plsRecord != null)
{
outputFile.write(plsRecord);
}
SetupRecord setup = new SetupRecord(settings);
outputFile.write(setup);
if (settings.isProtected())
{
ProtectRecord pr = new ProtectRecord(settings.isProtected());
outputFile.write(pr);
ScenarioProtectRecord spr = new ScenarioProtectRecord
(settings.isProtected());
outputFile.write(spr);
ObjectProtectRecord opr = new ObjectProtectRecord
(settings.isProtected());
outputFile.write(opr);
if (settings.getPassword() != null)
{
PasswordRecord pw = new PasswordRecord(settings.getPassword());
outputFile.write(pw);
}
else if (settings.getPasswordHash() != 0)
{
PasswordRecord pw = new PasswordRecord(settings.getPasswordHash());
outputFile.write(pw);
}
}
indexRecord.setDataStartPosition(outputFile.getPos());
DefaultColumnWidth dcw =
new DefaultColumnWidth(settings.getDefaultColumnWidth());
outputFile.write(dcw);
// Get a handle to the normal styles
WritableCellFormat normalStyle =
sheet.getWorkbook().getStyles().getNormalStyle();
WritableCellFormat defaultDateFormat =
sheet.getWorkbook().getStyles().getDefaultDateFormat();
// Write out all the column formats
ColumnInfoRecord cir = null;
for (Iterator colit = columnFormats.iterator(); colit.hasNext() ; )
{
cir = (ColumnInfoRecord) colit.next();
// Writing out the column info with index 0x100 causes excel to crash
if (cir.getColumn() < 0x100)
{
outputFile.write(cir);
}
XFRecord xfr = cir.getCellFormat();
if (xfr != normalStyle && cir.getColumn() < 0x100)
{
// Make this the format for every cell in the column
Cell[] cells = getColumn(cir.getColumn());
for (int i = 0; i < cells.length; i++)
{
if (cells[i] != null &&
(cells[i].getCellFormat() == normalStyle ||
cells[i].getCellFormat() == defaultDateFormat))
{
// The cell has no overriding format specified, so
// set it to the column default
((WritableCell) cells[i]).setCellFormat(xfr);
}
}
}
}
// Write out the auto filter
if (autoFilter != null)
{
autoFilter.write(outputFile);
}
DimensionRecord dr = new DimensionRecord(numRows, numCols);
outputFile.write(dr);
// Write out all the rows, in blocks of 32
for (int block = 0; block < numBlocks; block++)
{
DBCellRecord dbcell = new DBCellRecord(outputFile.getPos());
int blockRows = Math.min(32, numRows - block * 32);
boolean firstRow = true;
// First write out all the row records
for (int i = block * 32; i < block * 32 + blockRows; i++)
{
if (rows[i] != null)
{
rows[i].write(outputFile);
if (firstRow)
{
dbcell.setCellOffset(outputFile.getPos());
firstRow = false;
}
}
}
// Now write out all the cells
for (int i = block * 32; i < block * 32 + blockRows; i++)
{
if (rows[i] != null)
{
dbcell.addCellRowPosition(outputFile.getPos());
rows[i].writeCells(outputFile);
}
}
// Now set the current file position in the index record
indexRecord.addBlockPosition(outputFile.getPos());
// Set the position of the file pointer and write out the DBCell
// record
dbcell.setPosition(outputFile.getPos());
outputFile.write(dbcell);
}
// Do the drawings and charts if enabled
if (!workbookSettings.getDrawingsDisabled())
{
drawingWriter.write(outputFile);
}
Window2Record w2r = new Window2Record(settings);
outputFile.write(w2r);
// Handle the frozen panes
if (settings.getHorizontalFreeze() != 0 ||
settings.getVerticalFreeze() != 0)
{
PaneRecord pr = new PaneRecord(settings.getHorizontalFreeze(),
settings.getVerticalFreeze());
outputFile.write(pr);
// Handle the selection record. First, there will always be a top left
SelectionRecord sr = new SelectionRecord
(SelectionRecord.upperLeft, 0, 0);
outputFile.write(sr);
// Top right
if (settings.getHorizontalFreeze() != 0)
{
sr = new SelectionRecord
(SelectionRecord.upperRight, settings.getHorizontalFreeze(), 0);
outputFile.write(sr);
}
// Bottom left
if (settings.getVerticalFreeze() != 0)
{
sr = new SelectionRecord
(SelectionRecord.lowerLeft, 0, settings.getVerticalFreeze());
outputFile.write(sr);
}
// Bottom right
if (settings.getHorizontalFreeze() != 0 &&
settings.getVerticalFreeze() != 0)
{
sr = new SelectionRecord
(SelectionRecord.lowerRight,
settings.getHorizontalFreeze(),
settings.getVerticalFreeze());
outputFile.write(sr);
}
Weird1Record w1r = new Weird1Record();
outputFile.write(w1r);
}
else
{
// No frozen panes - just write out the selection record for the
// whole sheet
SelectionRecord sr = new SelectionRecord
(SelectionRecord.upperLeft, 0, 0);
outputFile.write(sr);
}
// Handle the zoom factor
if (settings.getZoomFactor() != 100)
{
SCLRecord sclr = new SCLRecord(settings.getZoomFactor());
outputFile.write(sclr);
}
// Now write out all the merged cells
mergedCells.write(outputFile);
// Write out all the hyperlinks
Iterator hi = hyperlinks.iterator();
WritableHyperlink hlr = null;
while (hi.hasNext())
{
hlr = (WritableHyperlink) hi.next();
outputFile.write(hlr);
}
if (buttonPropertySet != null)
{
outputFile.write(buttonPropertySet);
}
// Write out the data validations
if (dataValidation != null || validatedCells.size() > 0)
{
writeDataValidation();
}
// Write out the conditional formats
if (conditionalFormats != null && conditionalFormats.size() > 0)
{
for (Iterator i = conditionalFormats.iterator() ; i.hasNext() ; )
{
ConditionalFormat cf = (ConditionalFormat) i.next();
cf.write(outputFile);
}
}
EOFRecord eof = new EOFRecord();
outputFile.write(eof);
// Now the various cross reference offsets have been calculated,
// retrospectively set the values in the output file
outputFile.setData(indexRecord.getData(), indexPos+4);
}
/**
* Gets the header. Called when copying sheets
*
* @return the page header
*/
final HeaderRecord getHeader()
{
return header;
}
/**
* Gets the footer. Called when copying sheets
*
* @return the page footer
*/
final FooterRecord getFooter()
{
return footer;
}
/**
* Sets the data necessary for writing out the sheet. This method must
* be called immediately prior to writing
*
* @param rws the rows in the spreadsheet
*/
void setWriteData(RowRecord[] rws,
ArrayList rb,
ArrayList cb,
ArrayList hl,
MergedCells mc,
TreeSet cf,
int mrol,
int mcol)
{
rows = rws;
rowBreaks = rb;
columnBreaks = cb;
hyperlinks = hl;
mergedCells = mc;
columnFormats = cf;
maxRowOutlineLevel = mrol;
maxColumnOutlineLevel = mcol;
}
/**
* Sets the dimensions of this spreadsheet. This method must be called
* immediately prior to writing
*
* @param rws the number of rows
* @param cls the number of columns
*/
void setDimensions(int rws, int cls)
{
numRows = rws;
numCols = cls;
}
/**
* Sets the sheet settings for this particular sheet. Must be
* called immediately prior to writing
*
* @param sr the sheet settings
*/
void setSettings(SheetSettings sr)
{
settings = sr;
}
/**
* Accessor for the workspace options
*
* @return the workspace options
*/
WorkspaceInformationRecord getWorkspaceOptions()
{
return workspaceOptions;
}
/**
* Accessor for the workspace options
*
* @param wo the workspace options
*/
void setWorkspaceOptions(WorkspaceInformationRecord wo)
{
if (wo != null)
{
workspaceOptions = wo;
}
}
/**
* Sets the charts for this sheet
*
* @param ch the charts
*/
void setCharts(Chart[] ch)
{
drawingWriter.setCharts(ch);
}
/**
* Sets the drawings on this sheet
*
* @param dr the list of drawings
* @param mod a modified flag
*/
void setDrawings(ArrayList dr, boolean mod)
{
drawingWriter.setDrawings(dr, mod);
}
/**
* Accessor for the charts on this sheet
*
* @return the charts
*/
Chart[] getCharts()
{
return drawingWriter.getCharts();
}
/**
* Check all the merged cells for borders. If the merge record has
* borders, then we need to rejig the cell formats to take account of this.
* This is called by the write method of the WritableWorkbookImpl, so that
* any new XFRecords that are created may be written out with the others
*/
void checkMergedBorders()
{
Range[] mcells = mergedCells.getMergedCells();
ArrayList borderFormats = new ArrayList();
for (int mci = 0 ; mci < mcells.length ; mci++)
{
Range range = mcells[mci];
Cell topLeft = range.getTopLeft();
XFRecord tlformat = (XFRecord) topLeft.getCellFormat();
if (tlformat != null &&
tlformat.hasBorders() == true &&
!tlformat.isRead())
{
try
{
CellXFRecord cf1 = new CellXFRecord(tlformat);
Cell bottomRight = range.getBottomRight();
cf1.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
cf1.setBorder(Border.LEFT,
tlformat.getBorderLine(Border.LEFT),
tlformat.getBorderColour(Border.LEFT));
cf1.setBorder(Border.TOP,
tlformat.getBorderLine(Border.TOP),
tlformat.getBorderColour(Border.TOP));
if (topLeft.getRow() == bottomRight.getRow())
{
cf1.setBorder(Border.BOTTOM,
tlformat.getBorderLine(Border.BOTTOM),
tlformat.getBorderColour(Border.BOTTOM));
}
if (topLeft.getColumn() == bottomRight.getColumn())
{
cf1.setBorder(Border.RIGHT,
tlformat.getBorderLine(Border.RIGHT),
tlformat.getBorderColour(Border.RIGHT));
}
int index = borderFormats.indexOf(cf1);
if (index != -1)
{
cf1 = (CellXFRecord) borderFormats.get(index);
}
else
{
borderFormats.add(cf1);
}
( (WritableCell) topLeft).setCellFormat(cf1);
// Handle the bottom left corner
if (bottomRight.getRow() > topLeft.getRow())
{
// Handle the corner cell
if (bottomRight.getColumn() != topLeft.getColumn())
{
CellXFRecord cf2 = new CellXFRecord(tlformat);
cf2.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
cf2.setBorder(Border.LEFT,
tlformat.getBorderLine(Border.LEFT),
tlformat.getBorderColour(Border.LEFT));
cf2.setBorder(Border.BOTTOM,
tlformat.getBorderLine(Border.BOTTOM),
tlformat.getBorderColour(Border.BOTTOM));
index = borderFormats.indexOf(cf2);
if (index != -1)
{
cf2 = (CellXFRecord) borderFormats.get(index);
}
else
{
borderFormats.add(cf2);
}
sheet.addCell(new Blank(topLeft.getColumn(),
bottomRight.getRow(), cf2));
}
// Handle the cells down the left hand side (and along the
// right too, if necessary)
for (int i = topLeft.getRow() + 1; i < bottomRight.getRow() ;i++)
{
CellXFRecord cf3 = new CellXFRecord(tlformat);
cf3.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
cf3.setBorder(Border.LEFT,
tlformat.getBorderLine(Border.LEFT),
tlformat.getBorderColour(Border.LEFT));
if (topLeft.getColumn() == bottomRight.getColumn())
{
cf3.setBorder(Border.RIGHT,
tlformat.getBorderLine(Border.RIGHT),
tlformat.getBorderColour(Border.RIGHT));
}
index = borderFormats.indexOf(cf3);
if (index != -1)
{
cf3 = (CellXFRecord) borderFormats.get(index);
}
else
{
borderFormats.add(cf3);
}
sheet.addCell(new Blank(topLeft.getColumn(), i, cf3));
}
}
// Handle the top right corner
if (bottomRight.getColumn() > topLeft.getColumn())
{
if (bottomRight.getRow() != topLeft.getRow())
{
// Handle the corner cell
CellXFRecord cf6 = new CellXFRecord(tlformat);
cf6.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
cf6.setBorder(Border.RIGHT,
tlformat.getBorderLine(Border.RIGHT),
tlformat.getBorderColour(Border.RIGHT));
cf6.setBorder(Border.TOP,
tlformat.getBorderLine(Border.TOP),
tlformat.getBorderColour(Border.TOP));
index = borderFormats.indexOf(cf6);
if (index != -1)
{
cf6 = (CellXFRecord) borderFormats.get(index);
}
else
{
borderFormats.add(cf6);
}
sheet.addCell(new Blank(bottomRight.getColumn(),
topLeft.getRow(), cf6));
}
// Handle the cells along the right
for (int i = topLeft.getRow() + 1;
i < bottomRight.getRow() ;i++)
{
CellXFRecord cf7 = new CellXFRecord(tlformat);
cf7.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
cf7.setBorder(Border.RIGHT,
tlformat.getBorderLine(Border.RIGHT),
tlformat.getBorderColour(Border.RIGHT));
index = borderFormats.indexOf(cf7);
if (index != -1)
{
cf7 = (CellXFRecord) borderFormats.get(index);
}
else
{
borderFormats.add(cf7);
}
sheet.addCell(new Blank(bottomRight.getColumn(), i, cf7));
}
// Handle the cells along the top, and along the bottom too
for (int i = topLeft.getColumn() + 1;
i < bottomRight.getColumn() ;i++)
{
CellXFRecord cf8 = new CellXFRecord(tlformat);
cf8.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
cf8.setBorder(Border.TOP,
tlformat.getBorderLine(Border.TOP),
tlformat.getBorderColour(Border.TOP));
if (topLeft.getRow() == bottomRight.getRow())
{
cf8.setBorder(Border.BOTTOM,
tlformat.getBorderLine(Border.BOTTOM),
tlformat.getBorderColour(Border.BOTTOM));
}
index = borderFormats.indexOf(cf8);
if (index != -1)
{
cf8 = (CellXFRecord) borderFormats.get(index);
}
else
{
borderFormats.add(cf8);
}
sheet.addCell(new Blank(i, topLeft.getRow(), cf8));
}
}
// Handle the bottom right corner
if (bottomRight.getColumn() > topLeft.getColumn() ||
bottomRight.getRow() > topLeft.getRow())
{
// Handle the corner cell
CellXFRecord cf4 = new CellXFRecord(tlformat);
cf4.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
cf4.setBorder(Border.RIGHT,
tlformat.getBorderLine(Border.RIGHT),
tlformat.getBorderColour(Border.RIGHT));
cf4.setBorder(Border.BOTTOM,
tlformat.getBorderLine(Border.BOTTOM),
tlformat.getBorderColour(Border.BOTTOM));
if (bottomRight.getRow() == topLeft.getRow())
{
cf4.setBorder(Border.TOP,
tlformat.getBorderLine(Border.TOP),
tlformat.getBorderColour(Border.TOP));
}
if (bottomRight.getColumn() == topLeft.getColumn())
{
cf4.setBorder(Border.LEFT,
tlformat.getBorderLine(Border.LEFT),
tlformat.getBorderColour(Border.LEFT));
}
index = borderFormats.indexOf(cf4);
if (index != -1)
{
cf4 = (CellXFRecord) borderFormats.get(index);
}
else
{
borderFormats.add(cf4);
}
sheet.addCell(new Blank(bottomRight.getColumn(),
bottomRight.getRow(), cf4));
// Handle the cells along the bottom (and along the top
// as well, if appropriate)
for (int i = topLeft.getColumn() + 1;
i < bottomRight.getColumn() ;i++)
{
CellXFRecord cf5 = new CellXFRecord(tlformat);
cf5.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK);
cf5.setBorder(Border.BOTTOM,
tlformat.getBorderLine(Border.BOTTOM),
tlformat.getBorderColour(Border.BOTTOM));
if (topLeft.getRow() == bottomRight.getRow())
{
cf5.setBorder(Border.TOP,
tlformat.getBorderLine(Border.TOP),
tlformat.getBorderColour(Border.TOP));
}
index = borderFormats.indexOf(cf5);
if (index != -1)
{
cf5 = (CellXFRecord) borderFormats.get(index);
}
else
{
borderFormats.add(cf5);
}
sheet.addCell(new Blank(i, bottomRight.getRow(), cf5));
}
}
}
catch (WriteException e)
{
// just log e.toString(), not the whole stack trace
logger.warn(e.toString());
}
}
}
}
/**
* Get the cells in the column. Don't use the interface method
* getColumn for this as this will create loads of empty cells,
* and we could do without that overhead
*/
private Cell[] getColumn(int col)
{
// Find the last non-null cell
boolean found = false;
int row = numRows - 1;
while (row >= 0 && !found)
{
if (rows[row] != null &&
rows[row].getCell(col) != null)
{
found = true;
}
else
{
row--;
}
}
// Only create entries for non-empty cells
Cell[] cells = new Cell[row+1];
for (int i = 0; i <= row; i++)
{
cells[i] = rows[i] != null ? rows[i].getCell(col) : null;
}
return cells;
}
/**
* Sets a flag to indicate that this sheet contains a chart only
*/
void setChartOnly()
{
chartOnly = true;
}
/**
* Sets the environment specific print record
*
* @param pls the print record
*/
void setPLS(PLSRecord pls)
{
plsRecord = pls;
}
/**
* Sets the button property set record
*
* @param bps the button property set
*/
void setButtonPropertySet(ButtonPropertySetRecord bps)
{
buttonPropertySet = bps;
}
/**
* Sets the data validations
*
* @param dv the read-in list of data validations
* @param vc the api manipulated set of data validations
*/
void setDataValidation(DataValidation dv, ArrayList vc)
{
dataValidation = dv;
validatedCells = vc;
}
/**
* Sets the conditional formats
*
* @param cf the conditonal formats
*/
void setConditionalFormats(ArrayList cf)
{
conditionalFormats = cf;
}
/**
* Sets the auto filter
*
* @param af the autofilter
*/
void setAutoFilter(AutoFilter af)
{
autoFilter = af;
}
/**
* Writes out the data validations
*/
private void writeDataValidation() throws IOException
{
if (dataValidation != null && validatedCells.size() == 0)
{
// the only data validations are those read in - this should
// never be the case now that shared data validations add
// to the validatedCells list
dataValidation.write(outputFile);
return;
}
if (dataValidation == null && validatedCells.size() > 0)
{
// the only data validations are those which have been added by the
// write API. Need to sort out the combo box id
int comboBoxId = sheet.getComboBox() != null ?
sheet.getComboBox().getObjectId() : DataValidation.DEFAULT_OBJECT_ID;
dataValidation = new DataValidation(comboBoxId,
sheet.getWorkbook(),
sheet.getWorkbook(),
workbookSettings);
}
for (Iterator i = validatedCells.iterator(); i.hasNext(); )
{
CellValue cv = (CellValue) i.next();
CellFeatures cf = cv.getCellFeatures();
// Do not do anything if the DVParser has been copied, as it
// will already by on the DataValidation record as a result
// of the SheetCopier process
if (!cf.getDVParser().copied())
{
if (!cf.getDVParser().extendedCellsValidation())
{
// DVParser is specific for a single cell validation - just add it
DataValiditySettingsRecord dvsr =
new DataValiditySettingsRecord(cf.getDVParser());
dataValidation.add(dvsr);
}
else
{
// Only add the DVParser once for shared validations
// only add it if it is the top left cell
if (cv.getColumn() == cf.getDVParser().getFirstColumn() &&
cv.getRow() == cf.getDVParser().getFirstRow())
{
DataValiditySettingsRecord dvsr =
new DataValiditySettingsRecord(cf.getDVParser());
dataValidation.add(dvsr);
}
}
}
}
dataValidation.write(outputFile);
}
/*
// There is a mixture of read and write validations
for (Iterator i = validatedCells.iterator(); i.hasNext(); )
{
CellValue cv = (CellValue) i.next();
CellFeatures cf = cv.getCellFeatures();
DataValiditySettingsRecord dvsr =
new DataValiditySettingsRecord(cf.getDVParser());
dataValidation.add(dvsr);
}
dataValidation.write(outputFile);
return;
}
*/
}