<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
</release>
<release version="3.2-alpha1" date="2008-??-??">
+ <action dev="POI-DEVELOPERS" type="add">45890 - fixed HSSFSheet.shiftRows to also update conditional formats</action>
<action dev="POI-DEVELOPERS" type="add">45865 modified Formula Parser/Evaluator to handle cross-worksheet formulas</action>
<action dev="POI-DEVELOPERS" type="add">Optimised the FormulaEvaluator to take cell dependencies into account</action>
<action dev="POI-DEVELOPERS" type="add">16936 - Initial support for whole-row cell styling</action>
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
</release>
<release version="3.2-alpha1" date="2008-??-??">
+ <action dev="POI-DEVELOPERS" type="add">45890 - fixed HSSFSheet.shiftRows to also update conditional formats</action>
<action dev="POI-DEVELOPERS" type="add">45865 modified Formula Parser/Evaluator to handle cross-worksheet formulas</action>
<action dev="POI-DEVELOPERS" type="add">Optimised the FormulaEvaluator to take cell dependencies into account</action>
<action dev="POI-DEVELOPERS" type="add">16936 - Initial support for whole-row cell styling</action>
/**
- * ModelFactory creates workbook and sheet models based upon
+ * ModelFactory creates workbook and sheet models based upon
* events thrown by them there events from the EventRecordFactory.
- *
+ *
* @see org.apache.poi.hssf.eventmodel.EventRecordFactory
* @author Andrew C. Oliver acoliver@apache.org
*/
List listeners;
Model currentmodel;
boolean lastEOF;
-
+
/**
* Constructor for ModelFactory. Does practically nothing.
*/
super();
listeners = new ArrayList(1);
}
-
+
/**
- * register a ModelFactoryListener so that it can receive
+ * register a ModelFactoryListener so that it can receive
* Models as they are created.
*/
public void registerListener(ModelFactoryListener listener) {
listeners.add(listener);
}
-
+
/**
* Start processing the Workbook stream into Model events.
*/
{
if (rec.getSid() == BOFRecord.sid) {
if (lastEOF != true) {
- throw new RuntimeException("Not yet handled embedded models");
+ throw new RuntimeException("Not yet handled embedded models");
} else {
BOFRecord bof = (BOFRecord)rec;
switch (bof.getType()) {
case BOFRecord.TYPE_WORKBOOK:
- currentmodel = new Workbook();
+ currentmodel = new Workbook();
break;
case BOFRecord.TYPE_WORKSHEET:
- currentmodel = new Sheet();
+ currentmodel = Sheet.createSheet();
break;
default:
throw new RuntimeException("Unsupported model type "+bof.getType());
- }
-
- }
+ }
+
+ }
}
-
+
if (rec.getSid() == EOFRecord.sid) {
lastEOF = true;
throwEvent(currentmodel);
} else {
- lastEOF = false;
+ lastEOF = false;
}
-
-
+
+
return true;
}
import java.util.List;
+import org.apache.poi.hssf.record.ArrayRecord;
import org.apache.poi.hssf.record.BOFRecord;
+import org.apache.poi.hssf.record.BlankRecord;
+import org.apache.poi.hssf.record.BoolErrRecord;
import org.apache.poi.hssf.record.CalcCountRecord;
import org.apache.poi.hssf.record.CalcModeRecord;
import org.apache.poi.hssf.record.DVALRecord;
import org.apache.poi.hssf.record.DrawingRecord;
import org.apache.poi.hssf.record.DrawingSelectionRecord;
import org.apache.poi.hssf.record.EOFRecord;
+import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.GridsetRecord;
import org.apache.poi.hssf.record.GutsRecord;
import org.apache.poi.hssf.record.HyperlinkRecord;
import org.apache.poi.hssf.record.IndexRecord;
import org.apache.poi.hssf.record.IterationRecord;
+import org.apache.poi.hssf.record.LabelRecord;
+import org.apache.poi.hssf.record.LabelSSTRecord;
+import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.PaneRecord;
import org.apache.poi.hssf.record.PrecisionRecord;
import org.apache.poi.hssf.record.PrintGridlinesRecord;
import org.apache.poi.hssf.record.PrintHeadersRecord;
+import org.apache.poi.hssf.record.RKRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.RefModeRecord;
+import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.hssf.record.SCLRecord;
import org.apache.poi.hssf.record.SaveRecalcRecord;
import org.apache.poi.hssf.record.SelectionRecord;
+import org.apache.poi.hssf.record.SharedFormulaRecord;
+import org.apache.poi.hssf.record.TableRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import org.apache.poi.hssf.record.UncalcedRecord;
import org.apache.poi.hssf.record.UnknownRecord;
* It is assumed that at least one row or cell value record has been found prior to the current
* record
*/
- public static boolean isEndOfRowBlock(short sid) {
+ public static boolean isEndOfRowBlock(int sid) {
switch(sid) {
case DrawingRecord.sid:
case DrawingSelectionRecord.sid:
}
return PageSettingsBlock.isComponentRecord(sid);
}
+
+ /**
+ * @return <code>true</code> if the specified record id normally appears in the row blocks section
+ * of the sheet records
+ */
+ public static boolean isRowBlockRecord(int sid) {
+ switch (sid) {
+ case RowRecord.sid:
+
+ case BlankRecord.sid:
+ case BoolErrRecord.sid:
+ case FormulaRecord.sid:
+ case LabelRecord.sid:
+ case LabelSSTRecord.sid:
+ case NumberRecord.sid:
+ case RKRecord.sid:
+
+ case ArrayRecord.sid:
+ case SharedFormulaRecord.sid:
+ case TableRecord.sid:
+ return true;
+
+ }
+ return false;
+ }
}
private final List _plainRecords;
private final SharedValueManager _sfm;
private final MergeCellsRecord[] _mergedCellsRecords;
- private final int _totalNumberOfRecords;
/**
* Also collects any loose MergeCellRecords and puts them in the supplied
* mergedCellsTable
*/
- public RowBlocksReader(List recs, int startIx) {
+ public RowBlocksReader(RecordStream rs) {
List plainRecords = new ArrayList();
List shFrmRecords = new ArrayList();
List arrayRecords = new ArrayList();
List tableRecords = new ArrayList();
List mergeCellRecords = new ArrayList();
- int endIx = -1;
- for (int i = startIx; i < recs.size(); i++) {
- Record rec = (Record) recs.get(i);
- if (RecordOrderer.isEndOfRowBlock(rec.getSid())) {
- // End of row/cell records for the current sheet
- // Note - It is important that this code does not inadvertently any sheet
- // records from a subsequent sheet. For example, if SharedFormulaRecords
- // are taken from the wrong sheet, this could cause bug 44449.
- endIx = i;
- break;
+ while(!RecordOrderer.isEndOfRowBlock(rs.peekNextSid())) {
+ // End of row/cell records for the current sheet
+ // Note - It is important that this code does not inadvertently add any sheet
+ // records from a subsequent sheet. For example, if SharedFormulaRecords
+ // are taken from the wrong sheet, this could cause bug 44449.
+ if (!rs.hasNext()) {
+ throw new RuntimeException("Failed to find end of row/cell records");
+
}
+ Record rec = rs.getNext();
List dest;
switch (rec.getSid()) {
case MergeCellsRecord.sid: dest = mergeCellRecords; break;
}
dest.add(rec);
}
- if (endIx < 0) {
- throw new RuntimeException("Failed to find end of row/cell records");
- }
SharedFormulaRecord[] sharedFormulaRecs = new SharedFormulaRecord[shFrmRecords.size()];
ArrayRecord[] arrayRecs = new ArrayRecord[arrayRecords.size()];
TableRecord[] tableRecs = new TableRecord[tableRecords.size()];
_sfm = SharedValueManager.create(sharedFormulaRecs, arrayRecs, tableRecs);
_mergedCellsRecords = new MergeCellsRecord[mergeCellRecords.size()];
mergeCellRecords.toArray(_mergedCellsRecords);
- _totalNumberOfRecords = endIx - startIx;
}
/**
return _mergedCellsRecords;
}
- public int getTotalNumberOfRecords() {
- return _totalNumberOfRecords;
- }
-
public SharedValueManager getSharedFormulaManager() {
return _sfm;
}
import org.apache.poi.hssf.record.UncalcedRecord;
import org.apache.poi.hssf.record.WSBoolRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
-import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
import org.apache.poi.hssf.record.aggregates.DataValidityTable;
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.PositionTrackingVisitor;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
+import org.apache.poi.hssf.record.formula.FormulaShifter;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.util.POILogFactory;
private static POILogger log = POILogFactory.getLogger(Sheet.class);
protected ArrayList records = null;
- protected int dimsloc = -1; // TODO - remove dimsloc
protected PrintGridlinesRecord printGridlines = null;
protected GridsetRecord gridset = null;
private GutsRecord _gutsRecord;
protected ObjectProtectRecord objprotect = null;
protected ScenarioProtectRecord scenprotect = null;
protected PasswordRecord password = null;
-
+
protected WindowTwoRecord windowTwo = null;
protected SelectionRecord selection = null;
/** java object always present, but if empty no BIFF records are written */
/** the DimensionsRecord is always present */
private DimensionsRecord _dimensions;
/** always present */
- protected RowRecordsAggregate _rowsAggregate;
+ protected final RowRecordsAggregate _rowsAggregate;
private DataValidityTable _dataValidityTable= null;
private ConditionalFormattingTable condFormatting;
- protected int eofLoc = 0;
private Iterator rowRecIterator = null;
/** Add an UncalcedRecord if not true indicating formulas have not been calculated */
protected boolean _isUncalced = false;
-
+
public static final byte PANE_LOWER_RIGHT = (byte)0;
public static final byte PANE_UPPER_RIGHT = (byte)1;
public static final byte PANE_LOWER_LEFT = (byte)2;
public static final byte PANE_UPPER_LEFT = (byte)3;
- /**
- * Creates new Sheet with no initialization --useless at this point
- * @see #createSheet(List,int,int)
- */
- public Sheet() {
- _mergedCellsTable = new MergedCellsTable();
- }
-
/**
* read support (offset used as starting point for search) for low level
* API. Pass in an array of Record objects, the sheet number (0 based) and
* @see org.apache.poi.hssf.model.Workbook
* @see org.apache.poi.hssf.record.Record
*/
- public static Sheet createSheet(List inRecs, int sheetnum, int offset)
- {
- if (log.check( POILogger.DEBUG ))
- log.logFormatted(POILogger.DEBUG,
- "Sheet createSheet (existing file) with %",
- new Integer(inRecs.size()));
- Sheet retval = new Sheet();
- ArrayList records = new ArrayList(inRecs.size() / 5);
+ public static Sheet createSheet(RecordStream rs) {
+ return new Sheet(rs);
+ }
+ private Sheet(RecordStream rs) {
+ _mergedCellsTable = new MergedCellsTable();
+ RowRecordsAggregate rra = null;
+
+ records = new ArrayList(128);
// TODO - take chart streams off into separate java objects
int bofEofNestingLevel = 0; // nesting level can only get to 2 (when charts are present)
+ int dimsloc = -1;
- for (int k = offset; k < inRecs.size(); k++) {
- Record rec = ( Record ) inRecs.get(k);
- if ( rec.getSid() == IndexRecord.sid ) {
- // ignore INDEX record because it is only needed by Excel,
- // and POI always re-calculates its contents
- continue;
- }
+ while (rs.hasNext()) {
+ int recSid = rs.peekNextSid();
- if ( rec.getSid() == CFHeaderRecord.sid ) {
- RecordStream rs = new RecordStream(inRecs, k);
- retval.condFormatting = new ConditionalFormattingTable(rs);
- k += rs.getCountRead()-1;
- records.add(retval.condFormatting);
+ if ( recSid == CFHeaderRecord.sid ) {
+ condFormatting = new ConditionalFormattingTable(rs);
+ records.add(condFormatting);
continue;
}
-
- if (rec.getSid() == ColumnInfoRecord.sid) {
- RecordStream rs = new RecordStream(inRecs, k);
- retval._columnInfos = new ColumnInfoRecordsAggregate(rs);
- k += rs.getCountRead()-1;
- records.add(retval._columnInfos);
+
+ if (recSid == ColumnInfoRecord.sid) {
+ _columnInfos = new ColumnInfoRecordsAggregate(rs);
+ records.add(_columnInfos);
continue;
}
- if ( rec.getSid() == DVALRecord.sid) {
- RecordStream rs = new RecordStream(inRecs, k);
- retval._dataValidityTable = new DataValidityTable(rs);
- k += rs.getCountRead() - 1; // TODO - convert this method result to be zero based
- records.add(retval._dataValidityTable);
+ if ( recSid == DVALRecord.sid) {
+ _dataValidityTable = new DataValidityTable(rs);
+ records.add(_dataValidityTable);
continue;
}
- // TODO construct RowRecordsAggregate from RecordStream
- if ((rec.getSid() == RowRecord.sid || rec.isValue()) && bofEofNestingLevel == 1 ) {
+
+ if (RecordOrderer.isRowBlockRecord(recSid) && bofEofNestingLevel == 1 ) {
//only add the aggregate once
- if (retval._rowsAggregate != null) {
+ if (rra != null) {
throw new RuntimeException("row/cell records found in the wrong place");
}
- RowBlocksReader rbr = new RowBlocksReader(inRecs, k);
- retval._mergedCellsTable.addRecords(rbr.getLooseMergedCells());
- retval._rowsAggregate = new RowRecordsAggregate(rbr.getPlainRecordStream(), rbr.getSharedFormulaManager());
- records.add(retval._rowsAggregate); //only add the aggregate once
- k += rbr.getTotalNumberOfRecords() - 1;
+ RowBlocksReader rbr = new RowBlocksReader(rs);
+ _mergedCellsTable.addRecords(rbr.getLooseMergedCells());
+ rra = new RowRecordsAggregate(rbr.getPlainRecordStream(), rbr.getSharedFormulaManager());
+ records.add(rra); //only add the aggregate once
continue;
}
-
- if (PageSettingsBlock.isComponentRecord(rec.getSid())) {
- RecordStream rs = new RecordStream(inRecs, k);
+
+ if (PageSettingsBlock.isComponentRecord(recSid)) {
PageSettingsBlock psb = new PageSettingsBlock(rs);
if (bofEofNestingLevel == 1) {
- if (retval._psBlock == null) {
- retval._psBlock = psb;
+ if (_psBlock == null) {
+ _psBlock = psb;
} else {
// more than one 'Page Settings Block' at nesting level 1 ?
// apparently this happens in about 15 test sample files
}
}
records.add(psb);
- k += rs.getCountRead()-1;
continue;
}
-
- if (rec.getSid() == MergeCellsRecord.sid) {
+
+ if (recSid == MergeCellsRecord.sid) {
// when the MergedCellsTable is found in the right place, we expect those records to be contiguous
- RecordStream rs = new RecordStream(inRecs, k);
- retval._mergedCellsTable.read(rs);
- k += rs.getCountRead()-1;
+ _mergedCellsTable.read(rs);
+ continue;
+ }
+
+ Record rec = rs.getNext();
+ if ( recSid == IndexRecord.sid ) {
+ // ignore INDEX record because it is only needed by Excel,
+ // and POI always re-calculates its contents
continue;
}
- if (rec.getSid() == UncalcedRecord.sid) {
+
+
+ if (recSid == UncalcedRecord.sid) {
// don't add UncalcedRecord to the list
- retval._isUncalced = true; // this flag is enough
+ _isUncalced = true; // this flag is enough
continue;
}
- if (rec.getSid() == BOFRecord.sid)
+ if (recSid == BOFRecord.sid)
{
bofEofNestingLevel++;
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Hit BOF record. Nesting increased to " + bofEofNestingLevel);
}
- else if (rec.getSid() == EOFRecord.sid)
+ else if (recSid == EOFRecord.sid)
{
--bofEofNestingLevel;
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Hit EOF record. Nesting decreased to " + bofEofNestingLevel);
if (bofEofNestingLevel == 0) {
records.add(rec);
- retval.eofLoc = k;
break;
}
}
- else if (rec.getSid() == DimensionsRecord.sid)
+ else if (recSid == DimensionsRecord.sid)
{
// Make a columns aggregate if one hasn't ready been created.
- if (retval._columnInfos == null)
+ if (_columnInfos == null)
{
- retval._columnInfos = new ColumnInfoRecordsAggregate();
- records.add(retval._columnInfos);
+ _columnInfos = new ColumnInfoRecordsAggregate();
+ records.add(_columnInfos);
}
- retval._dimensions = ( DimensionsRecord ) rec;
- retval.dimsloc = records.size();
+ _dimensions = ( DimensionsRecord ) rec;
+ dimsloc = records.size();
}
- else if (rec.getSid() == DefaultColWidthRecord.sid)
+ else if (recSid == DefaultColWidthRecord.sid)
{
- retval.defaultcolwidth = ( DefaultColWidthRecord ) rec;
+ defaultcolwidth = ( DefaultColWidthRecord ) rec;
}
- else if (rec.getSid() == DefaultRowHeightRecord.sid)
+ else if (recSid == DefaultRowHeightRecord.sid)
{
- retval.defaultrowheight = ( DefaultRowHeightRecord ) rec;
+ defaultrowheight = ( DefaultRowHeightRecord ) rec;
}
- else if ( rec.getSid() == PrintGridlinesRecord.sid )
+ else if ( recSid == PrintGridlinesRecord.sid )
{
- retval.printGridlines = (PrintGridlinesRecord) rec;
+ printGridlines = (PrintGridlinesRecord) rec;
}
- else if ( rec.getSid() == GridsetRecord.sid )
+ else if ( recSid == GridsetRecord.sid )
{
- retval.gridset = (GridsetRecord) rec;
+ gridset = (GridsetRecord) rec;
}
- else if ( rec.getSid() == SelectionRecord.sid )
+ else if ( recSid == SelectionRecord.sid )
{
- retval.selection = (SelectionRecord) rec;
+ selection = (SelectionRecord) rec;
}
- else if ( rec.getSid() == WindowTwoRecord.sid )
+ else if ( recSid == WindowTwoRecord.sid )
{
- retval.windowTwo = (WindowTwoRecord) rec;
+ windowTwo = (WindowTwoRecord) rec;
}
- else if ( rec.getSid() == ProtectRecord.sid )
+ else if ( recSid == ProtectRecord.sid )
{
- retval.protect = (ProtectRecord) rec;
+ protect = (ProtectRecord) rec;
}
- else if ( rec.getSid() == ObjectProtectRecord.sid )
+ else if ( recSid == ObjectProtectRecord.sid )
{
- retval.objprotect = (ObjectProtectRecord) rec;
+ objprotect = (ObjectProtectRecord) rec;
}
- else if ( rec.getSid() == ScenarioProtectRecord.sid )
+ else if ( recSid == ScenarioProtectRecord.sid )
{
- retval.scenprotect = (ScenarioProtectRecord) rec;
+ scenprotect = (ScenarioProtectRecord) rec;
}
- else if ( rec.getSid() == PasswordRecord.sid )
+ else if ( recSid == PasswordRecord.sid )
{
- retval.password = (PasswordRecord) rec;
+ password = (PasswordRecord) rec;
}
records.add(rec);
}
- if (retval._dimensions == null) {
+ if (_dimensions == null) {
throw new RuntimeException("DimensionsRecord was not found");
}
- if (retval.windowTwo == null) {
+ if (windowTwo == null) {
throw new RuntimeException("WINDOW2 was not found");
}
- if (retval._rowsAggregate == null) {
- retval._rowsAggregate = new RowRecordsAggregate();
- records.add(retval.dimsloc + 1, retval._rowsAggregate);
+ if (rra == null) {
+ rra = new RowRecordsAggregate();
+ records.add(dimsloc + 1, rra);
}
+ _rowsAggregate = rra;
// put merged cells table in the right place (regardless of where the first MergedCellsRecord was found */
- RecordOrderer.addNewSheetRecord(records, retval._mergedCellsTable);
- retval.records = records;
+ RecordOrderer.addNewSheetRecord(records, _mergedCellsTable);
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited");
- return retval;
}
private static final class RecordCloner implements RecordVisitor {
* belongs to a sheet.
*/
public Sheet cloneSheet() {
- ArrayList clonedRecords = new ArrayList(this.records.size());
+ List clonedRecords = new ArrayList(this.records.size());
for (int i = 0; i < this.records.size(); i++) {
RecordBase rb = (RecordBase) this.records.get(i);
if (rb instanceof RecordAggregate) {
Record rec = (Record) ((Record) rb).clone();
clonedRecords.add(rec);
}
- return createSheet(clonedRecords, 0, 0);
- }
-
-
- /**
- * read support (offset = 0) Same as createSheet(Record[] recs, int, int)
- * only the record offset is assumed to be 0.
- *
- * @param records array containing those records in the sheet in sequence (normally obtained from RecordFactory)
- * @param sheetnum integer specifying the sheet's number (0,1 or 2 in this release)
- * @return Sheet object
- */
-
- public static Sheet createSheet(List records, int sheetnum)
- {
- if (log.check( POILogger.DEBUG ))
- log.log(POILogger.DEBUG,
- "Sheet createSheet (exisiting file) assumed offset 0");
- return createSheet(records, sheetnum, 0);
+ return createSheet(new RecordStream(clonedRecords, 0));
}
/**
*
* @return Sheet object with all values set to defaults
*/
-
- public static Sheet createSheet()
- {
- // TODO - convert this method to a constructor
+ public static Sheet createSheet() {
+ return new Sheet();
+ }
+ private Sheet() {
+ _mergedCellsTable = new MergedCellsTable();
+ records = new ArrayList(32);
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Sheet createsheet from scratch called");
- Sheet retval = new Sheet();
- ArrayList records = new ArrayList(30);
records.add(createBOF());
- // records.add(retval.createIndex());
records.add(createCalcMode());
records.add(createCalcCount() );
records.add(createRefMode() );
records.add(createDelta() );
records.add(createSaveRecalc() );
records.add(createPrintHeaders() );
- retval.printGridlines = createPrintGridlines();
- records.add( retval.printGridlines );
- retval.gridset = createGridset();
- records.add( retval.gridset );
- retval._gutsRecord = createGuts();
- records.add( retval._gutsRecord );
- retval.defaultrowheight = createDefaultRowHeight();
- records.add( retval.defaultrowheight );
- records.add( retval.createWSBool() );
-
+ printGridlines = createPrintGridlines();
+ records.add( printGridlines );
+ gridset = createGridset();
+ records.add( gridset );
+ _gutsRecord = createGuts();
+ records.add( _gutsRecord );
+ defaultrowheight = createDefaultRowHeight();
+ records.add( defaultrowheight );
+ records.add( createWSBool() );
+
// 'Page Settings Block'
- retval._psBlock = new PageSettingsBlock();
- records.add(retval._psBlock);
-
+ _psBlock = new PageSettingsBlock();
+ records.add(_psBlock);
+
// 'Worksheet Protection Block' (after 'Page Settings Block' and before DEFCOLWIDTH)
// PROTECT record normally goes here, don't add yet since the flag is initially false
-
- retval.defaultcolwidth = createDefaultColWidth();
- records.add( retval.defaultcolwidth);
+
+ defaultcolwidth = createDefaultColWidth();
+ records.add( defaultcolwidth);
ColumnInfoRecordsAggregate columns = new ColumnInfoRecordsAggregate();
records.add( columns );
- retval._columnInfos = columns;
- retval._dimensions = createDimensions();
- records.add(retval._dimensions);
- retval.dimsloc = records.size()-1;
- retval._rowsAggregate = new RowRecordsAggregate();
- records.add(retval._rowsAggregate);
+ _columnInfos = columns;
+ _dimensions = createDimensions();
+ records.add(_dimensions);
+ _rowsAggregate = new RowRecordsAggregate();
+ records.add(_rowsAggregate);
// 'Sheet View Settings'
- records.add(retval.windowTwo = retval.createWindowTwo());
- retval.selection = createSelection();
- records.add(retval.selection);
+ records.add(windowTwo = createWindowTwo());
+ selection = createSelection();
+ records.add(selection);
- records.add(retval._mergedCellsTable); // MCT comes after 'Sheet View Settings'
+ records.add(_mergedCellsTable); // MCT comes after 'Sheet View Settings'
records.add(EOFRecord.instance);
-
- retval.records = records;
if (log.check( POILogger.DEBUG ))
log.log(POILogger.DEBUG, "Sheet createsheet from scratch exit");
- return retval;
}
public RowRecordsAggregate getRowsAggregate() {
- return _rowsAggregate;
+ return _rowsAggregate;
}
private MergedCellsTable getMergedRecords() {
return _mergedCellsTable;
}
+ /**
+ * Updates formulas in cells and conditional formats due to moving of cells
+ * @param externSheetIndex the externSheet index of this sheet
+ */
+ public void updateFormulasAfterCellShift(FormulaShifter shifter, int externSheetIndex) {
+ getRowsAggregate().updateFormulasAfterRowShift(shifter, externSheetIndex);
+ getConditionalFormattingTable().updateFormulasAfterCellShift(shifter, externSheetIndex);
+ // TODO - adjust data validations
+ }
public int addMergedRegion(int rowFrom, int colFrom, int rowTo, int colTo) {
// Validate input
public int getNumMergedRegions() {
return getMergedRecords().getNumberOfMergedRegions();
}
- private ConditionalFormattingTable getConditionalFormattingTable() {
+ public ConditionalFormattingTable getConditionalFormattingTable() {
if (condFormatting == null) {
condFormatting = new ConditionalFormattingTable();
RecordOrderer.addNewSheetRecord(records, condFormatting);
return condFormatting;
}
-
- public int addConditionalFormatting(CFRecordsAggregate cfAggregate) {
- ConditionalFormattingTable cft = getConditionalFormattingTable();
- return cft.add(cfAggregate);
- }
-
- public void removeConditionalFormatting(int index) {
- getConditionalFormattingTable().remove(index);
- }
-
- public CFRecordsAggregate getCFRecordsAggregateAt(int index) {
- return getConditionalFormattingTable().get(index);
- }
-
- public int getNumConditionalFormattings() {
- return getConditionalFormattingTable().size();
- }
-
/**
* Per an earlier reported bug in working with Andy Khan's excel read library. This
* sets the values in the sheet's DimensionsRecord object to be correct. Excel doesn't
public void visitContainedRecords(RecordVisitor rv, int offset) {
PositionTrackingVisitor ptv = new PositionTrackingVisitor(rv, offset);
-
+
boolean haveSerializedIndex = false;
for (int k = 0; k < records.size(); k++)
/**
* set the width for a given column in 1/256th of a character width units
- *
+ *
* @param column -
* the column number
* @param width
public WindowTwoRecord getWindowTwo() {
return windowTwo;
}
-
+
/**
* Returns the PrintGridlinesRecord.
* @return PrintGridlinesRecord for the sheet.
windowTwo.setSelected(sel);
}
- public int getEofLoc()
- {
- return eofLoc;
- }
-
/**
* Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
* @param colSplit Horizonatal position of split.
if (log.check( POILogger.DEBUG )) {
log.log(POILogger.DEBUG, "create protect record with protection disabled");
}
- ProtectRecord retval = new ProtectRecord();
+ ProtectRecord retval = new ProtectRecord();
retval.setProtect(false); // TODO - supply param to constructor
return retval;
}
}
}
-
+
public PageSettingsBlock getPageSettings() {
if (_psBlock == null) {
_psBlock = new PageSettingsBlock();
RecordOrderer.addNewSheetRecord(records, _psBlock);
- dimsloc++;
}
return _psBlock;
}
public void setColumnGroupCollapsed(int columnNumber, boolean collapsed) {
- if (collapsed) {
- _columnInfos.collapseColumn(columnNumber);
- } else {
- _columnInfos.expandColumn(columnNumber);
- }
- }
+ if (collapsed) {
+ _columnInfos.collapseColumn(columnNumber);
+ } else {
+ _columnInfos.expandColumn(columnNumber);
+ }
+ }
/**
* protect a spreadsheet with a password (not encypted, just sets protect
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
-/*
- * BlankRecord.java
- *
- * Created on December 10, 2001, 12:07 PM
- */
package org.apache.poi.hssf.record;
+import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
/**
- * Title: Blank cell record <P>
+ * Title: Blank cell record (0x0201) <P>
* Description: Represents a column in a row with no value but with styling.<P>
* REFERENCE: PG 287 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @version 2.0-pre
*/
public final class BlankRecord extends Record implements CellValueRecordInterface {
- public final static short sid = 0x201;
+ public final static short sid = 0x0201;
private int field_1_row;
private short field_2_col;
private short field_3_xf;
/** Creates a new instance of BlankRecord */
-
public BlankRecord()
{
}
* Constructs a BlankRecord and sets its fields appropriately
* @param in the RecordInputstream to read the record from
*/
-
public BlankRecord(RecordInputStream in)
{
super(in);
protected void fillFields(RecordInputStream in)
{
- //field_1_row = LittleEndian.getShort(data, 0 + offset);
field_1_row = in.readUShort();
field_2_col = in.readShort();
field_3_xf = in.readShort();
*
* @param id alleged id for this record
*/
-
protected void validateSid(short id)
{
if (id != sid)
* set the row this cell occurs on
* @param row the row this cell occurs within
*/
-
- //public void setRow(short row)
public void setRow(int row)
{
field_1_row = row;
*
* @return the row
*/
-
- //public short getRow()
public int getRow()
{
return field_1_row;
*
* @return the column
*/
-
public short getColumn()
{
return field_2_col;
* @param xf - the 0-based index of the extended format
* @see org.apache.poi.hssf.record.ExtendedFormatRecord
*/
-
public void setXFIndex(short xf)
{
field_3_xf = xf;
*
* @return extended format index
*/
-
public short getXFIndex()
{
return field_3_xf;
field_2_col = col;
}
- public boolean isInValueSection()
- {
- return true;
- }
-
- public boolean isValue()
- {
- return true;
- }
-
/**
* return the non static version of the id for this record.
*/
-
public short getSid()
{
return sid;
public String toString()
{
- StringBuffer buffer = new StringBuffer();
-
- buffer.append("[BLANK]\n");
- buffer.append("row = ").append(Integer.toHexString(getRow()))
- .append("\n");
- buffer.append("col = ").append(Integer.toHexString(getColumn()))
- .append("\n");
- buffer.append("xf = ")
- .append(Integer.toHexString(getXFIndex())).append("\n");
- buffer.append("[/BLANK]\n");
- return buffer.toString();
+ StringBuffer sb = new StringBuffer();
+
+ sb.append("[BLANK]\n");
+ sb.append(" row= ").append(HexDump.shortToHex(getRow())).append("\n");
+ sb.append(" col= ").append(HexDump.shortToHex(getColumn())).append("\n");
+ sb.append(" xf = ").append(HexDump.shortToHex(getXFIndex())).append("\n");
+ sb.append("[/BLANK]\n");
+ return sb.toString();
}
/**
*
* @return byte array containing instance data
*/
-
public int serialize(int offset, byte [] data)
{
- LittleEndian.putShort(data, 0 + offset, sid);
- LittleEndian.putShort(data, 2 + offset, ( short ) 6);
- //LittleEndian.putShort(data, 4 + offset, getRow());
- LittleEndian.putShort(data, 4 + offset, ( short ) getRow());
- LittleEndian.putShort(data, 6 + offset, getColumn());
- LittleEndian.putShort(data, 8 + offset, getXFIndex());
+ LittleEndian.putUShort(data, 0 + offset, sid);
+ LittleEndian.putUShort(data, 2 + offset, 6);
+ LittleEndian.putUShort(data, 4 + offset, getRow());
+ LittleEndian.putUShort(data, 6 + offset, getColumn());
+ LittleEndian.putUShort(data, 8 + offset, getXFIndex());
return getRecordSize();
}
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
-/*
- * BoolErrRecord.java
- *
- * Created on January 19, 2002, 9:30 AM
- */
package org.apache.poi.hssf.record;
+import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
/**
- * Creates new BoolErrRecord. <P>
+ * Creates new BoolErrRecord. (0x0205) <P>
* REFERENCE: PG ??? Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* @author Michael P. Harhen
* @author Jason Height (jheight at chariot dot net dot au)
* @version 2.0-pre
*/
public final class BoolErrRecord extends Record implements CellValueRecordInterface {
- public final static short sid = 0x205;
+ public final static short sid = 0x0205;
private int field_1_row;
private short field_2_column;
private short field_3_xf_index;
*
* @param in the RecordInputstream to read the record from
*/
-
public BoolErrRecord(RecordInputStream in)
{
super(in);
/**
* @param in the RecordInputstream to read the record from
*/
-
protected void fillFields(RecordInputStream in)
{
//field_1_row = LittleEndian.getShort(data, 0 + offset);
field_5_fError = in.readByte();
}
- //public void setRow(short row)
public void setRow(int row)
{
field_1_row = row;
* @see org.apache.poi.hssf.record.ExtendedFormatRecord
* @param xf index to the XF record
*/
-
public void setXFIndex(short xf)
{
field_3_xf_index = xf;
*
* @param value representing the boolean value
*/
-
public void setValue(boolean value)
{
field_4_bBoolErr = value ? ( byte ) 1
* this value can only be 0,7,15,23,29,36 or 42
* see bugzilla bug 16560 for an explanation
*/
-
public void setValue(byte value)
{
if ( (value==0)||(value==7)||(value==15)||(value==23)||(value==29)||(value==36)||(value==42)) {
}
}
- //public short getRow()
public int getRow()
{
return field_1_row;
* @see org.apache.poi.hssf.record.ExtendedFormatRecord
* @return index to the XF record
*/
-
public short getXFIndex()
{
return field_3_xf_index;
*
* @return boolean representing the boolean value
*/
-
public boolean getBooleanValue()
{
return (field_4_bBoolErr != 0);
*
* @return byte representing the error value
*/
-
public byte getErrorValue()
{
return field_4_bBoolErr;
*
* @return boolean true if the cell holds a boolean value
*/
-
public boolean isBoolean()
{
return (field_5_fError == ( byte ) 0);
public boolean isError()
{
- return (field_5_fError != ( byte ) 0);
+ return field_5_fError != 0;
}
public String toString()
{
- StringBuffer buffer = new StringBuffer();
+ StringBuffer sb = new StringBuffer();
- buffer.append("[BOOLERR]\n");
- buffer.append(" .row = ")
- .append(Integer.toHexString(getRow())).append("\n");
- buffer.append(" .col = ")
- .append(Integer.toHexString(getColumn())).append("\n");
- buffer.append(" .xfindex = ")
- .append(Integer.toHexString(getXFIndex())).append("\n");
- if (isBoolean())
- {
- buffer.append(" .booleanValue = ").append(getBooleanValue())
- .append("\n");
- }
- else
- {
- buffer.append(" .errorValue = ").append(getErrorValue())
- .append("\n");
+ sb.append("[BOOLERR]\n");
+ sb.append(" .row = ").append(HexDump.shortToHex(getRow())).append("\n");
+ sb.append(" .col = ").append(HexDump.shortToHex(getColumn())).append("\n");
+ sb.append(" .xfindex= ").append(HexDump.shortToHex(getXFIndex())).append("\n");
+ if (isBoolean()) {
+ sb.append(" .booleanValue = ").append(getBooleanValue()).append("\n");
+ } else {
+ sb.append(" .errorValue = ").append(getErrorValue()).append("\n");
}
- buffer.append("[/BOOLERR]\n");
- return buffer.toString();
+ sb.append("[/BOOLERR]\n");
+ return sb.toString();
}
/**
* called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a
* byte array.
- *
+ *
* @return byte array containing instance data
*/
-
public int serialize(int offset, byte [] data)
{
- LittleEndian.putShort(data, 0 + offset, sid);
- LittleEndian.putShort(data, 2 + offset, ( short ) 8);
- //LittleEndian.putShort(data, 4 + offset, getRow());
- LittleEndian.putShort(data, 4 + offset, ( short ) getRow());
- LittleEndian.putShort(data, 6 + offset, getColumn());
- LittleEndian.putShort(data, 8 + offset, getXFIndex());
+ LittleEndian.putUShort(data, 0 + offset, sid);
+ LittleEndian.putUShort(data, 2 + offset, 8);
+ LittleEndian.putUShort(data, 4 + offset, getRow());
+ LittleEndian.putUShort(data, 6 + offset, getColumn());
+ LittleEndian.putUShort(data, 8 + offset, getXFIndex());
data[ 10 + offset ] = field_4_bBoolErr;
data[ 11 + offset ] = field_5_fError;
return getRecordSize();
*
* @param id alleged id for this record
*/
-
protected void validateSid(short id)
{
if (id != BoolErrRecord.sid)
return sid;
}
- public boolean isInValueSection()
- {
- return true;
- }
-
- public boolean isValue()
- {
- return true;
- }
-
public Object clone() {
BoolErrRecord rec = new BoolErrRecord();
rec.field_1_row = field_1_row;
{
return field_17_formula1;
}
+ public void setParsedExpression1(Ptg[] ptgs) {
+ field_17_formula1 = safeClone(ptgs);
+ }
+ private static Ptg[] safeClone(Ptg[] ptgs) {
+ if (ptgs == null) {
+ return null;
+ }
+ return (Ptg[]) ptgs.clone();
+ }
/**
* get the stack of the 2nd expression as a list
{
return field_18_formula2;
}
+ public void setParsedExpression2(Ptg[] ptgs) {
+ field_18_formula2 = safeClone(ptgs);
+ }
/**
* called by constructor, should throw runtime exception in the event of a
return sid;
}
- public boolean isInValueSection()
- {
- return true;
- }
public Object clone() {
// TODO - make immutable.
// this should be safe because only the instantiating code mutates these objects
return 4 + getDataSize();
}
- public boolean isInValueSection() {
- return true;
- }
-
- public boolean isValue() {
- return true;
- }
-
public String toString() {
StringBuffer sb = new StringBuffer();
package org.apache.poi.hssf.record;
+import org.apache.poi.util.HexDump;
+
/**
- * Label Record - read only support for strings stored directly in the cell.. Don't
+ * Label Record (0x0204) - read only support for strings stored directly in the cell.. Don't
* use this (except to read), use LabelSST instead <P>
* REFERENCE: PG 325 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @see org.apache.poi.hssf.record.LabelSSTRecord
*/
public final class LabelRecord extends Record implements CellValueRecordInterface {
- public final static short sid = 0x204;
+ public final static short sid = 0x0204;
private int field_1_row;
private short field_2_column;
private String field_6_value;
/** Creates new LabelRecord */
-
public LabelRecord()
{
}
*
* @param in the RecordInputstream to read the record from
*/
-
public LabelRecord(RecordInputStream in)
{
super(in);
*
* @param id alleged id for this record
*/
-
protected void validateSid(short id)
{
if (id != sid)
/**
* @param in the RecordInputstream to read the record from
*/
-
protected void fillFields(RecordInputStream in)
{
field_1_row = in.readUShort();
/*
* READ ONLY ACCESS... THIS IS FOR COMPATIBILITY ONLY...USE LABELSST! public
- * void setRow(short row) { field_1_row = row; }
- *
- * public void setColumn(short col) { field_2_column = col; }
- *
- * public void setXFIndex(short index) { field_3_xf_index = index; }
*/
public int getRow()
{
* get the number of characters this string contains
* @return number of characters
*/
-
public short getStringLength()
{
return field_4_string_len;
* is this uncompressed unicode (16bit)? Or just 8-bit compressed?
* @return isUnicode - True for 16bit- false for 8bit
*/
-
public boolean isUnCompressedUnicode()
{
return (field_5_unicode_flag == 1);
* @return the text string
* @see #getStringLength()
*/
-
public String getValue()
{
return field_6_value;
/**
* THROWS A RUNTIME EXCEPTION.. USE LABELSSTRecords. YOU HAVE NO REASON to use LABELRecord!!
*/
-
public int serialize(int offset, byte [] data)
{
throw new RecordFormatException(
public String toString()
{
- StringBuffer buffer = new StringBuffer();
- buffer.append("[LABEL]\n");
- buffer.append(" .row = ")
- .append(Integer.toHexString(getRow())).append("\n");
- buffer.append(" .column = ")
- .append(Integer.toHexString(getColumn())).append("\n");
- buffer.append(" .xfindex = ")
- .append(Integer.toHexString(getXFIndex())).append("\n");
- buffer.append(" .string_len = ")
- .append(Integer.toHexString(field_4_string_len)).append("\n");
- buffer.append(" .unicode_flag = ")
- .append(Integer.toHexString(field_5_unicode_flag)).append("\n");
- buffer.append(" .value = ")
- .append(getValue()).append("\n");
- buffer.append("[/LABEL]\n");
- return buffer.toString();
- }
-
- public boolean isInValueSection()
- {
- return true;
- }
-
- public boolean isValue()
- {
- return true;
+ StringBuffer sb = new StringBuffer();
+ sb.append("[LABEL]\n");
+ sb.append(" .row = ").append(HexDump.shortToHex(getRow())).append("\n");
+ sb.append(" .column = ").append(HexDump.shortToHex(getColumn())).append("\n");
+ sb.append(" .xfindex = ").append(HexDump.shortToHex(getXFIndex())).append("\n");
+ sb.append(" .string_len= ").append(HexDump.shortToHex(field_4_string_len)).append("\n");
+ sb.append(" .unicode_flag= ").append(HexDump.byteToHex(field_5_unicode_flag)).append("\n");
+ sb.append(" .value = ").append(getValue()).append("\n");
+ sb.append("[/LABEL]\n");
+ return sb.toString();
}
/**
- * NO-OP!
- */
-
+ * NO-OP!
+ */
public void setColumn(short col)
{
}
/**
* NO-OP!
*/
-
- //public void setRow(short row)
public void setRow(int row)
{
}
/**
* no op!
*/
-
public void setXFIndex(short xf)
{
}
package org.apache.poi.hssf.record;
+import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
/**
*/
public final class LabelSSTRecord extends Record implements CellValueRecordInterface {
public final static short sid = 0xfd;
- private int field_1_row;
- private short field_2_column;
- private short field_3_xf_index;
- private int field_4_sst_index;
+ private int field_1_row;
+ private int field_2_column;
+ private int field_3_xf_index;
+ private int field_4_sst_index;
public LabelSSTRecord()
{
* Constructs an LabelSST record and sets its fields appropriately.
* @param in the RecordInputstream to read the record from
*/
-
public LabelSSTRecord(RecordInputStream in)
{
super(in);
protected void fillFields(RecordInputStream in)
{
- //field_1_row = LittleEndian.getShort(data, 0 + offset);
field_1_row = in.readUShort();
- field_2_column = in.readShort();
- field_3_xf_index = in.readShort();
+ field_2_column = in.readUShort();
+ field_3_xf_index = in.readUShort();
field_4_sst_index = in.readInt();
}
- //public void setRow(short row)
public void setRow(int row)
{
field_1_row = row;
field_4_sst_index = index;
}
- //public short getRow()
public int getRow()
{
return field_1_row;
public short getColumn()
{
- return field_2_column;
+ return (short)field_2_column;
}
/**
public short getXFIndex()
{
- return field_3_xf_index;
+ return (short)field_3_xf_index;
}
/**
public String toString()
{
- StringBuffer buffer = new StringBuffer();
+ StringBuffer sb = new StringBuffer();
- buffer.append("[LABELSST]\n");
- buffer.append(" .row = ")
- .append(Integer.toHexString(getRow())).append("\n");
- buffer.append(" .column = ")
- .append(Integer.toHexString(getColumn())).append("\n");
- buffer.append(" .xfindex = ")
- .append(Integer.toHexString(getXFIndex())).append("\n");
- buffer.append(" .sstindex = ")
- .append(Integer.toHexString(getSSTIndex())).append("\n");
- buffer.append("[/LABELSST]\n");
- return buffer.toString();
+ sb.append("[LABELSST]\n");
+ sb.append(" .row = ").append(HexDump.shortToHex(getRow())).append("\n");
+ sb.append(" .column = ").append(HexDump.shortToHex(getColumn())).append("\n");
+ sb.append(" .xfindex = ").append(HexDump.shortToHex(getXFIndex())).append("\n");
+ sb.append(" .sstindex= ").append(HexDump.intToHex(getSSTIndex())).append("\n");
+ sb.append("[/LABELSST]\n");
+ return sb.toString();
}
public int serialize(int offset, byte [] data)
{
- LittleEndian.putShort(data, 0 + offset, sid);
- LittleEndian.putShort(data, 2 + offset, ( short ) 10);
- //LittleEndian.putShort(data, 4 + offset, getRow());
- LittleEndian.putShort(data, 4 + offset, ( short )getRow());
- LittleEndian.putShort(data, 6 + offset, getColumn());
- LittleEndian.putShort(data, 8 + offset, getXFIndex());
+ LittleEndian.putUShort(data, 0 + offset, sid);
+ LittleEndian.putUShort(data, 2 + offset, 10);
+ LittleEndian.putUShort(data, 4 + offset, getRow());
+ LittleEndian.putUShort(data, 6 + offset, getColumn());
+ LittleEndian.putUShort(data, 8 + offset, getXFIndex());
LittleEndian.putInt(data, 10 + offset, getSSTIndex());
return getRecordSize();
}
return sid;
}
- public boolean isInValueSection()
- {
- return true;
- }
-
- public boolean isValue()
- {
- return true;
- }
-
public Object clone() {
LabelSSTRecord rec = new LabelSSTRecord();
rec.field_1_row = field_1_row;
package org.apache.poi.hssf.record;
+import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.hssf.record.Record;
/**
- * Contains a numeric cell value. <P>
+ * NUMBER (0x0203) Contains a numeric cell value. <P>
* REFERENCE: PG 334 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at chariot dot net dot au)
* @version 2.0-pre
*/
public final class NumberRecord extends Record implements CellValueRecordInterface {
- public static final short sid = 0x203;
- private int field_1_row;
- private short field_2_col;
- private short field_3_xf;
- private double field_4_value;
+ public static final short sid = 0x0203;
+ private int field_1_row;
+ private int field_2_col;
+ private int field_3_xf;
+ private double field_4_value;
/** Creates new NumberRecord */
public NumberRecord()
*
* @param in the RecordInputstream to read the record from
*/
-
public NumberRecord(RecordInputStream in)
{
super(in);
/**
* @param in the RecordInputstream to read the record from
*/
-
protected void fillFields(RecordInputStream in)
{
- //field_1_row = LittleEndian.getShort(data, 0 + offset);
field_1_row = in.readUShort();
- field_2_col = in.readShort();
- field_3_xf = in.readShort();
+ field_2_col = in.readUShort();
+ field_3_xf = in.readUShort();
field_4_value = in.readDouble();
}
- //public void setRow(short row)
public void setRow(int row)
{
field_1_row = row;
* @see org.apache.poi.hssf.record.ExtendedFormatRecord
* @param xf index to the XF record
*/
-
public void setXFIndex(short xf)
{
field_3_xf = xf;
*
* @param value double representing the value
*/
-
public void setValue(double value)
{
field_4_value = value;
}
- //public short getRow()
public int getRow()
{
return field_1_row;
public short getColumn()
{
- return field_2_col;
+ return (short)field_2_col;
}
/**
* @see org.apache.poi.hssf.record.ExtendedFormatRecord
* @return index to the XF record
*/
-
public short getXFIndex()
{
- return field_3_xf;
+ return (short)field_3_xf;
}
/**
*
* @return double representing the value
*/
-
public double getValue()
{
return field_4_value;
public String toString()
{
- StringBuffer buffer = new StringBuffer();
+ StringBuffer sb = new StringBuffer();
- buffer.append("[NUMBER]\n");
- buffer.append(" .row = ")
- .append(Integer.toHexString(getRow())).append("\n");
- buffer.append(" .col = ")
- .append(Integer.toHexString(getColumn())).append("\n");
- buffer.append(" .xfindex = ")
- .append(Integer.toHexString(getXFIndex())).append("\n");
- buffer.append(" .value = ").append(getValue())
- .append("\n");
- buffer.append("[/NUMBER]\n");
- return buffer.toString();
+ sb.append("[NUMBER]\n");
+ sb.append(" .row = ").append(HexDump.shortToHex(getRow())).append("\n");
+ sb.append(" .col = ").append(HexDump.shortToHex(getColumn())).append("\n");
+ sb.append(" .xfindex= ").append(HexDump.shortToHex(getXFIndex())).append("\n");
+ sb.append(" .value = ").append(getValue()).append("\n");
+ sb.append("[/NUMBER]\n");
+ return sb.toString();
}
/**
* called by the class that is responsible for writing this sucker.
* Subclasses should implement this so that their data is passed back in a
* byte array.
- *
+ *
* @return byte array containing instance data
*/
-
public int serialize(int offset, byte [] data)
{
- LittleEndian.putShort(data, 0 + offset, sid);
- LittleEndian.putShort(data, 2 + offset, ( short ) 14);
- //LittleEndian.putShort(data, 4 + offset, getRow());
- LittleEndian.putShort(data, 4 + offset, ( short ) getRow());
- LittleEndian.putShort(data, 6 + offset, getColumn());
- LittleEndian.putShort(data, 8 + offset, getXFIndex());
+ LittleEndian.putUShort(data, 0 + offset, sid);
+ LittleEndian.putUShort(data, 2 + offset, 14);
+ LittleEndian.putUShort(data, 4 + offset, getRow());
+ LittleEndian.putUShort(data, 6 + offset, getColumn());
+ LittleEndian.putUShort(data, 8 + offset, getXFIndex());
LittleEndian.putDouble(data, 10 + offset, getValue());
return getRecordSize();
}
return sid;
}
- public boolean isInValueSection()
- {
- return true;
- }
-
- public boolean isValue()
- {
- return true;
- }
-
public Object clone() {
NumberRecord rec = new NumberRecord();
rec.field_1_row = field_1_row;
package org.apache.poi.hssf.record;
import org.apache.poi.hssf.util.RKUtil;
+import org.apache.poi.util.HexDump;
/**
- * Title: RK Record
+ * Title: RK Record (0x027E)
* Description: An internal 32 bit number with the two most significant bits
* storing the type. This is part of a bizarre scheme to save disk
* space and memory (gee look at all the other whole records that
* @see org.apache.poi.hssf.record.NumberRecord
*/
public final class RKRecord extends Record implements CellValueRecordInterface {
- public final static short sid = 0x27e;
+ public final static short sid = 0x027E;
public final static short RK_IEEE_NUMBER = 0;
public final static short RK_IEEE_NUMBER_TIMES_100 = 1;
public final static short RK_INTEGER = 2;
public final static short RK_INTEGER_TIMES_100 = 3;
- private int field_1_row;
- private short field_2_col;
- private short field_3_xf_index;
- private int field_4_rk_number;
+ private int field_1_row;
+ private int field_2_col;
+ private int field_3_xf_index;
+ private int field_4_rk_number;
public RKRecord()
{
* Constructs a RK record and sets its fields appropriately.
* @param in the RecordInputstream to read the record from
*/
-
public RKRecord(RecordInputStream in)
{
super(in);
protected void fillFields(RecordInputStream in)
{
- //field_1_row = LittleEndian.getShort(data, 0 + offset);
field_1_row = in.readUShort();
- field_2_col = in.readShort();
- field_3_xf_index = in.readShort();
+ field_2_col = in.readUShort();
+ field_3_xf_index = in.readUShort();
field_4_rk_number = in.readInt();
}
- //public short getRow()
public int getRow()
{
return field_1_row;
public short getColumn()
{
- return field_2_col;
+ return (short) field_2_col;
}
public short getXFIndex()
{
- return field_3_xf_index;
+ return (short) field_3_xf_index;
}
public int getRKField()
* <LI>RK_INTEGER_TIMES_100</LI>
* </OL>
*/
-
public short getRKType()
{
return ( short ) (field_4_rk_number & 3);
* @return the value as a proper double (hey, it <B>could</B>
* happen)
*/
-
public double getRKNumber()
{
return RKUtil.decodeNumber(field_4_rk_number);
public String toString()
{
- StringBuffer buffer = new StringBuffer();
-
- buffer.append("[RK]\n");
- buffer.append(" .row = ")
- .append(Integer.toHexString(getRow())).append("\n");
- buffer.append(" .col = ")
- .append(Integer.toHexString(getColumn())).append("\n");
- buffer.append(" .xfindex = ")
- .append(Integer.toHexString(getXFIndex())).append("\n");
- buffer.append(" .rknumber = ")
- .append(Integer.toHexString(getRKField())).append("\n");
- buffer.append(" .rktype = ")
- .append(Integer.toHexString(getRKType())).append("\n");
- buffer.append(" .rknumber = ").append(getRKNumber())
- .append("\n");
- buffer.append("[/RK]\n");
- return buffer.toString();
- }
-
-//temporarily just constructs a new number record and returns its value
+ StringBuffer sb = new StringBuffer();
+
+ sb.append("[RK]\n");
+ sb.append(" .row = ").append(HexDump.shortToHex(getRow())).append("\n");
+ sb.append(" .col = ").append(HexDump.shortToHex(getColumn())).append("\n");
+ sb.append(" .xfindex = ").append(HexDump.shortToHex(getXFIndex())).append("\n");
+ sb.append(" .rknumber = ").append(HexDump.intToHex(getRKField())).append("\n");
+ sb.append(" .rktype = ").append(HexDump.byteToHex(getRKType())).append("\n");
+ sb.append(" .rknumber= ").append(getRKNumber()).append("\n");
+ sb.append("[/RK]\n");
+ return sb.toString();
+ }
+
+// temporarily just constructs a new number record and returns its value
public int serialize(int offset, byte [] data)
{
NumberRecord rec = new NumberRecord();
return sid;
}
- public boolean isInValueSection()
- {
- return true;
- }
-
- public boolean isValue()
- {
- return true;
- }
-
public void setColumn(short col)
{
}
- //public void setRow(short row)
public void setRow(int row)
{
}
return serialize().length;
}
- /**
- * tells whether this type of record contains a value
- */
-
- public boolean isValue()
- {
- return false;
- }
-
- /**
- * DBCELL, ROW, VALUES all say yes
- */
-
- public boolean isInValueSection()
- {
- return false;
- }
-
/**
* get a string representation of the record (for biffview/debugging)
*/
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
/**
* @author Jason Height (jheight at chariot dot net dot au)
* @version 2.0-pre
*/
-public final class RowRecord extends Record implements Comparable {
+public final class RowRecord extends Record {
public final static short sid = 0x0208;
public static final int ENCODED_SIZE = 20;
* Constructs a Row record and sets its fields appropriately.
* @param in the RecordInputstream to read the record from
*/
-
public RowRecord(RecordInputStream in)
{
super(in);
* set the logical row number for this row (0 based index)
* @param row - the row number
*/
-
- //public void setRowNumber(short row)
public void setRowNumber(int row)
{
field_1_row_number = row;
* set the logical col number for the first cell this row (0 based index)
* @param col - the col number
*/
-
public void setFirstCol(short col)
{
field_2_first_col = col;
* set the logical col number for the last cell this row (0 based index)
* @param col - the col number
*/
-
public void setLastCol(short col)
{
field_3_last_col = col;
* set the height of the row
* @param height of the row
*/
-
public void setHeight(short height)
{
field_4_height = height;
* set whether to optimize or not (set to 0)
* @param optimize (set to 0)
*/
-
public void setOptimize(short optimize)
{
field_5_optimize = optimize;
}
- /**
- * sets the option bitmask. (use the individual bit setters that refer to this
- * method)
- * @param options - the bitmask
- */
-
- public void setOptionFlags(short options)
- {
- field_7_option_flags = options | OPTION_BITS_ALWAYS_SET;
- }
-
// option bitfields
/**
* set the outline level of this row
* @param ol - the outline level
- * @see #setOptionFlags(short)
*/
-
public void setOutlineLevel(short ol)
{
field_7_option_flags = outlineLevel.setValue(field_7_option_flags, ol);
/**
* set whether or not to collapse this row
* @param c - collapse or not
- * @see #setOptionFlags(short)
*/
-
public void setColapsed(boolean c)
{
field_7_option_flags = colapsed.setBoolean(field_7_option_flags, c);
/**
* set whether or not to display this row with 0 height
* @param z height is zero or not.
- * @see #setOptionFlags(short)
*/
-
public void setZeroHeight(boolean z)
{
field_7_option_flags = zeroHeight.setBoolean(field_7_option_flags, z);
/**
* set whether the font and row height are not compatible
* @param f true if they aren't compatible (damn not logic)
- * @see #setOptionFlags(short)
*/
-
public void setBadFontHeight(boolean f)
{
field_7_option_flags = badFontHeight.setBoolean(field_7_option_flags, f);
/**
* set whether the row has been formatted (even if its got all blank cells)
* @param f formatted or not
- * @see #setOptionFlags(short)
*/
-
public void setFormatted(boolean f)
{
field_7_option_flags = formatted.setBoolean(field_7_option_flags, f);
* @see org.apache.poi.hssf.record.ExtendedFormatRecord
* @param index to the XF record
*/
-
public void setXFIndex(short index)
{
field_8_xf_index = index;
* get the logical row number for this row (0 based index)
* @return row - the row number
*/
-
- //public short getRowNumber()
public int getRowNumber()
{
return field_1_row_number;
* get the logical col number for the first cell this row (0 based index)
* @return col - the col number
*/
-
public short getFirstCol()
{
return field_2_first_col;
* get the logical col number for the last cell this row plus one (0 based index)
* @return col - the last col number + 1
*/
-
public short getLastCol()
{
return field_3_last_col;
* get the height of the row
* @return height of the row
*/
-
public short getHeight()
{
return field_4_height;
* get whether to optimize or not (set to 0)
* @return optimize (set to 0)
*/
-
public short getOptimize()
{
return field_5_optimize;
* method)
* @return options - the bitmask
*/
-
public short getOptionFlags()
{
return (short)field_7_option_flags;
* @return ol - the outline level
* @see #getOptionFlags()
*/
-
public short getOutlineLevel()
{
return (short)outlineLevel.getValue(field_7_option_flags);
* @return c - colapse or not
* @see #getOptionFlags()
*/
-
public boolean getColapsed()
{
return (colapsed.isSet(field_7_option_flags));
* @return - z height is zero or not.
* @see #getOptionFlags()
*/
-
public boolean getZeroHeight()
{
return zeroHeight.isSet(field_7_option_flags);
return field_8_xf_index;
}
- public boolean isInValueSection()
- {
- return true;
- }
-
public String toString()
{
- StringBuffer buffer = new StringBuffer();
-
- buffer.append("[ROW]\n");
- buffer.append(" .rownumber = ")
- .append(Integer.toHexString(getRowNumber())).append("\n");
- buffer.append(" .firstcol = ")
- .append(Integer.toHexString(getFirstCol())).append("\n");
- buffer.append(" .lastcol = ")
- .append(Integer.toHexString(getLastCol())).append("\n");
- buffer.append(" .height = ")
- .append(Integer.toHexString(getHeight())).append("\n");
- buffer.append(" .optimize = ")
- .append(Integer.toHexString(getOptimize())).append("\n");
- buffer.append(" .reserved = ")
- .append(Integer.toHexString(field_6_reserved)).append("\n");
- buffer.append(" .optionflags = ")
- .append(Integer.toHexString(getOptionFlags())).append("\n");
- buffer.append(" .outlinelvl = ")
- .append(Integer.toHexString(getOutlineLevel())).append("\n");
- buffer.append(" .colapsed = ").append(getColapsed())
- .append("\n");
- buffer.append(" .zeroheight = ").append(getZeroHeight())
- .append("\n");
- buffer.append(" .badfontheig= ").append(getBadFontHeight())
- .append("\n");
- buffer.append(" .formatted = ").append(getFormatted())
- .append("\n");
- buffer.append(" .xfindex = ")
- .append(Integer.toHexString(getXFIndex())).append("\n");
- buffer.append("[/ROW]\n");
- return buffer.toString();
+ StringBuffer sb = new StringBuffer();
+
+ sb.append("[ROW]\n");
+ sb.append(" .rownumber = ").append(Integer.toHexString(getRowNumber()))
+ .append("\n");
+ sb.append(" .firstcol = ").append(HexDump.shortToHex(getFirstCol())).append("\n");
+ sb.append(" .lastcol = ").append(HexDump.shortToHex(getLastCol())).append("\n");
+ sb.append(" .height = ").append(HexDump.shortToHex(getHeight())).append("\n");
+ sb.append(" .optimize = ").append(HexDump.shortToHex(getOptimize())).append("\n");
+ sb.append(" .reserved = ").append(HexDump.shortToHex(field_6_reserved)).append("\n");
+ sb.append(" .optionflags = ").append(HexDump.shortToHex(getOptionFlags())).append("\n");
+ sb.append(" .outlinelvl = ").append(Integer.toHexString(getOutlineLevel())).append("\n");
+ sb.append(" .colapsed = ").append(getColapsed()).append("\n");
+ sb.append(" .zeroheight = ").append(getZeroHeight()).append("\n");
+ sb.append(" .badfontheig= ").append(getBadFontHeight()).append("\n");
+ sb.append(" .formatted = ").append(getFormatted()).append("\n");
+ sb.append(" .xfindex = ").append(Integer.toHexString(getXFIndex())).append("\n");
+ sb.append("[/ROW]\n");
+ return sb.toString();
}
public int serialize(int offset, byte [] data)
return sid;
}
- public int compareTo(Object obj)
- {
- RowRecord loc = ( RowRecord ) obj;
-
- if (this.getRowNumber() == loc.getRowNumber())
- {
- return 0;
- }
- if (this.getRowNumber() < loc.getRowNumber())
- {
- return -1;
- }
- if (this.getRowNumber() > loc.getRowNumber())
- {
- return 1;
- }
- return -1;
- }
-
- public boolean equals(Object obj)
- {
- if (!(obj instanceof RowRecord))
- {
- return false;
- }
- RowRecord loc = ( RowRecord ) obj;
-
- if (this.getRowNumber() == loc.getRowNumber())
- {
- return true;
- }
- return false;
- }
-
public Object clone() {
RowRecord rec = new RowRecord(field_1_row_number);
rec.field_2_first_col = field_2_first_col;
CellRangeAddress8Bit r = getRange();
return r.getFirstRow() == rowIx && r.getFirstColumn() == colIx;
}
-
- /**
- * Mirroring formula records so it is registered in the
- * ValueRecordsAggregate
- */
- public final boolean isInValueSection() {
- return true;
- }
-
- /**
- * Register it in the ValueRecordsAggregate so it can go into the
- * FormulaRecordAggregate
- */
- public final boolean isValue() {
- return true;
- }
}
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record;
import org.apache.poi.util.StringUtil;
/**
- * Supports the STRING record structure.
+ * Supports the STRING record structure. (0x0207)
*
* @author Glen Stampoultzis (glens at apache.org)
*/
-public class StringRecord
- extends Record
-{
- public final static short sid = 0x207;
+public class StringRecord extends Record {
+ public final static short sid = 0x0207;
private int field_1_string_length;
private byte field_2_unicode_flag;
private String field_3_string;
field_1_string_length = in.readShort();
field_2_unicode_flag = in.readByte();
byte[] data = in.readRemainder();
- //Why isnt this using the in.readString methods???
+ //Why isn't this using the in.readString methods???
if (isUnCompressedUnicode())
{
field_3_string = StringUtil.getFromUnicodeLE(data, 0, field_1_string_length );
}
}
- public boolean isInValueSection()
- {
- return true;
- }
-
private int getStringByteLength()
{
return isUnCompressedUnicode() ? field_1_string_length * 2 : field_1_string_length;
*/
public int serialize( int offset, byte[] data )
{
- LittleEndian.putShort(data, 0 + offset, sid);
- LittleEndian.putShort(data, 2 + offset, ( short ) (3 + getStringByteLength()));
+ LittleEndian.putUShort(data, 0 + offset, sid);
+ LittleEndian.putUShort(data, 2 + offset, 3 + getStringByteLength());
LittleEndian.putUShort(data, 4 + offset, field_1_string_length);
data[6 + offset] = field_2_unicode_flag;
if (isUnCompressedUnicode())
setCompressedFlag(StringUtil.hasMultibyte(string) ? (byte)1 : (byte)0);
}
-
-
public String toString()
{
StringBuffer buffer = new StringBuffer();
rec.field_2_unicode_flag= this.field_2_unicode_flag;
rec.field_3_string = this.field_3_string;
return rec;
-
}
-
}
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.Record;
-import org.apache.poi.ss.util.Region;
+import org.apache.poi.hssf.record.formula.AreaErrPtg;
+import org.apache.poi.hssf.record.formula.AreaPtg;
+import org.apache.poi.hssf.record.formula.FormulaShifter;
+import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.ss.util.CellRangeAddress;
/**
rv.visitRecord(rule);
}
}
+
+ /**
+ * @return <code>false</code> if this whole {@link CFHeaderRecord} / {@link CFRuleRecord}s should be deleted
+ */
+ public boolean updateFormulasAfterCellShift(FormulaShifter shifter, int currentExternSheetIx) {
+ CellRangeAddress[] cellRanges = header.getCellRanges();
+ boolean changed = false;
+ List temp = new ArrayList();
+ for (int i = 0; i < cellRanges.length; i++) {
+ CellRangeAddress craOld = cellRanges[i];
+ CellRangeAddress craNew = shiftRange(shifter, craOld, currentExternSheetIx);
+ if (craNew == null) {
+ changed = true;
+ continue;
+ }
+ temp.add(craNew);
+ if (craNew != craOld) {
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ int nRanges = temp.size();
+ if (nRanges == 0) {
+ return false;
+ }
+ CellRangeAddress[] newRanges = new CellRangeAddress[nRanges];
+ temp.toArray(newRanges);
+ header.setCellRanges(newRanges);
+ }
+
+ for(int i=0; i<rules.size(); i++) {
+ CFRuleRecord rule = (CFRuleRecord)rules.get(i);
+ Ptg[] ptgs;
+ ptgs = rule.getParsedExpression1();
+ if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
+ rule.setParsedExpression1(ptgs);
+ }
+ ptgs = rule.getParsedExpression2();
+ if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
+ rule.setParsedExpression2(ptgs);
+ }
+ }
+ return true;
+ }
+
+ private static CellRangeAddress shiftRange(FormulaShifter shifter, CellRangeAddress cra, int currentExternSheetIx) {
+ // FormulaShifter works well in terms of Ptgs - so convert CellRangeAddress to AreaPtg (and back) here
+ AreaPtg aptg = new AreaPtg(cra.getFirstRow(), cra.getLastRow(), cra.getFirstColumn(), cra.getLastColumn(), false, false, false, false);
+ Ptg[] ptgs = { aptg, };
+
+ if (!shifter.adjustFormula(ptgs, currentExternSheetIx)) {
+ return cra;
+ }
+ Ptg ptg0 = ptgs[0];
+ if (ptg0 instanceof AreaPtg) {
+ AreaPtg bptg = (AreaPtg) ptg0;
+ return new CellRangeAddress(bptg.getFirstRow(), bptg.getLastRow(), bptg.getFirstColumn(), bptg.getLastColumn());
+ }
+ if (ptg0 instanceof AreaErrPtg) {
+ return null;
+ }
+ throw new IllegalStateException("Unexpected shifted ptg class (" + ptg0.getClass().getName() + ")");
+ }
}
import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.record.CFHeaderRecord;
+import org.apache.poi.hssf.record.formula.FormulaShifter;
/**
* Holds all the conditional formatting for a workbook sheet.<p/>
+ " is outside the allowable range (0.." + (_cfHeaders.size() - 1) + ")");
}
}
+
+ public void updateFormulasAfterCellShift(FormulaShifter shifter, int externSheetIndex) {
+ for (int i = 0; i < _cfHeaders.size(); i++) {
+ CFRecordsAggregate subAgg = (CFRecordsAggregate) _cfHeaders.get(i);
+ boolean shouldKeep = subAgg.updateFormulasAfterCellShift(shifter, externSheetIndex);
+ if (!shouldKeep) {
+ _cfHeaders.remove(i);
+ i--;
+ }
+ }
+ }
}
}
boolean hasStringRec = stringRec != null;
boolean hasCachedStringFlag = formulaRec.hasCachedResultString();
- if (hasStringRec != hasCachedStringFlag) {
- throw new RecordFormatException("String record was "
- + (hasStringRec ? "": "not ") + " supplied but formula record flag is "
- + (hasCachedStringFlag ? "" : "not ") + " set");
- }
-
+ if (hasStringRec != hasCachedStringFlag) {
+ throw new RecordFormatException("String record was "
+ + (hasStringRec ? "": "not ") + " supplied but formula record flag is "
+ + (hasCachedStringFlag ? "" : "not ") + " set");
+ }
+
if (formulaRec.isSharedFormula()) {
svm.convertSharedFormulaRecord(formulaRec);
}
// might need to keep track of where exactly these belong
continue;
}
- if (!rec.isValue()) {
+ if (!(rec instanceof CellValueRecordInterface)) {
throw new RuntimeException("Unexpected record type (" + rec.getClass().getName() + ")");
}
_valuesAgg.construct((CellValueRecordInterface)rec, rs, svm);
int sheetIndex = workbook.getSheetIndex(this);
short externSheetIndex = book.checkExternSheet(sheetIndex);
FormulaShifter shifter = FormulaShifter.createForRowShift(externSheetIndex, startRow, endRow, n);
- sheet.getRowsAggregate().updateFormulasAfterRowShift(shifter, externSheetIndex);
+ sheet.updateFormulasAfterCellShift(shifter, externSheetIndex);
int nSheets = workbook.getNumberOfSheets();
for(int i=0; i<nSheets; i++) {
continue;
}
short otherExtSheetIx = book.checkExternSheet(i);
- otherSheet.getRowsAggregate().updateFormulasAfterRowShift(shifter, otherExtSheetIx);
+ otherSheet.updateFormulasAfterCellShift(shifter, otherExtSheetIx);
}
// TODO - adjust formulas in named ranges
}
import org.apache.poi.hssf.model.Sheet;\r
import org.apache.poi.hssf.record.CFRuleRecord;\r
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;\r
+import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;\r
import org.apache.poi.ss.util.Region;\r
import org.apache.poi.ss.util.CellRangeAddress;\r
\r
public final class HSSFSheetConditionalFormatting {\r
\r
private final HSSFWorkbook _workbook;\r
- private final Sheet _sheet;\r
+ private final ConditionalFormattingTable _conditionalFormattingTable;\r
\r
/* package */ HSSFSheetConditionalFormatting(HSSFWorkbook workbook, Sheet sheet) {\r
_workbook = workbook;\r
- _sheet = sheet;\r
+ _conditionalFormattingTable = sheet.getConditionalFormattingTable();\r
}\r
\r
/**\r
public int addConditionalFormatting( HSSFConditionalFormatting cf ) {\r
CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate();\r
\r
- return _sheet.addConditionalFormatting(cfraClone);\r
+ return _conditionalFormattingTable.add(cfraClone);\r
}\r
/**\r
* @deprecated use <tt>CellRangeAddress</tt> instead of <tt>Region</tt>\r
rules[i] = cfRules[i].getCfRuleRecord();\r
}\r
CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules);\r
- return _sheet.addConditionalFormatting(cfra);\r
+ return _conditionalFormattingTable.add(cfra);\r
}\r
\r
public int addConditionalFormatting(CellRangeAddress[] regions,\r
* @return Conditional Formatting object\r
*/\r
public HSSFConditionalFormatting getConditionalFormattingAt(int index) {\r
- CFRecordsAggregate cf = _sheet.getCFRecordsAggregateAt(index);\r
+ CFRecordsAggregate cf = _conditionalFormattingTable.get(index);\r
if (cf == null) {\r
return null;\r
}\r
* @return number of Conditional Formatting objects of the sheet\r
*/\r
public int getNumConditionalFormattings() {\r
- return _sheet.getNumConditionalFormattings();\r
+ return _conditionalFormattingTable.size();\r
}\r
\r
/**\r
* @param index of a Conditional Formatting object to remove\r
*/\r
public void removeConditionalFormatting(int index) {\r
- _sheet.removeConditionalFormatting(index);\r
+ _conditionalFormattingTable.remove(index);\r
}\r
}\r
import org.apache.poi.ddf.EscherBitmapBlip;
import org.apache.poi.ddf.EscherBlipRecord;
import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.AbstractEscherHolderRecord;
// convert all LabelRecord records to LabelSSTRecord
convertLabelRecords(records, recOffset);
- while (recOffset < records.size()) {
- Sheet sheet = Sheet.createSheet(records, sheetNum++, recOffset );
-
- recOffset = sheet.getEofLoc()+1; // TODO - use better technique to keep track of the used records
+ RecordStream rs = new RecordStream(records, recOffset);
+ while (rs.hasNext()) {
+ Sheet sheet = Sheet.createSheet(rs);
_sheets.add(new HSSFSheet(this, sheet));
}
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class TestSheet extends TestCase {
+ private static Sheet createSheet(List inRecs) {
+ return Sheet.createSheet(new RecordStream(inRecs, 0));
+ }
+
+
public void testCreateSheet() {
// Check we're adding row and cell aggregates
List records = new ArrayList();
records.add( new DimensionsRecord() );
records.add(createWindow2Record());
records.add(EOFRecord.instance);
- Sheet sheet = Sheet.createSheet( records, 0, 0 );
+ Sheet sheet = createSheet(records);
int pos = 0;
assertTrue( sheet.records.get(pos++) instanceof BOFRecord );
records.add(EOFRecord.instance);
records.add(merged);
- Sheet sheet = Sheet.createSheet(records, 0);
+ Sheet sheet = createSheet(records);
sheet.records.remove(0);
//stub object to throw off list INDEX operations
records.add(createWindow2Record());
records.add(EOFRecord.instance);
- Sheet sheet = Sheet.createSheet(records, 0);
+ Sheet sheet = createSheet(records);
assertNotNull("Row [2] was skipped", sheet.getRow(2));
}
records.add(new DimensionsRecord());
records.add(createWindow2Record());
records.add(EOFRecord.instance);
- Sheet sheet = Sheet.createSheet(records, 0, 0);
+ Sheet sheet = createSheet(records);
// The original bug was due to different logic for collecting records for sizing and
// serialization. The code has since been refactored into a single method for visiting
assertTrue(enr.isAutomaticLink());\r
assertFalse(enr.isBuiltInName());\r
assertFalse(enr.isIconifiedPictureLink());\r
- assertFalse(enr.isInValueSection());\r
assertFalse(enr.isOLELink());\r
assertFalse(enr.isPicureLink());\r
assertTrue(enr.isStdDocumentNameIdentifier());\r
- assertFalse(enr.isValue());\r
\r
TestcaseRecordInputStream.confirmRecordEncoding(0x0023, dataAutoDocName, enr.serialize());\r
}\r
assertFalse(enr.isAutomaticLink());\r
assertFalse(enr.isBuiltInName());\r
assertFalse(enr.isIconifiedPictureLink());\r
- assertFalse(enr.isInValueSection());\r
assertFalse(enr.isOLELink());\r
assertFalse(enr.isPicureLink());\r
assertFalse(enr.isStdDocumentNameIdentifier());\r
- assertFalse(enr.isValue());\r
\r
TestcaseRecordInputStream.confirmRecordEncoding(0x0023, dataPlainName, enr.serialize());\r
}\r
}
private void constructValueRecord(List records) {
- RowBlocksReader rbr = new RowBlocksReader(records, 0);
+ RowBlocksReader rbr = new RowBlocksReader(new RecordStream(records, 0));
SharedValueManager sfrh = rbr.getSharedFormulaManager();
RecordStream rs = rbr.getPlainRecordStream();
while(rs.hasNext()) {
*
* @author Dmitriy Kumshayev
*/
-public final class TestHSSFConditionalFormatting extends TestCase
-{
- public void testCreateCF()
- {
+public final class TestHSSFConditionalFormatting extends TestCase {
+ public void testCreateCF() {
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
String formula = "7";
}
assertEquals(2, wb.getNumberOfSheets());
}
+
+ public void testShiftRows() {
+
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sheet = wb.createSheet();
+
+ HSSFSheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
+
+ HSSFConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(
+ ComparisonOperator.BETWEEN, "sum(A10:A15)", "1+sum(B16:B30)");
+ HSSFFontFormatting fontFmt = rule1.createFontFormatting();
+ fontFmt.setFontStyle(true, false);
+
+ HSSFPatternFormatting patternFmt = rule1.createPatternFormatting();
+ patternFmt.setFillBackgroundColor(HSSFColor.YELLOW.index);
+ HSSFConditionalFormattingRule [] cfRules = { rule1, };
+
+ CellRangeAddress [] regions = {
+ new CellRangeAddress(2, 4, 0, 0), // A3:A5
+ };
+ sheetCF.addConditionalFormatting(regions, cfRules);
+
+ // This row-shift should destroy the CF region
+ sheet.shiftRows(10, 20, -9);
+ assertEquals(0, sheetCF.getNumConditionalFormattings());
+
+ // re-add the CF
+ sheetCF.addConditionalFormatting(regions, cfRules);
+
+ // This row shift should only affect the formulas
+ sheet.shiftRows(14, 17, 8);
+ HSSFConditionalFormatting cf = sheetCF.getConditionalFormattingAt(0);
+ assertEquals("SUM(A10:A23)", cf.getRule(0).getFormula1());
+ assertEquals("1+SUM(B24:B30)", cf.getRule(0).getFormula2());
+
+ sheet.shiftRows(0, 8, 21);
+ cf = sheetCF.getConditionalFormattingAt(0);
+ assertEquals("SUM(A10:A21)", cf.getRule(0).getFormula1());
+ assertEquals("1+SUM(#REF!)", cf.getRule(0).getFormula2());
+ }
}