org.ttzero.excel.entity.e3.GlobalsSubStream 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.entity.style.FormatParser;
import org.ttzero.excel.entity.style.NumFmt;
import org.ttzero.excel.entity.style.PaletteParser;
import org.ttzero.excel.entity.style.Styles;
import org.ttzero.excel.entity.style.XFParser;
import org.ttzero.excel.reader.ShareStringParser;
import java.awt.Color;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
/**
* 4.2.5 Workbook Globals Sub-stream
*
* The sub-stream that contains the global information
* of a workbook is called the Workbook Globals Sub-stream.
* It is part of the Workbook Stream of BIFF5-BIFF8 workbooks.
*
* @author guanquan.wang at 2019-02-23 11:47
*/
public class GlobalsSubStream {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalsSubStream.class);
public static GlobalsSetting get(Block block) {
// Check Beginning of File
short id = block.nextIdentifier();
if (id != ParserIdentifier.BOF) {
throw new RuntimeException("Miss the Workbook BOF.");
}
BOFParser.BOF bof = BOFParser.get(block);
LOGGER.debug(bof.toString());
GlobalsSetting gs = new GlobalsSetting();
gs.firstSid = block.sid;
List sheetList = new ArrayList<>();
List fmtList = new ArrayList<>();
List xfList = new ArrayList<>();
short nextId, size;
for (; ; ) {
nextId = block.nextIdentifier();
if (nextId == ParserIdentifier.EOF) {
break;
}
// Check the identify
if (ParserIdentifier.contains(nextId)) {
switch (nextId) {
// 5.112 WRITEACCESS
case ParserIdentifier.WRITEACCESS:
gs.writeAccess = StringParser.get16BitWithHead(block);
break;
// 5.17 CODEPAGE
case ParserIdentifier.CODEPAGE:
// The next data size
size = block.nextShort(); // size always 2
assert size == 2;
short code_page = block.nextShort();
// Charset charset = MicroCodePage.of(block.nextShort());
//The CODEPAGE record in BIFF8 always contains the code page 1200 (UTF-16, ➜2.5.3).
// Therefore it is not possible to obtain the encoding used for
// a protection password (it is not UTF-16).
if (code_page != 1200) {
throw new RuntimeException("In BIFF8 always contains the code page 1200(UTF-16LE).");
}
break;
// 5.36 DSF – Double Stream File
case ParserIdentifier.DSF:
size = block.nextShort(); // size always 2
assert size == 2;
// This record specifies if the BIFF8 workbook document contains an
// additional BIFF5 Workbook Stream with the name “Book” (➜2.3.3).
short dsf = block.nextShort();
// 0 = Only the BIFF8 “Workbook” stream is present
// 1 = Additional BIFF5 “Book” stream is in the file
if (dsf == 1) {
throw new RuntimeException("Only support BIFF8.");
}
break;
// 5.111 WINDOWPROTECT
case ParserIdentifier.WINDOWPROTECT:
// 5.82 PROTECT
case ParserIdentifier.PROTECT:
// 5.72 OBJECTPROTECT
case ParserIdentifier.OBJECTPROTECT:
// 5.91 SCENPROTECT
case ParserIdentifier.SCENPROTECT:
size = block.nextShort();
assert size == 2;
// 0 = Objects not protected
// 1 = Objects protected
short p = block.nextShort();
if (p == 1) {
// TODO maybe tip a password message
LOGGER.debug("protected");
}
break;
// 5.76 PASSWORD
case ParserIdentifier.PASSWORD:
size = block.nextShort();
assert size == 2;
gs.hash = block.nextShort();
break;
// // WINDOW1 ➜5.109 require
// case ParserIdentifier.WINDOW1:
// Window1Parser.Window1 window1 = Window1Parser.get(block);
// // FIXME maybe this record will be ignored
// LOGGER.debug(window1);
// break;
// 5.5 BACKUP
// case ParserIdentifier.BACKUP:
// size = block.nextShort();
// assert size == 2;
// short backup = block.nextShort();
// // FIXME maybe this record will be ignored
// if (backup == 1) {
// LOGGER.debug("Create a backup on saving");
// }
// break;
// // HIDEOBJ ➜5.56
// case ParserIdentifier.HIDEOBJ:
// size = block.nextShort();
// assert size == 2;
// short hideobj = block.nextShort();
// // 0 = Show all objects
// // 1 = Show placeholders
// // 2 = Do not show objects
// // FIXME maybe this record will be ignored
// LOGGER.debug("hideobj: " + hideobj);
// break;
// DATEMODE ➜5.28
case ParserIdentifier.DATEMODE:
size = block.nextShort();
assert size == 2;
// 0 = Base date is 1899-Dec-31 (the cell value 1 represents 1900-Jan-01)
// 1 = Base date is 1904-Jan-01 (the cell value 1 represents 1904-Jan-02)
gs.dataMode = block.nextShort();
break;
// // 5.79 PRECISION
// case ParserIdentifier.PRECISION:
// size = block.nextShort();
// assert size == 2;
// // 0 = Use displayed values
// // 1 = Use real cell values
// gs.precision = block.nextShort();
// break;
// // 5.9 BOOKBOOL
// case ParserIdentifier.BOOKBOOL:
// size = block.nextShort();
// assert size == 2;
// // 0 = Save external linked values
// // 1 = Do not save external linked values
// gs.bookbool = block.nextShort();
// break;
// 5.45 FONT require
// case ParserIdentifier.FONT:
// BIFFFont font = FontParser.get(block);
// LOGGER.debug(font);
// break;
// 5.49 FORMAT
case ParserIdentifier.FORMAT:
NumFmt format = FormatParser.get(block);
fmtList.add(format);
break;
// 5.115 XF – Extended Format
case ParserIdentifier.XF:
XFParser.XF xf = XFParser.get(block);
xf.id = xfList.size();
xfList.add(xf);
break;
// 5.103 STYLE
// case ParserIdentifier.STYLE:
// StyleParser.Style style = StyleParser.get(block);
// LOGGER.debug(style);
// break;
// 5.74 PALETTE
case ParserIdentifier.PALETTE:
Color[] colors = PaletteParser.get(block);
break;
// 5.95 SHEET
case ParserIdentifier.SHEET:
sheetList.add(SheetParser.get(block));
break;
// // FIXME ignore 5.22 COUNTRY
// case ParserIdentifier.COUNTRY:
// CountryParser.get(block);
// break;
// FIXME 4.10.3 References in BIFF8
// FIXME 5.33 DEFINEDNAME
// 4.11 Shared String Table (BIFF8)
case ParserIdentifier.SST:
// String[] sst = ShareStringParser.get(block);
// LOGGER.debug(Arrays.toString(sst));
gs.sst = ShareStringParser.get(block);
break;
// 5.33 DEFINEDNAME
// case ParserIdentifier.DEFINEDNAME:
// break;
default:
IgnoreParser.get(block);
}
} else {
IgnoreParser.get(block);
}
}
SheetInfo[] sheets = new SheetInfo[sheetList.size()];
sheetList.toArray(sheets);
gs.sheets = sheets;
// Create a simple Styles
gs.styles = Styles.forReader();
// Test and merge date format
testDateFormat(gs, xfList, fmtList);
LOGGER.debug(gs.toString());
return gs;
}
private static void testDateFormat(GlobalsSetting gs, List xfList, List fmtList) {
List clearXFList = xfList.stream().filter(xf -> xf.format > 0).collect(Collectors.toList());
for (NumFmt nf : fmtList) {
if (Styles.testCodeIsDate(nf.getCode())) {
for (XFParser.XF xf : clearXFList) {
if (xf.format == nf.getId()) {
gs.styles.addDateFmtCache(xf.id);
}
}
}
}
}
}