com.hfg.xml.msofficexml.xlsx.Xlsx Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com_hfg Show documentation
Show all versions of com_hfg Show documentation
com.hfg xml, html, svg, and bioinformatics utility library
package com.hfg.xml.msofficexml.xlsx;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import com.hfg.util.StringUtil;
import com.hfg.util.collection.OrderedMap;
import com.hfg.util.io.NoCloseBufferedInputStream;
import com.hfg.util.io.RuntimeIOException;
import com.hfg.util.io.StreamUtil;
import com.hfg.xml.XMLDoc;
import com.hfg.xml.XMLNode;
import com.hfg.xml.XMLTag;
import com.hfg.xml.msofficexml.OfficeOpenXmlDocument;
import com.hfg.xml.msofficexml.OfficeXML;
import com.hfg.xml.msofficexml.RelationshipType;
import com.hfg.xml.msofficexml.docx.RelationshipXML;
import com.hfg.xml.msofficexml.xlsx.part.SharedStringsPart;
import com.hfg.xml.msofficexml.xlsx.part.SsmlDrawingPart;
import com.hfg.xml.msofficexml.xlsx.part.StylesPart;
import com.hfg.xml.msofficexml.xlsx.part.WorkbookPart;
import com.hfg.xml.msofficexml.xlsx.part.WorkbookRelationshipPart;
import com.hfg.xml.msofficexml.xlsx.spreadsheetml.SsmlWorkbook;
import com.hfg.xml.msofficexml.xlsx.spreadsheetml.SsmlXML;
//------------------------------------------------------------------------------
/**
Office Open XML format Excel document.
@author J. Alex Taylor, hairyfatguy.com
*/
//------------------------------------------------------------------------------
// com.hfg XML/HTML Coding Library
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
// [email protected]
//------------------------------------------------------------------------------
// For various specifications and limits see:
// https://support.office.com/en-us/article/Excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3
public class Xlsx extends OfficeOpenXmlDocument
{
private Workbook mWorkbook;
private WorkbookPart mWorkbookPart;
private WorkbookRelationshipPart mWorkbookRelationshipPart;
private StylesPart mStylesPart;
private SharedStringsPart mSharedStringsPart;
private int mDrawingIndex = 1;
private static String sDefaultName = "Untitled.xlsx";
//##########################################################################
// CONSTRUCTORS
//##########################################################################
//---------------------------------------------------------------------------
public Xlsx()
{
super();
init();
}
//---------------------------------------------------------------------------
// TODO: Work in progress
public Xlsx(File inFile)
{
if (! inFile.exists())
{
throw new RuntimeIOException("The specified .xlsx file "
+ StringUtil.singleQuote(inFile.getPath()) + " doesn't exist!");
}
else if (! inFile.canRead())
{
throw new RuntimeIOException("No read permissions for the specified .xlsx file "
+ StringUtil.singleQuote(inFile.getPath()) + "!");
}
try
{
readFromStream(new FileInputStream(inFile));
}
catch (Exception e)
{
throw new RuntimeIOException(e);
}
}
//---------------------------------------------------------------------------
public Xlsx(InputStream inFileStream)
{
readFromStream(inFileStream);
}
//---------------------------------------------------------------------------
private void init()
{
// Setup essential relationships
getPackageRelationshipPart().addRelationship(RelationshipType.OFFICE_DOCUMENT, SsmlXML.WORKBOOK_FILE);
/*
getContentTypesPart().addOverride(new OfficeXMLPart(this).setFile(new File("/docProps/core.xml")), OfficeOpenXMLContentType.CORE_PROPERTIES);
getContentTypesPart().addOverride(new OfficeXMLPart(this).setFile(new File("/docProps/app.xml")), OfficeOpenXMLContentType.EXTENDED_PROPERTIES);
getContentTypesPart().addOverride(new OfficeXMLPart(this).setFile(new File("/xl/workbook.xml")), SsmlContentType.WORKBOOK);
getContentTypesPart().addOverride(new OfficeXMLPart(this).setFile(new File("/xl/styles.xml")), SsmlContentType.SPREADSHEET_STYLES);
getContentTypesPart().addOverride(new OfficeXMLPart(this).setFile(new File("/xl/sharedStrings.xml")), SsmlContentType.SPREADSHEET_SHARED_STRINGS);
*/
mWorkbookPart = new WorkbookPart(this);
// addPart(mWorkbookPart);
}
//##########################################################################
// PUBLIC METHODS
//##########################################################################
//---------------------------------------------------------------------------
public static String getDefaultName()
{
return sDefaultName;
}
//---------------------------------------------------------------------------
@Override
public String name()
{
String name = super.name();
if (! StringUtil.isSet(name))
{
name = getDefaultName();
setName(name);
}
return name;
}
//---------------------------------------------------------------------------
public WorkbookRelationshipPart getWorkbookRelationshipPart()
{
if (null == mWorkbookRelationshipPart)
{
mWorkbookRelationshipPart = new WorkbookRelationshipPart(this);
}
return mWorkbookRelationshipPart;
}
//---------------------------------------------------------------------------
public WorkbookPart getWorkbookPart()
{
if (null == mWorkbookPart)
{
mWorkbookPart = new WorkbookPart(this);
}
return mWorkbookPart;
}
//---------------------------------------------------------------------------
public StylesPart getStylesPart()
{
if (null == mStylesPart)
{
mStylesPart = new StylesPart(this);
mStylesPart.setDefaults();
}
return mStylesPart;
}
//---------------------------------------------------------------------------
public SharedStringsPart getSharedStringsPart()
{
if (null == mSharedStringsPart)
{
mSharedStringsPart = new SharedStringsPart(this);
}
return mSharedStringsPart;
}
//---------------------------------------------------------------------------
public Workbook getWorkbook()
{
if (null == mWorkbook)
{
mWorkbook = new Workbook(this);
}
return mWorkbook;
}
//---------------------------------------------------------------------------
public void addDrawingPart(SsmlDrawingPart inValue)
{
// The part has already been added, we just need to assign a drawing index.
inValue.setDrawingIndex(mDrawingIndex++);
}
//---------------------------------------------------------------------------
@Override
public void write(OutputStream inStream)
throws IOException
{
finalizeWorkbook();
super.write(inStream);
}
//##########################################################################
// PRIVATE METHODS
//##########################################################################
//---------------------------------------------------------------------------
// This method is just parsing the basics at the moment.
private void parse(ZipInputStream inStream)
throws IOException
{
mWorkbookPart = new WorkbookPart(this);
ZipEntry zipEntry;
// This to to prevent the closes from the file processing from closing the main zip stream
NoCloseBufferedInputStream noCloseStream = new NoCloseBufferedInputStream(inStream);
XMLTag workbookTag = null;
XMLTag workbookRelationshipsTag = null;
Map sheetMap = new HashMap<>(25);
while ((zipEntry = inStream.getNextEntry()) != null)
{
if (zipEntry.getName().equals(SsmlXML.WORKBOOK_FILE.getPath()))
{
XMLDoc doc = new XMLDoc(noCloseStream);
workbookTag = (XMLTag) doc.getRootNode();
mWorkbookPart.setRootNode(new SsmlWorkbook(this, workbookTag));
}
else if (zipEntry.getName().equals("xl/_rels/workbook.xml.rels"))
{
XMLDoc doc = new XMLDoc(noCloseStream);
workbookRelationshipsTag = (XMLTag) doc.getRootNode();
}
else if (zipEntry.getName().startsWith(SsmlXML.WORKSHEETS_DIR.getPath()))
{
if (! zipEntry.getName().contains("/_rels"))
{
sheetMap.put(new File(zipEntry.getName()), (XMLTag) new XMLDoc(noCloseStream).getRootNode());
}
}
else if (zipEntry.getName().equals(SsmlXML.SHARED_STRINGS_FILE.getPath()))
{
mSharedStringsPart = new SharedStringsPart(this, noCloseStream);
}
else if (zipEntry.getName().equals(SsmlXML.STYLES_FILE.getPath()))
{
mStylesPart = new StylesPart(this, noCloseStream);
}
inStream.closeEntry();
}
// Add the sheets to the workbook (in the proper order)
OrderedMap sheetNameMap = buildSheetNameMap(workbookTag, workbookRelationshipsTag);
for (File sheetFile : sheetNameMap.keySet())
{
getWorkbook().addWorksheet(sheetNameMap.get(sheetFile), null, sheetMap.get(sheetFile));
}
}
//---------------------------------------------------------------------------
private OrderedMap buildSheetNameMap(XMLTag inWorkbookTag, XMLTag inWorkbookRelationshipsTag)
{
OrderedMap sheetNameMap = new OrderedMap<>(25);
XMLTag sheetsTag = inWorkbookTag.getRequiredSubtagByName(SsmlXML.SHEETS);
for (XMLNode sheetTag : sheetsTag.getSubtagsByName(SsmlXML.SHEET))
{
String relationshipRef = sheetTag.getAttributeValue(RelationshipXML.ID_ATT);
for (XMLNode relationshipTag : inWorkbookRelationshipsTag.getSubtagsByName(OfficeXML.RELATIONSHIP))
{
if (relationshipTag.getAttributeValue(OfficeXML.ID_ATT).equals(relationshipRef))
{
File file = new File(SsmlXML.XL_DIR, relationshipTag.getAttributeValue(OfficeXML.TARGET_ATT));
sheetNameMap.put(file, sheetTag.getAttributeValue(SsmlXML.NAME_ATT));
break;
}
}
}
return sheetNameMap;
}
//---------------------------------------------------------------------------
private void finalizeWorkbook()
{
}
//---------------------------------------------------------------------------
private void readFromStream(InputStream inFileStream)
{
ZipInputStream zipStream = null;
try
{
zipStream = new ZipInputStream(inFileStream);
parse(zipStream);
}
catch (Exception e)
{
throw new RuntimeIOException(e);
}
finally
{
StreamUtil.close(zipStream);
}
}
}