All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hfg.xml.msofficexml.xlsx.Xlsx Maven / Gradle / Ivy

There is a newer version: 20240423
Show newest version
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);
      }
   }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy