sheet.java
来自「EXCEL read and write」· Java 代码 · 共 1,758 行 · 第 1/5 页
JAVA
1,758 行
/* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.==================================================================== */package org.apache.poi.hssf.model;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import org.apache.poi.hssf.record.BOFRecord;import org.apache.poi.hssf.record.CFHeaderRecord;import org.apache.poi.hssf.record.CalcCountRecord;import org.apache.poi.hssf.record.CalcModeRecord;import org.apache.poi.hssf.record.CellValueRecordInterface;import org.apache.poi.hssf.record.ColumnInfoRecord;import org.apache.poi.hssf.record.DVALRecord;import org.apache.poi.hssf.record.DefaultColWidthRecord;import org.apache.poi.hssf.record.DefaultRowHeightRecord;import org.apache.poi.hssf.record.DeltaRecord;import org.apache.poi.hssf.record.DimensionsRecord;import org.apache.poi.hssf.record.DrawingRecord;import org.apache.poi.hssf.record.EOFRecord;import org.apache.poi.hssf.record.EscherAggregate;import org.apache.poi.hssf.record.GridsetRecord;import org.apache.poi.hssf.record.GutsRecord;import org.apache.poi.hssf.record.IndexRecord;import org.apache.poi.hssf.record.IterationRecord;import org.apache.poi.hssf.record.MergeCellsRecord;import org.apache.poi.hssf.record.ObjRecord;import org.apache.poi.hssf.record.ObjectProtectRecord;import org.apache.poi.hssf.record.PaneRecord;import org.apache.poi.hssf.record.PasswordRecord;import org.apache.poi.hssf.record.PrintGridlinesRecord;import org.apache.poi.hssf.record.PrintHeadersRecord;import org.apache.poi.hssf.record.ProtectRecord;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.ScenarioProtectRecord;import org.apache.poi.hssf.record.SelectionRecord;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.ColumnInfoRecordsAggregate;import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;import org.apache.poi.hssf.record.aggregates.DataValidityTable;import org.apache.poi.hssf.record.aggregates.MergedCellsTable;import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;import org.apache.poi.hssf.record.aggregates.RecordAggregate;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;import org.apache.poi.util.POILogger;/** * Low level model implementation of a Sheet (one workbook contains many sheets) * This file contains the low level binary records starting at the sheets BOF and * ending with the sheets EOF. Use HSSFSheet for a high level representation. * <P> * The structures of the highlevel API use references to this to perform most of their * operations. Its probably unwise to use these low level structures directly unless you * really know what you're doing. I recommend you read the Microsoft Excel 97 Developer's * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf * before even attempting to use this. * <P> * @author Andrew C. Oliver (acoliver at apache dot org) * @author Glen Stampoultzis (glens at apache.org) * @author Shawn Laubach (slaubach at apache dot org) Gridlines, Headers, Footers, PrintSetup, and Setting Default Column Styles * @author Jason Height (jheight at chariot dot net dot au) Clone support. DBCell & Index Record writing support * @author Brian Sanders (kestrel at burdell dot org) Active Cell support * @author Jean-Pierre Paris (jean-pierre.paris at m4x dot org) (Just a little) * * @see org.apache.poi.hssf.model.Workbook * @see org.apache.poi.hssf.usermodel.HSSFSheet * @version 1.0-pre */public final class Sheet implements Model { public static final short LeftMargin = 0; public static final short RightMargin = 1; public static final short TopMargin = 2; public static final short BottomMargin = 3; private static POILogger log = POILogFactory.getLogger(Sheet.class); protected ArrayList records = null; protected PrintGridlinesRecord printGridlines = null; protected GridsetRecord gridset = null; private GutsRecord _gutsRecord; protected DefaultColWidthRecord defaultcolwidth = null; protected DefaultRowHeightRecord defaultrowheight = null; private PageSettingsBlock _psBlock; // 'Worksheet Protection Block' protected ProtectRecord protect = null; 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 */ private final MergedCellsTable _mergedCellsTable; /** always present in this POI object, not always written to Excel file */ /*package*/ColumnInfoRecordsAggregate _columnInfos; /** the DimensionsRecord is always present */ private DimensionsRecord _dimensions; /** always present */ protected final RowRecordsAggregate _rowsAggregate; private DataValidityTable _dataValidityTable= null; private ConditionalFormattingTable condFormatting; 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; /** * 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 * a record offset (should be the location of the sheets BOF record). A Sheet * object is constructed and passed back with all of its initialization set * to the passed in records and references to those records held. This function * is normally called via Workbook. * * @param inRecs 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) * @param offset of the sheet's BOF record * * @return Sheet object with all values set to those read from the file * * @see org.apache.poi.hssf.model.Workbook * @see org.apache.poi.hssf.record.Record */ 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; while (rs.hasNext()) { int recSid = rs.peekNextSid(); if ( recSid == CFHeaderRecord.sid ) { condFormatting = new ConditionalFormattingTable(rs); records.add(condFormatting); continue; } if (recSid == ColumnInfoRecord.sid) { _columnInfos = new ColumnInfoRecordsAggregate(rs); records.add(_columnInfos); continue; } if ( recSid == DVALRecord.sid) { _dataValidityTable = new DataValidityTable(rs); records.add(_dataValidityTable); continue; } if (RecordOrderer.isRowBlockRecord(recSid) && bofEofNestingLevel == 1 ) { //only add the aggregate once if (rra != null) { throw new RuntimeException("row/cell records found in the wrong place"); } 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(recSid)) { PageSettingsBlock psb = new PageSettingsBlock(rs); if (bofEofNestingLevel == 1) { 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); continue; } if (recSid == MergeCellsRecord.sid) { // when the MergedCellsTable is found in the right place, we expect those records to be contiguous _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 (recSid == UncalcedRecord.sid) { // don't add UncalcedRecord to the list _isUncalced = true; // this flag is enough continue; } if (recSid == BOFRecord.sid) { bofEofNestingLevel++; if (log.check( POILogger.DEBUG )) log.log(POILogger.DEBUG, "Hit BOF record. Nesting increased to " + bofEofNestingLevel); } 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); break; } } else if (recSid == DimensionsRecord.sid) { // Make a columns aggregate if one hasn't ready been created. if (_columnInfos == null) { _columnInfos = new ColumnInfoRecordsAggregate(); records.add(_columnInfos); } _dimensions = ( DimensionsRecord ) rec; dimsloc = records.size(); } else if (recSid == DefaultColWidthRecord.sid) { defaultcolwidth = ( DefaultColWidthRecord ) rec; } else if (recSid == DefaultRowHeightRecord.sid) { defaultrowheight = ( DefaultRowHeightRecord ) rec; } else if ( recSid == PrintGridlinesRecord.sid ) { printGridlines = (PrintGridlinesRecord) rec; } else if ( recSid == GridsetRecord.sid ) { gridset = (GridsetRecord) rec; } else if ( recSid == SelectionRecord.sid ) { selection = (SelectionRecord) rec; } else if ( recSid == WindowTwoRecord.sid ) { windowTwo = (WindowTwoRecord) rec; } else if ( recSid == ProtectRecord.sid ) { protect = (ProtectRecord) rec; } else if ( recSid == ObjectProtectRecord.sid ) { objprotect = (ObjectProtectRecord) rec; } else if ( recSid == ScenarioProtectRecord.sid ) { scenprotect = (ScenarioProtectRecord) rec; } else if ( recSid == PasswordRecord.sid ) { password = (PasswordRecord) rec; } records.add(rec); } if (_dimensions == null) { throw new RuntimeException("DimensionsRecord was not found"); } if (windowTwo == null) { throw new RuntimeException("WINDOW2 was not found"); } 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, _mergedCellsTable); if (log.check( POILogger.DEBUG )) log.log(POILogger.DEBUG, "sheet createSheet (existing file) exited"); } private static final class RecordCloner implements RecordVisitor { private final List _destList; public RecordCloner(List destList) { _destList = destList; } public void visitRecord(Record r) { _destList.add(r.clone()); } } /** * Clones the low level records of this sheet and returns the new sheet instance. * This method is implemented by adding methods for deep cloning to all records that * can be added to a sheet. The <b>Record</b> object does not implement cloneable. * When adding a new record, implement a public clone method if and only if the record * belongs to a sheet. */ public Sheet cloneSheet() { 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) { ((RecordAggregate) rb).visitContainedRecords(new RecordCloner(clonedRecords)); continue; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?