/*
* 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
}
}