diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java index 3e6713c4..c2ed2b51 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java @@ -12,6 +12,7 @@ import com.alibaba.excel.exception.ExcelAnalysisStopException; import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.holder.xls.XlsReadWorkbookHolder; import com.alibaba.excel.util.SheetUtils; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STSheetState; /** * Record handler @@ -63,6 +64,7 @@ public class BofRecordHandler extends AbstractXlsRecordHandler { for (int i = 0; i < boundSheetRecords.length; i++) { BoundSheetRecord boundSheetRecord = boundSheetRecords[i]; ReadSheet readSheet = new ReadSheet(i, boundSheetRecord.getSheetname()); + readSheet.setState(sheetState(boundSheetRecord)); readSheetDataList.add(readSheet); } xlsReadWorkbookHolder.setActualSheetDataList(readSheetDataList); @@ -71,4 +73,15 @@ public class BofRecordHandler extends AbstractXlsRecordHandler { throw new ExcelAnalysisStopException("Just need to get the list of sheets."); } } + + private STSheetState.Enum sheetState(BoundSheetRecord boundSheetRecord) { + if (boundSheetRecord.isHidden()) { + return STSheetState.HIDDEN; + } + else if (boundSheetRecord.isVeryHidden()) { + return STSheetState.VERY_HIDDEN; + } + return STSheetState.VISIBLE; + } + } diff --git a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java index 329f5250..9925aefc 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/XlsxSaxAnalyser.java @@ -14,6 +14,7 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import com.alibaba.excel.analysis.v07.usermodel.FineXssfReader; import com.alibaba.excel.analysis.ExcelReadExecutor; import com.alibaba.excel.analysis.v07.handlers.sax.SharedStringsTableHandler; import com.alibaba.excel.analysis.v07.handlers.sax.XlsxRowHandler; @@ -80,7 +81,7 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { analysisSharedStringsTable(sharedStringsTablePackagePart.getInputStream(), xlsxReadWorkbookHolder); } - XSSFReader xssfReader = new XSSFReader(pkg); + FineXssfReader xssfReader = new FineXssfReader(pkg); analysisUse1904WindowDate(xssfReader, xlsxReadWorkbookHolder); // set style table @@ -89,14 +90,14 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { sheetList = new ArrayList(); sheetMap = new HashMap(); commentsTableMap = new HashMap(); - XSSFReader.SheetIterator ite = (XSSFReader.SheetIterator)xssfReader.getSheetsData(); + FineXssfReader.SheetIterator ite = (FineXssfReader.SheetIterator)xssfReader.getSheetsData(); int index = 0; if (!ite.hasNext()) { throw new ExcelAnalysisException("Can not find any sheet!"); } while (ite.hasNext()) { InputStream inputStream = ite.next(); - sheetList.add(new ReadSheet(index, ite.getSheetName())); + sheetList.add(new ReadSheet(index, ite.getSheetName(), ite.getState())); sheetMap.put(index, inputStream); if (xlsxReadContext.readWorkbookHolder().getExtraReadSet().contains(CellExtraTypeEnum.COMMENT)) { CommentsTable commentsTable = ite.getSheetComments(); @@ -108,7 +109,7 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { } } - private void setStylesTable(XlsxReadWorkbookHolder xlsxReadWorkbookHolder, XSSFReader xssfReader) { + private void setStylesTable(XlsxReadWorkbookHolder xlsxReadWorkbookHolder, FineXssfReader xssfReader) { try { xlsxReadWorkbookHolder.setStylesTable(xssfReader.getStylesTable()); } catch (Exception e) { @@ -126,7 +127,7 @@ public class XlsxSaxAnalyser implements ExcelReadExecutor { readCache.init(xlsxReadContext); } - private void analysisUse1904WindowDate(XSSFReader xssfReader, XlsxReadWorkbookHolder xlsxReadWorkbookHolder) + private void analysisUse1904WindowDate(FineXssfReader xssfReader, XlsxReadWorkbookHolder xlsxReadWorkbookHolder) throws Exception { if (xlsxReadWorkbookHolder.globalConfiguration().getUse1904windowing() != null) { return; diff --git a/src/main/java/com/alibaba/excel/analysis/v07/usermodel/FineXssfReader.java b/src/main/java/com/alibaba/excel/analysis/v07/usermodel/FineXssfReader.java new file mode 100644 index 00000000..fe68a4bd --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/v07/usermodel/FineXssfReader.java @@ -0,0 +1,350 @@ +package com.alibaba.excel.analysis.v07.usermodel; + +import org.apache.poi.ooxml.POIXMLException; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; +import org.apache.poi.openxml4j.opc.PackagingURIHelper; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.XMLHelper; +import org.apache.poi.xssf.model.CommentsTable; +import org.apache.poi.xssf.model.SharedStringsTable; +import org.apache.poi.xssf.model.StylesTable; +import org.apache.poi.xssf.model.ThemesTable; +import org.apache.poi.xssf.usermodel.XSSFDrawing; +import org.apache.poi.xssf.usermodel.XSSFRelation; +import org.apache.poi.xssf.usermodel.XSSFShape; +import org.apache.xmlbeans.XmlException; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STSheetState; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @see org.apache.poi.xssf.eventusermodel.XSSFReader + * @author lucian + */ +public class FineXssfReader { + + private static final String RELATIONSHIP_TYPE_1 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; + private static final String RELATIONSHIP_TYPE_2 = "http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument"; + + private static final Set WORKSHEET_RELS; + private static final POILogger LOGGER; + protected OPCPackage pkg; + protected PackagePart workbookPart; + + public FineXssfReader(OPCPackage pkg) throws IOException, OpenXML4JException { + this.pkg = pkg; + PackageRelationship coreDocRelationship = this.pkg.getRelationshipsByType(RELATIONSHIP_TYPE_1).getRelationship(0); + if (coreDocRelationship == null) { + if (this.pkg.getRelationshipsByType(RELATIONSHIP_TYPE_2).getRelationship(0) != null) { + throw new POIXMLException("Strict OOXML isn't currently supported, please see bug #57699"); + } else { + throw new POIXMLException("OOXML file structure broken/invalid - no core document found!"); + } + } else { + this.workbookPart = this.pkg.getPart(coreDocRelationship); + } + } + + public SharedStringsTable getSharedStringsTable() throws IOException, InvalidFormatException { + ArrayList parts = this.pkg.getPartsByContentType(XSSFRelation.SHARED_STRINGS.getContentType()); + return parts.size() == 0 ? null : new SharedStringsTable((PackagePart)parts.get(0)); + } + + public StylesTable getStylesTable() throws IOException, InvalidFormatException { + ArrayList parts = this.pkg.getPartsByContentType(XSSFRelation.STYLES.getContentType()); + if (parts.size() == 0) { + return null; + } else { + StylesTable styles = new StylesTable((PackagePart)parts.get(0)); + parts = this.pkg.getPartsByContentType(XSSFRelation.THEME.getContentType()); + if (parts.size() != 0) { + styles.setTheme(new ThemesTable((PackagePart)parts.get(0))); + } + + return styles; + } + } + + public InputStream getSharedStringsData() throws IOException, InvalidFormatException { + return XSSFRelation.SHARED_STRINGS.getContents(this.workbookPart); + } + + public InputStream getStylesData() throws IOException, InvalidFormatException { + return XSSFRelation.STYLES.getContents(this.workbookPart); + } + + public InputStream getThemesData() throws IOException, InvalidFormatException { + return XSSFRelation.THEME.getContents(this.workbookPart); + } + + public InputStream getWorkbookData() throws IOException, InvalidFormatException { + return this.workbookPart.getInputStream(); + } + + public InputStream getSheet(String relId) throws IOException, InvalidFormatException { + PackageRelationship rel = this.workbookPart.getRelationship(relId); + if (rel == null) { + throw new IllegalArgumentException("No Sheet found with r:id " + relId); + } else { + PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); + PackagePart sheet = this.pkg.getPart(relName); + if (sheet == null) { + throw new IllegalArgumentException("No data found for Sheet with r:id " + relId); + } else { + return sheet.getInputStream(); + } + } + } + + public Iterator getSheetsData() throws IOException, InvalidFormatException { + return new SheetIterator(this.workbookPart); + } + + static { + WORKSHEET_RELS = Collections.unmodifiableSet(new HashSet(Arrays.asList(XSSFRelation.WORKSHEET.getRelation(), XSSFRelation.CHARTSHEET.getRelation()))); + LOGGER = POILogFactory.getLogger(FineXssfReader.class); + } + + private static class XmlSheetRefReader extends DefaultHandler { + private static final String SHEET = "sheet"; + private static final String ID = "id"; + private static final String NAME = "name"; + private static final String STATE = "state"; + private final List sheetRefs; + + private XmlSheetRefReader() { + this.sheetRefs = new LinkedList(); + } + + public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { + if (localName.equalsIgnoreCase(SHEET)) { + String name = null; + String id = null; + STSheetState.Enum state = STSheetState.VISIBLE; + + for(int i = 0; i < attrs.getLength(); ++i) { + String attrName = attrs.getLocalName(i); + if (attrName.equalsIgnoreCase(NAME)) { + name = attrs.getValue(i); + } else if (attrName.equalsIgnoreCase(ID)) { + id = attrs.getValue(i); + } else if (attrName.equalsIgnoreCase(STATE)) { + state = STSheetState.Enum.forString(attrs.getValue(i)); + } + + if (name != null && id != null) { + this.sheetRefs.add(new XssfSheetRef(id, name, state)); + break; + } + } + } + + } + + List getSheetRefs() { + return Collections.unmodifiableList(this.sheetRefs); + } + } + + protected static final class XssfSheetRef { + private final String id; + private final String name; + private final STSheetState.Enum state; + + public XssfSheetRef(String id, String name, STSheetState.Enum state) { + this.id = id; + this.name = name; + this.state = state; + } + + public String getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public STSheetState.Enum getState() { + return state; + } + } + + public static class SheetIterator implements Iterator { + private final Map sheetMap; + XssfSheetRef xssfSheetRef; + final Iterator sheetIterator; + + SheetIterator(PackagePart wb) throws IOException { + try { + this.sheetMap = new HashMap(); + OPCPackage pkg = wb.getPackage(); + Set worksheetRels = this.getSheetRelationships(); + Iterator var4 = wb.getRelationships().iterator(); + + while(var4.hasNext()) { + PackageRelationship rel = (PackageRelationship)var4.next(); + String relType = rel.getRelationshipType(); + if (worksheetRels.contains(relType)) { + PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); + this.sheetMap.put(rel.getId(), pkg.getPart(relName)); + } + } + + this.sheetIterator = this.createSheetIteratorFromWB(wb); + } catch (InvalidFormatException var8) { + throw new POIXMLException(var8); + } + } + + Iterator createSheetIteratorFromWB(PackagePart wb) throws IOException { + XmlSheetRefReader xmlSheetRefReader = new XmlSheetRefReader(); + + XMLReader xmlReader; + try { + xmlReader = XMLHelper.newXMLReader(); + } catch (SAXException var9) { + throw new POIXMLException(var9); + } catch (ParserConfigurationException var9) { + throw new POIXMLException(var9); + } + + xmlReader.setContentHandler(xmlSheetRefReader); + + try { + xmlReader.parse(new InputSource(wb.getInputStream())); + } catch (SAXException var8) { + throw new POIXMLException(var8); + } + + List validSheets = new ArrayList(); + Iterator var5 = xmlSheetRefReader.getSheetRefs().iterator(); + + while(var5.hasNext()) { + XssfSheetRef xssfSheetRef = (XssfSheetRef)var5.next(); + String sheetId = xssfSheetRef.getId(); + if (sheetId != null && sheetId.length() > 0) { + validSheets.add(xssfSheetRef); + } + } + + return validSheets.iterator(); + } + + Set getSheetRelationships() { + return WORKSHEET_RELS; + } + + public boolean hasNext() { + return this.sheetIterator.hasNext(); + } + + public InputStream next() { + this.xssfSheetRef = (XssfSheetRef)this.sheetIterator.next(); + String sheetId = this.xssfSheetRef.getId(); + + try { + PackagePart sheetPkg = (PackagePart)this.sheetMap.get(sheetId); + return sheetPkg.getInputStream(); + } catch (IOException var3) { + throw new POIXMLException(var3); + } + } + + public String getSheetName() { + return this.xssfSheetRef.getName(); + } + + public STSheetState.Enum getState() { + return this.xssfSheetRef.getState(); + } + + public CommentsTable getSheetComments() { + PackagePart sheetPkg = this.getSheetPart(); + + try { + PackageRelationshipCollection commentsList = sheetPkg.getRelationshipsByType(XSSFRelation.SHEET_COMMENTS.getRelation()); + if (commentsList.size() > 0) { + PackageRelationship comments = commentsList.getRelationship(0); + PackagePartName commentsName = PackagingURIHelper.createPartName(comments.getTargetURI()); + PackagePart commentsPart = sheetPkg.getPackage().getPart(commentsName); + return new CommentsTable(commentsPart); + } else { + return null; + } + } catch (IOException var6) { + LOGGER.log(5, new Object[]{var6}); + return null; + } catch (InvalidFormatException var6) { + LOGGER.log(5, new Object[]{var6}); + return null; + } + } + + public List getShapes() { + PackagePart sheetPkg = this.getSheetPart(); + LinkedList shapes = new LinkedList(); + + try { + PackageRelationshipCollection drawingsList = sheetPkg.getRelationshipsByType(XSSFRelation.DRAWINGS.getRelation()); + + for(int i = 0; i < drawingsList.size(); ++i) { + PackageRelationship drawings = drawingsList.getRelationship(i); + PackagePartName drawingsName = PackagingURIHelper.createPartName(drawings.getTargetURI()); + PackagePart drawingsPart = sheetPkg.getPackage().getPart(drawingsName); + if (drawingsPart == null) { + LOGGER.log(5, new Object[]{"Missing drawing: " + drawingsName + ". Skipping it."}); + } else { + XSSFDrawing drawing = new XSSFDrawing(drawingsPart); + shapes.addAll(drawing.getShapes()); + } + } + + return shapes; + } catch (InvalidFormatException var9) { + LOGGER.log(5, new Object[]{var9}); + return null; + } catch (IOException e) { + LOGGER.log(5, new Object[]{e}); + return null; + } catch (XmlException e) { + LOGGER.log(5, new Object[]{e}); + return null; + } + } + + public PackagePart getSheetPart() { + String sheetId = this.xssfSheetRef.getId(); + return this.sheetMap.get(sheetId); + } + + public void remove() { + throw new IllegalStateException("Not supported"); + } + } +} + diff --git a/src/main/java/com/alibaba/excel/read/metadata/ReadSheet.java b/src/main/java/com/alibaba/excel/read/metadata/ReadSheet.java index 5b6f8dec..ff9031e9 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/ReadSheet.java +++ b/src/main/java/com/alibaba/excel/read/metadata/ReadSheet.java @@ -1,5 +1,7 @@ package com.alibaba.excel.read.metadata; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STSheetState; + /** * Read sheet * @@ -14,6 +16,10 @@ public class ReadSheet extends ReadBasicParameter { * sheet name */ private String sheetName; + /** + * sheet state + */ + private STSheetState.Enum state; public ReadSheet() {} @@ -26,6 +32,12 @@ public class ReadSheet extends ReadBasicParameter { this.sheetName = sheetName; } + public ReadSheet(Integer sheetNo, String sheetName, STSheetState.Enum state) { + this.sheetNo = sheetNo; + this.sheetName = sheetName; + this.state = state; + } + public Integer getSheetNo() { return sheetNo; } @@ -42,6 +54,14 @@ public class ReadSheet extends ReadBasicParameter { this.sheetName = sheetName; } + public STSheetState.Enum getState() { + return state; + } + + public void setState(STSheetState.Enum state) { + this.state = state; + } + public void copyBasicParameter(ReadSheet other) { if (other == null) { return;