/* * You may amend and distribute as you like, but don't remove this header! * * ExcelPackage provides server-side generation of Excel 2007 spreadsheets. * See http://www.codeplex.com/ExcelPackage for details. * * Copyright 2007 © Dr John Tunnicliffe * mailto:dr.john.tunnicliffe@btinternet.com * All rights reserved. * * ExcelPackage is an Open Source project provided under the * GNU General Public License (GPL) as published by the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * The GNU General Public License can be viewed at http://www.opensource.org/licenses/gpl-license.php * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html * * The code for this project may be used and redistributed by any means PROVIDING it is * not sold for profit without the author's written consent, and providing that this notice * and the author's name and all copyright notices remain intact. * * All code and executables are provided "as is" with no warranty either express or implied. * The author accepts no liability for any damage or loss of business that this product may cause. */ /* * Code change notes: * * Author Change Date * ****************************************************************************** * John Tunnicliffe Initial Release 01-Jan-2007 * ****************************************************************************** */ using System; using System.IO; using System.IO.Packaging; using System.Xml.Linq; namespace OfficeOpenXml.Core.ExcelPackage { /// /// Represents an Excel 2007 XLSX file package. Opens the file and provides access /// to all the components (workbook, worksheets, properties etc.). /// public class ExcelPackage : IDisposable { #region Properties /// /// Provides access to the main schema used by all Excel components /// protected internal static XNamespace schemaMain = @"http://schemas.openxmlformats.org/spreadsheetml/2006/main"; /// /// Provides access to the relationship schema /// protected internal static XNamespace schemaRelationships = @"http://schemas.openxmlformats.org/officeDocument/2006/relationships"; private Package _package; private string _outputFolderPath; private ExcelWorkbook _workbook; #endregion #region ExcelPackage Constructors /// /// Creates a new instance of ExcelPackage based on an underlying storage stream. /// Pass an OfficeCryptoStream to support encrypted (password-protected) Excel files. /// /// If stream is empty, new package is created, otherwise /// it is opened by reading from the stream. public ExcelPackage(Stream packageStream) { if (packageStream.Length > 0) { // open the existing package _package = Package.Open(packageStream, FileMode.Open, FileAccess.ReadWrite); } else { // create a new package and add the main workbook.xml part _package = Package.Open(packageStream, FileMode.Create); InitializeNewPackage(); } } /// /// Creates a new instance of the ExcelPackage class based on a existing file or creates a new file. /// /// If newFile exists, it is opened. Otherwise it is created from scratch. public ExcelPackage(FileInfo newFile) { _outputFolderPath = newFile.DirectoryName; if (newFile.Exists) { // open the existing package _package = Package.Open(newFile.FullName, FileMode.Open, FileAccess.ReadWrite); } else { // create a new package and add the main workbook.xml part _package = Package.Open(newFile.FullName, FileMode.Create, FileAccess.ReadWrite); InitializeNewPackage(); } } private void InitializeNewPackage() { if (_package == null) { throw new Exception("Package is null."); } // save a temporary part to create the default application/xml content type Uri uriDefaultContentType = new Uri("/default.xml", UriKind.Relative); PackagePart partTemp = _package.CreatePart(uriDefaultContentType, "application/xml", CompressionOption.Normal); XDocument workbook = Workbook.WorkbookXml; // this will create the workbook xml in the package // create the relationship to the main part _package.CreateRelationship(Workbook.WorkbookUri, TargetMode.Internal, schemaRelationships.NamespaceName + "/officeDocument"); // remove the temporary part that created the default xml content type _package.DeletePart(uriDefaultContentType); } /// /// Creates a new instance of the ExcelPackage class based on a existing template. /// WARNING: If newFile exists, it is deleted! /// /// The name of the Excel file to be created /// The name of the Excel template to use as the basis of the new Excel file public ExcelPackage(FileInfo newFile, FileInfo template) { _outputFolderPath = newFile.DirectoryName; if (template.Exists) { if (newFile.Exists) { try { newFile.Delete(); } catch (Exception ex) { throw new Exception("ExcelPackage Error: Target file already exists and is locked.", ex); } } newFile = template.CopyTo(newFile.FullName); newFile.IsReadOnly = false; _package = Package.Open(newFile.FullName, FileMode.Open, FileAccess.ReadWrite); } else throw new Exception("ExcelPackage Error: Passed invalid TemplatePath to Excel Template"); } #endregion #region Public Properties /// /// Setting DebugMode to true will cause the Save method to write the /// raw XML components to the same folder as the output Excel file /// public bool DebugMode = false; /// /// Returns a reference to the file package /// public Package Package => _package; /// /// Returns a reference to the workbook component within the package. /// All worksheets and cells can be accessed through the workbook. /// public ExcelWorkbook Workbook { get { if (_workbook == null) _workbook = new ExcelWorkbook(this); return (_workbook); } } #endregion #region WriteDebugFile /// /// Writes a debug file to the output folder, but only if DebugMode = true /// /// The XmlDocument to save to the file system /// The subfolder in which the file is to be saved /// The name of the file to save. protected internal void WriteDebugFile(XDocument xmlDoc, string subFolder, string FileName) { if (DebugMode) { DirectoryInfo dir = new DirectoryInfo(_outputFolderPath + "/" + subFolder); if (!dir.Exists) dir.Create(); FileInfo file = new FileInfo(_outputFolderPath + "/" + subFolder + "/" + FileName); if (file.Exists) { file.IsReadOnly = false; file.Delete(); } using (var fs = new FileStream(file.FullName, FileMode.OpenOrCreate)) { xmlDoc.Save(fs); } } } #endregion ///// ///// Returns the Uri to a parent part (e.g. workbook.xml) ///// ///// The relationship the ///// //protected internal Uri GetMainUri(string Relationship) //{ // Uri uriMain = null; // // Get the Uri to the main part // Uri uriParent = new Uri("/", UriKind.Relative); // PackageRelationship relationship = GetMainRelationship(Relationship); // if (relationship != null) // uriMain = PackUriHelper.ResolvePartUri(uriParent, relationship.TargetUri); // return (uriMain); //} ///// ///// ///// ///// ///// //protected internal PackageRelationship GetMainRelationship(string Relationship) //{ // PackageRelationship relMain = null; // foreach (PackageRelationship relationship in _package.GetRelationshipsByType(schemaRelationships + "/" + Relationship)) // { // relMain = relationship; // break; // There should only be one main part // } // return (relMain); //} #region GetSharedUri /// /// Obtains the Uri to a shared part (e.g. sharedstrings.xml) /// /// Uri to the parent component /// The relationship to the parent component /// The Uri to a shared part protected internal Uri GetSharedUri(Uri uriParent, string Relationship) { Uri uriShared = null; PackagePart partParent = _package.GetPart(uriParent); // Get the Uri to the shared part foreach (System.IO.Packaging.PackageRelationship relationship in partParent.GetRelationshipsByType(schemaRelationships + "/" + Relationship)) { uriShared = PackUriHelper.ResolvePartUri(uriParent, relationship.TargetUri); break; // There should only be one shared resource } return (uriShared); } #endregion #region AddSchemaAttribute ///// ///// Adds additional schema attributes to the root element ///// ///// The root element ///// The schema to apply //protected internal static void AddSchemaAttribute(XmlElement root, string schema) //{ // var nsAttribute = root.OwnerDocument.CreateAttribute("xmlns"); // nsAttribute.Value = schema; // root.Attributes.Append(nsAttribute); //} #endregion #region SavePart /// /// Saves the XmlDocument into the package at the specified Uri. /// /// The Uri of the component /// The XmlDocument to save protected internal void SavePart(Uri uriPart, XDocument xmlPart) { PackagePart partPack = _package.GetPart(uriPart); xmlPart.Save(partPack.GetStream(FileMode.Create, FileAccess.Write)); } #endregion #region Dispose /// /// Closes the package. /// public void Dispose() { _package.Close(); } #endregion #region Save // ExcelPackage save /// /// Saves all the components back into the package. /// This method recursively calls the Save method on all sub-components. /// public void Save() { Workbook.Save(); } #endregion #region GetXmlFromUri /// /// Obtains the XmlDocument from the package referenced by the Uri /// /// The Uri to the component /// The XmlDocument of the component protected internal XDocument GetXmlFromUri(Uri uriPart) { var packPart = _package.GetPart(uriPart); return XDocument.Load(packPart.GetStream()); } #endregion } }