org.ttzero.excel.entity.e3.SheetSubStream Maven / Gradle / Ivy
/*
* Copyright (c) 2019-2020, [email protected] All Rights Reserved.
*
* Licensed 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.ttzero.excel.entity.e3;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.ttzero.excel.reader.BIFF8Row;
import org.ttzero.excel.reader.Dimension;
import org.ttzero.excel.reader.ExcelReadException;
import org.ttzero.excel.reader.RowBlock;
import org.ttzero.excel.reader.RowBlockParser;
/**
* 2.3.4 Sub-streams
*
* A sub-stream that describes a sheet in a workbook
* is called Sheet Sub-stream. It is part of the BIFF5-BIFF8
* Workbook Stream as well as the BIFF4W Workspace Stream.
*
* @author guanquan.wang at 2019-03-02 11:29
*/
public class SheetSubStream {
protected static final Logger LOGGER = LoggerFactory.getLogger(SheetSubStream.class);
protected GlobalsSetting gs;
protected SheetInfo sheet;
protected Index index;
protected Dimension range;
protected Block block;
protected RowBlock rowBlock;
protected BIFF8Row firstRow;
protected boolean eof;
public SheetSubStream(GlobalsSetting gs, SheetInfo sheet) {
this.gs = gs;
this.sheet = sheet;
}
/**
* @return sheet name
*/
public String getName() {
return sheet.getName();
}
public void get(Block block) {
int sid = gs.firstSid;
int n = sheet.position >> block.context.ssz, m = sheet.position - (n << block.context.ssz);
block.context.sectorTable.moveTo(sid);
for (; n-- > 0; sid = block.context.sectorTable.nextSecID()) ;
block.testShouldLoad(sid);
block.skip(m);
// Check Beginning of File
short id = block.nextIdentifier();
if (id != ParserIdentifier.BOF) {
throw new ExcelReadException("Miss the BOF.");
}
// BOF
BOFParser.BOF bof = BOFParser.get(block);
LOGGER.debug(bof.toString());
for ( ; ; ) {
short nextId = block.nextIdentifier();
if (nextId == ParserIdentifier.EOF) {
break;
}
// Check the identify
if (!ParserIdentifier.contains(nextId)) {
IgnoreParser.get(block);
continue;
}
// Only parse the record in whitelist
if (parseWhiteListRecord(nextId, block)) {
break;
}
}
// Empty worksheet
if (range.lastRow - range.firstRow < 0) {
eof = true;
}
if (!eof && beforeParseRowBlock()) {
startReadRowBlock();
}
}
/**
* Begin to parse rows
*/
protected void startReadRowBlock() {
// Parse the first row block
rowBlock = RowBlockParser.get(this.block);
rowBlock.setGlobalEntry(gs.sst, gs.styles);
// The first row block's first row
if (rowBlock.hasNext()) {
firstRow = rowBlock.firstRow();
rowBlock.setHeaderRow(firstRow.asHeader());
} else {
eof = true;
}
}
/**
* Parse whitelist record
*
* @param id the record id
* @param block block data
* @return true if abort all parse
*/
protected boolean parseWhiteListRecord(int id, Block block) {
switch (id) {
// 4.7 Cell Table and Row Blocks
case ParserIdentifier.INDEX:
index = IndexParser.get(block);
break;
// 5.35 DIMENSION
case ParserIdentifier.DIMENSION:
block.ready();
// Index to first used row
int fr = block.nextInt() + 1;
// Index to last used row, increased by 1
int lr = block.nextInt();
// Index to first used column
short fc = (short) (block.nextShort() + 1);
// Index to last used column, increased by 1
short lc = block.nextShort();
range = new Dimension(fr, fc, lr, lc);
block.commit();
break;
// 4.7 Cell Table and Row Blocks
case ParserIdentifier.ROW:
block.cacheIdentifier(); // rollback
this.block = block.deepClone();
return true;
// 5.29
case ParserIdentifier.DBCELL:
// Empty sheet
return eof = true;
default:
IgnoreParser.get(block);
}
return false;
}
/**
* Do something before parse RowBlock
*
* @return boolean value, abort if returns false
*/
protected boolean beforeParseRowBlock() {
return this.block != null;
}
public Dimension getRange() {
return range;
}
public BIFF8Row firstRow() {
return firstRow;
}
/**
* iterator rows
*
* @return Row
*/
public BIFF8Row nextRow() {
if (eof) return null;
if (!rowBlock.hasNext()) {
BIFF8Row row = rowBlock.lastRow();
if (row.getRowNumber() < range.lastRow - 1) {
rowBlock = RowBlockParser.get(block);
if (!rowBlock.hasNext()) {
return null;
}
// End loop
} else {
eof = true;
return null;
}
}
return rowBlock.next();
}
}