| /******************************************************************************* | 
 |  * You may amend and distribute as you like, but don't remove this header! | 
 |  * | 
 |  * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets. | 
 |  * See http://www.codeplex.com/EPPlus for details. | 
 |  * | 
 |  * Copyright (C) 2011  Jan Källman | 
 |  * | 
 |  * 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. | 
 |  * | 
 |  * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php | 
 |  * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html | 
 |  * | 
 |  * 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 | 
 |  * ****************************************************************************** | 
 |  * Jan Källman		                Initial Release		        2009-10-01 | 
 |  * Starnuto Di Topo & Jan Källman   Added stream constructors  | 
 |  *                                  and Load method Save as  | 
 |  *                                  stream                      2010-03-14 | 
 |  * Jan Källman		License changed GPL-->LGPL 2011-12-27 | 
 |  *******************************************************************************/ | 
 | using System; | 
 | using System.Xml; | 
 | using System.IO; | 
 | using System.Collections.Generic; | 
 | using System.Security.Cryptography; | 
 | using OfficeOpenXml.Drawing; | 
 | using OfficeOpenXml.Utils; | 
 | using OfficeOpenXml.Packaging.Ionic.Zlib; | 
 | using OfficeOpenXml.FormulaParsing; | 
 | using OfficeOpenXml.Encryption; | 
 | namespace OfficeOpenXml | 
 | { | 
 |     /// <summary> | 
 |     /// Maps to DotNetZips CompressionLevel enum | 
 |     /// </summary> | 
 |     public enum CompressionLevel | 
 |     { | 
 |         Level0 = 0, | 
 |         None = 0, | 
 |         Level1 = 1, | 
 |         BestSpeed = 1, | 
 |         Level2 = 2, | 
 |         Level3 = 3, | 
 |         Level4 = 4, | 
 |         Level5 = 5, | 
 |         Level6 = 6, | 
 |         Default = 6, | 
 |         Level7 = 7, | 
 |         Level8 = 8, | 
 |         BestCompression = 9, | 
 |         Level9 = 9, | 
 |     } | 
 |     /// <summary> | 
 |     /// Represents an Excel 2007/2010 XLSX file package.   | 
 |     /// This is the top-level object to access all parts of the document. | 
 |     /// <code> | 
 | 	///     FileInfo newFile = new FileInfo(outputDir.FullName + @"\sample1.xlsx"); | 
 | 	/// 	if (newFile.Exists) | 
 | 	/// 	{ | 
 | 	/// 		newFile.Delete();  // ensures we create a new workbook | 
 | 	/// 		newFile = new FileInfo(outputDir.FullName + @"\sample1.xlsx"); | 
 | 	/// 	} | 
 | 	/// 	using (ExcelPackage package = new ExcelPackage(newFile)) | 
 |     ///     { | 
 |     ///         // add a new worksheet to the empty workbook | 
 |     ///         ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Inventory"); | 
 |     ///         //Add the headers | 
 |     ///         worksheet.Cells[1, 1].Value = "ID"; | 
 |     ///         worksheet.Cells[1, 2].Value = "Product"; | 
 |     ///         worksheet.Cells[1, 3].Value = "Quantity"; | 
 |     ///         worksheet.Cells[1, 4].Value = "Price"; | 
 |     ///         worksheet.Cells[1, 5].Value = "Value"; | 
 |     /// | 
 |     ///         //Add some items... | 
 |     ///         worksheet.Cells["A2"].Value = "12001"; | 
 |     ///         worksheet.Cells["B2"].Value = "Nails"; | 
 |     ///         worksheet.Cells["C2"].Value = 37; | 
 |     ///         worksheet.Cells["D2"].Value = 3.99; | 
 |     /// | 
 |     ///         worksheet.Cells["A3"].Value = "12002"; | 
 |     ///         worksheet.Cells["B3"].Value = "Hammer"; | 
 |     ///         worksheet.Cells["C3"].Value = 5; | 
 |     ///         worksheet.Cells["D3"].Value = 12.10; | 
 |     /// | 
 |     ///         worksheet.Cells["A4"].Value = "12003"; | 
 |     ///         worksheet.Cells["B4"].Value = "Saw"; | 
 |     ///         worksheet.Cells["C4"].Value = 12; | 
 |     ///         worksheet.Cells["D4"].Value = 15.37; | 
 |     /// | 
 |     ///         //Add a formula for the value-column | 
 |     ///         worksheet.Cells["E2:E4"].Formula = "C2*D2"; | 
 |     /// | 
 |     ///            //Ok now format the values; | 
 |     ///         using (var range = worksheet.Cells[1, 1, 1, 5])  | 
 |     ///          { | 
 |     ///             range.Style.Font.Bold = true; | 
 |     ///             range.Style.Fill.PatternType = ExcelFillStyle.Solid; | 
 |     ///             range.Style.Fill.BackgroundColor.SetColor(Color.DarkBlue); | 
 |     ///             range.Style.Font.Color.SetColor(Color.White); | 
 |     ///         } | 
 |     /// | 
 |     ///         worksheet.Cells["A5:E5"].Style.Border.Top.Style = ExcelBorderStyle.Thin; | 
 |     ///         worksheet.Cells["A5:E5"].Style.Font.Bold = true; | 
 |     /// | 
 |     ///         worksheet.Cells[5, 3, 5, 5].Formula = string.Format("SUBTOTAL(9,{0})", new ExcelAddress(2,3,4,3).Address); | 
 |     ///         worksheet.Cells["C2:C5"].Style.Numberformat.Format = "#,##0"; | 
 |     ///         worksheet.Cells["D2:E5"].Style.Numberformat.Format = "#,##0.00"; | 
 |     /// | 
 |     ///         //Create an autofilter for the range | 
 |     ///         worksheet.Cells["A1:E4"].AutoFilter = true; | 
 |     /// | 
 |     ///         worksheet.Cells["A1:E5"].AutoFitColumns(0); | 
 |     /// | 
 |     ///         // lets set the header text  | 
 |     ///         worksheet.HeaderFooter.oddHeader.CenteredText = "&24&U&\"Arial,Regular Bold\" Inventory"; | 
 |     ///         // add the page number to the footer plus the total number of pages | 
 |     ///         worksheet.HeaderFooter.oddFooter.RightAlignedText = | 
 |     ///         string.Format("Page {0} of {1}", ExcelHeaderFooter.PageNumber, ExcelHeaderFooter.NumberOfPages); | 
 |     ///         // add the sheet name to the footer | 
 |     ///         worksheet.HeaderFooter.oddFooter.CenteredText = ExcelHeaderFooter.SheetName; | 
 |     ///         // add the file path to the footer | 
 |     ///         worksheet.HeaderFooter.oddFooter.LeftAlignedText = ExcelHeaderFooter.FilePath + ExcelHeaderFooter.FileName; | 
 |     /// | 
 |     ///         worksheet.PrinterSettings.RepeatRows = worksheet.Cells["1:2"]; | 
 |     ///         worksheet.PrinterSettings.RepeatColumns = worksheet.Cells["A:G"]; | 
 |     /// | 
 |     ///          // Change the sheet view to show it in page layout mode | 
 |     ///           worksheet.View.PageLayoutView = true; | 
 |     /// | 
 |     ///         // set some document properties | 
 |     ///         package.Workbook.Properties.Title = "Invertory"; | 
 |     ///         package.Workbook.Properties.Author = "Jan Källman"; | 
 |     ///         package.Workbook.Properties.Comments = "This sample demonstrates how to create an Excel 2007 workbook using EPPlus"; | 
 |     /// | 
 |     ///         // set some extended property values | 
 |     ///         package.Workbook.Properties.Company = "AdventureWorks Inc."; | 
 |     /// | 
 |     ///         // set some custom property values | 
 |     ///         package.Workbook.Properties.SetCustomPropertyValue("Checked by", "Jan Källman"); | 
 |     ///         package.Workbook.Properties.SetCustomPropertyValue("AssemblyName", "EPPlus"); | 
 |     /// | 
 |     ///         // save our new workbook and we are done! | 
 |     ///         package.Save(); | 
 |     /// | 
 |     ///       } | 
 |     /// | 
 |     ///       return newFile.FullName; | 
 |     /// </code> | 
 |     /// More samples can be found at  <a href="http://epplus.codeplex.com/">http://epplus.codeplex.com/</a> | 
 |     /// </summary> | 
 | 	public sealed class ExcelPackage : IDisposable | 
 | 	{ | 
 |         internal const bool preserveWhitespace=false; | 
 |         Stream _stream = null; | 
 |         private bool _isExternalStream=false; | 
 |         internal class ImageInfo | 
 |         { | 
 |             internal string Hash { get; set; } | 
 |             internal Uri Uri{get;set;} | 
 |             internal int RefCount { get; set; } | 
 |             internal Packaging.ZipPackagePart Part { get; set; } | 
 |         } | 
 |         internal Dictionary<string, ImageInfo> _images = new Dictionary<string, ImageInfo>(); | 
 | 		#region Properties | 
 | 		/// <summary> | 
 | 		/// Extention Schema types | 
 | 		/// </summary> | 
 |         internal const string schemaXmlExtension = "application/xml"; | 
 |         internal const string schemaRelsExtension = "application/vnd.openxmlformats-package.relationships+xml"; | 
 |         /// <summary> | 
 | 		/// Main Xml schema name | 
 | 		/// </summary> | 
 | 		internal const string schemaMain = @"http://schemas.openxmlformats.org/spreadsheetml/2006/main"; | 
 | 		/// <summary> | 
 | 		/// Relationship schema name | 
 | 		/// </summary> | 
 | 		internal const string schemaRelationships = @"http://schemas.openxmlformats.org/officeDocument/2006/relationships"; | 
 |                                                                                | 
 |         internal const string schemaDrawings = @"http://schemas.openxmlformats.org/drawingml/2006/main"; | 
 |         internal const string schemaSheetDrawings = @"http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"; | 
 |         internal const string schemaMarkupCompatibility = @"http://schemas.openxmlformats.org/markup-compatibility/2006"; | 
 |  | 
 |         internal const string schemaMicrosoftVml = @"urn:schemas-microsoft-com:vml"; | 
 |         internal const string schemaMicrosoftOffice = "urn:schemas-microsoft-com:office:office"; | 
 |         internal const string schemaMicrosoftExcel = "urn:schemas-microsoft-com:office:excel"; | 
 |  | 
 |         internal const string schemaChart = @"http://schemas.openxmlformats.org/drawingml/2006/chart";                                                         | 
 |         internal const string schemaHyperlink = @"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"; | 
 |         internal const string schemaComment = @"http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; | 
 |         internal const string schemaImage = @"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"; | 
 |         //Office properties | 
 |         internal const string schemaCore = @"http://schemas.openxmlformats.org/package/2006/metadata/core-properties"; | 
 |         internal const string schemaExtended = @"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"; | 
 |         internal const string schemaCustom = @"http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"; | 
 |         internal const string schemaDc = @"http://purl.org/dc/elements/1.1/"; | 
 |         internal const string schemaDcTerms = @"http://purl.org/dc/terms/"; | 
 |         internal const string schemaDcmiType = @"http://purl.org/dc/dcmitype/"; | 
 |         internal const string schemaXsi = @"http://www.w3.org/2001/XMLSchema-instance"; | 
 |         internal const string schemaVt = @"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"; | 
 |  | 
 |         //Pivottables | 
 |         internal const string schemaPivotTable = @"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"; | 
 |         internal const string schemaPivotCacheDefinition = @"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"; | 
 |         internal const string schemaPivotCacheRecords = @"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"; | 
 |  | 
 |         //VBA | 
 |         internal const string schemaVBA = @"application/vnd.ms-office.vbaProject"; | 
 |         internal const string schemaVBASignature = @"application/vnd.ms-office.vbaProjectSignature"; | 
 |  | 
 |         internal const string contentTypeWorkbookDefault = @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"; | 
 |         internal const string contentTypeWorkbookMacroEnabled = "application/vnd.ms-excel.sheet.macroEnabled.main+xml"; | 
 |         internal const string contentTypeSharedString = @"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"; | 
 |         //Package reference | 
 |         private Packaging.ZipPackage _package; | 
 | 		internal ExcelWorkbook _workbook; | 
 |         /// <summary> | 
 |         /// Maximum number of columns in a worksheet (16384).  | 
 |         /// </summary> | 
 |         public const int MaxColumns = 16384; | 
 |         /// <summary> | 
 |         /// Maximum number of rows in a worksheet (1048576).  | 
 |         /// </summary> | 
 |         public const int MaxRows = 1048576; | 
 | 		#endregion | 
 |  | 
 | 		#region ExcelPackage Constructors | 
 |         /// <summary> | 
 |         /// Create a new instance of the ExcelPackage. Output is accessed through the Stream property. | 
 |         /// </summary> | 
 |         public ExcelPackage() | 
 |         { | 
 |             Init(); | 
 |             ConstructNewFile(null); | 
 |         } | 
 |         /// <summary> | 
 | 		/// Create a new instance of the ExcelPackage class based on a existing file or creates a new file.  | 
 | 		/// </summary> | 
 | 		/// <param name="newFile">If newFile exists, it is opened.  Otherwise it is created from scratch.</param> | 
 |         public ExcelPackage(FileInfo newFile) | 
 | 		{ | 
 |             Init(); | 
 |             File = newFile; | 
 |             ConstructNewFile(null); | 
 |         } | 
 |         /// <summary> | 
 |         /// Create a new instance of the ExcelPackage class based on a existing file or creates a new file.  | 
 |         /// </summary> | 
 |         /// <param name="newFile">If newFile exists, it is opened.  Otherwise it is created from scratch.</param> | 
 |         /// <param name="password">Password for an encrypted package</param> | 
 |         public ExcelPackage(FileInfo newFile, string password) | 
 |         { | 
 |             Init(); | 
 |             File = newFile; | 
 |             ConstructNewFile(password); | 
 |         } | 
 | 		/// <summary> | 
 | 		/// Create a new instance of the ExcelPackage class based on a existing template. | 
 | 		/// If newFile exists, it will be overwritten when the Save method is called | 
 | 		/// </summary> | 
 | 		/// <param name="newFile">The name of the Excel file to be created</param> | 
 | 		/// <param name="template">The name of the Excel template to use as the basis of the new Excel file</param> | 
 | 		public ExcelPackage(FileInfo newFile, FileInfo template) | 
 | 		{ | 
 |             Init(); | 
 |             File = newFile; | 
 |             CreateFromTemplate(template, null); | 
 | 		} | 
 |         /// <summary> | 
 |         /// Create a new instance of the ExcelPackage class based on a existing template. | 
 |         /// If newFile exists, it will be overwritten when the Save method is called | 
 |         /// </summary> | 
 |         /// <param name="newFile">The name of the Excel file to be created</param> | 
 |         /// <param name="template">The name of the Excel template to use as the basis of the new Excel file</param> | 
 |         /// <param name="password">Password to decrypted the template</param> | 
 |         public ExcelPackage(FileInfo newFile, FileInfo template, string password) | 
 |         { | 
 |             Init(); | 
 |             File = newFile; | 
 |             CreateFromTemplate(template, password); | 
 |         } | 
 |         /// <summary> | 
 |         /// Create a new instance of the ExcelPackage class based on a existing template. | 
 |         /// </summary> | 
 |         /// <param name="template">The name of the Excel template to use as the basis of the new Excel file</param> | 
 |         /// <param name="useStream">if true use a stream. If false create a file in the temp dir with a random name</param> | 
 |         public ExcelPackage(FileInfo template, bool useStream) | 
 |         { | 
 |             Init(); | 
 |             CreateFromTemplate(template, null); | 
 |             if (useStream == false) | 
 |             { | 
 |                 File = new FileInfo(Path.GetTempPath() + Guid.NewGuid().ToString() + ".xlsx"); | 
 |             } | 
 |         } | 
 |         /// <summary> | 
 |         /// Create a new instance of the ExcelPackage class based on a existing template. | 
 |         /// </summary> | 
 |         /// <param name="template">The name of the Excel template to use as the basis of the new Excel file</param> | 
 |         /// <param name="useStream">if true use a stream. If false create a file in the temp dir with a random name</param> | 
 |         /// <param name="password">Password to decrypted the template</param> | 
 |         public ExcelPackage(FileInfo template, bool useStream, string password) | 
 |         { | 
 |             Init(); | 
 |             CreateFromTemplate(template, password); | 
 |             if (useStream == false) | 
 |             { | 
 |                 File = new FileInfo(Path.GetTempPath() + Guid.NewGuid().ToString() + ".xlsx"); | 
 |             } | 
 |         } | 
 |         /// <summary> | 
 |         /// Create a new instance of the ExcelPackage class based on a stream | 
 |         /// </summary> | 
 |         /// <param name="newStream">The stream object can be empty or contain a package. The stream must be Read/Write</param> | 
 |         public ExcelPackage(Stream newStream)  | 
 |         { | 
 |             Init(); | 
 |             if (newStream.Length == 0) | 
 |             { | 
 |                 _stream = newStream; | 
 |                 _isExternalStream = true; | 
 |                 ConstructNewFile(null); | 
 |             } | 
 |             else | 
 |             {                 | 
 |                 Load(newStream); | 
 |             } | 
 |         } | 
 |         /// <summary> | 
 |         /// Create a new instance of the ExcelPackage class based on a stream | 
 |         /// </summary> | 
 |         /// <param name="newStream">The stream object can be empty or contain a package. The stream must be Read/Write</param> | 
 |         /// <param name="Password">The password to decrypt the document</param> | 
 |         public ExcelPackage(Stream newStream, string Password) | 
 |         { | 
 |             if (!(newStream.CanRead && newStream.CanWrite)) | 
 |             { | 
 |                 throw new Exception("The stream must be read/write"); | 
 |             } | 
 |  | 
 |             Init(); | 
 |             if (newStream.Length > 0) | 
 |             { | 
 |                 Load(newStream,Password); | 
 |             } | 
 |             else | 
 |             { | 
 |                 _stream = newStream; | 
 |                 _isExternalStream = true; | 
 |                 //_package = Package.Open(_stream, FileMode.Create, FileAccess.ReadWrite); TODO:Remove | 
 |                 _package = new Packaging.ZipPackage(_stream); | 
 |                 CreateBlankWb(); | 
 |             } | 
 |         } | 
 |         /// <summary> | 
 |         /// Create a new instance of the ExcelPackage class based on a stream | 
 |         /// </summary> | 
 |         /// <param name="newStream">The output stream. Must be an empty read/write stream.</param> | 
 |         /// <param name="templateStream">This stream is copied to the output stream at load</param> | 
 |         public ExcelPackage(Stream newStream, Stream templateStream) | 
 |         { | 
 |             if (newStream.Length > 0) | 
 |             { | 
 |                 throw(new Exception("The output stream must be empty. Length > 0")); | 
 |             } | 
 |             else if (!(newStream.CanRead && newStream.CanWrite)) | 
 |             { | 
 |                 throw new Exception("The stream must be read/write"); | 
 |             } | 
 |             Init(); | 
 |             Load(templateStream, newStream, null); | 
 |         } | 
 |         /// <summary> | 
 |         /// Create a new instance of the ExcelPackage class based on a stream | 
 |         /// </summary> | 
 |         /// <param name="newStream">The output stream. Must be an empty read/write stream.</param> | 
 |         /// <param name="templateStream">This stream is copied to the output stream at load</param> | 
 |         /// <param name="Password">Password to decrypted the template</param> | 
 |         public ExcelPackage(Stream newStream, Stream templateStream, string Password) | 
 |         { | 
 |             if (newStream.Length > 0) | 
 |             { | 
 |                 throw (new Exception("The output stream must be empty. Length > 0")); | 
 |             } | 
 |             else if (!(newStream.CanRead && newStream.CanWrite)) | 
 |             { | 
 |                 throw new Exception("The stream must be read/write"); | 
 |             } | 
 |             Init(); | 
 |             Load(templateStream, newStream, Password); | 
 |         } | 
 |         #endregion | 
 |         internal ImageInfo AddImage(byte[] image) | 
 |         { | 
 |             return AddImage(image, null, ""); | 
 |         } | 
 |         internal ImageInfo AddImage(byte[] image, Uri uri, string contentType) | 
 |         { | 
 |             var hashProvider = new SHA1CryptoServiceProvider(); | 
 |             var hash = BitConverter.ToString(hashProvider.ComputeHash(image)).Replace("-",""); | 
 |             lock (_images) | 
 |             { | 
 |                 if (_images.ContainsKey(hash)) | 
 |                 { | 
 |                     _images[hash].RefCount++; | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     Packaging.ZipPackagePart imagePart; | 
 |                     if (uri == null) | 
 |                     { | 
 |                         uri = GetNewUri(Package, "/xl/media/image{0}.jpg"); | 
 |                         imagePart = Package.CreatePart(uri, "image/jpeg", CompressionLevel.None); | 
 |                     } | 
 |                     else | 
 |                     { | 
 |                         imagePart = Package.CreatePart(uri, contentType, CompressionLevel.None); | 
 |                     } | 
 |                     var stream = imagePart.GetStream(FileMode.Create, FileAccess.Write); | 
 |                     stream.Write(image, 0, image.GetLength(0)); | 
 |  | 
 |                     _images.Add(hash, new ImageInfo() { Uri = uri, RefCount = 1, Hash = hash, Part = imagePart }); | 
 |                 } | 
 |             } | 
 |             return _images[hash]; | 
 |         } | 
 |         internal ImageInfo LoadImage(byte[] image, Uri uri, Packaging.ZipPackagePart imagePart) | 
 |         { | 
 |             var hashProvider = new SHA1CryptoServiceProvider(); | 
 |             var hash = BitConverter.ToString(hashProvider.ComputeHash(image)).Replace("-", ""); | 
 |             if (_images.ContainsKey(hash)) | 
 |             { | 
 |                 _images[hash].RefCount++; | 
 |             } | 
 |             else | 
 |             { | 
 |                 _images.Add(hash, new ImageInfo() { Uri = uri, RefCount = 1, Hash = hash, Part = imagePart }); | 
 |             } | 
 |             return _images[hash]; | 
 |         } | 
 |         internal void RemoveImage(string hash) | 
 |         { | 
 |             lock (_images) | 
 |             { | 
 |                 if (_images.ContainsKey(hash)) | 
 |                 { | 
 |                     var ii = _images[hash]; | 
 |                     ii.RefCount--; | 
 |                     if (ii.RefCount == 0) | 
 |                     { | 
 |                         Package.DeletePart(ii.Uri); | 
 |                         _images.Remove(hash); | 
 |                     } | 
 |                 } | 
 |             } | 
 |         } | 
 |         internal ImageInfo GetImageInfo(byte[] image) | 
 |         { | 
 |             var hashProvider = new SHA1CryptoServiceProvider(); | 
 |             var hash = BitConverter.ToString(hashProvider.ComputeHash(image)).Replace("-",""); | 
 |  | 
 |             if (_images.ContainsKey(hash)) | 
 |             { | 
 |                 return _images[hash]; | 
 |             } | 
 |             else | 
 |             { | 
 |                 return null; | 
 |             } | 
 |         } | 
 |         private Uri GetNewUri(Packaging.ZipPackage package, string sUri) | 
 |         { | 
 |             int id = 1; | 
 |             Uri uri; | 
 |             do | 
 |             { | 
 |                 uri = new Uri(string.Format(sUri, id++), UriKind.Relative); | 
 |             } | 
 |             while (package.PartExists(uri)); | 
 |             return uri; | 
 |         } | 
 |         /// <summary> | 
 |         /// Init values here | 
 |         /// </summary> | 
 |         private void Init() | 
 |         { | 
 |             DoAdjustDrawings = true; | 
 |         } | 
 |         /// <summary> | 
 |         /// Create a new file from a template | 
 |         /// </summary> | 
 |         /// <param name="template">An existing xlsx file to use as a template</param> | 
 |         /// <param name="password">The password to decrypt the package.</param> | 
 |         /// <returns></returns> | 
 |         private void CreateFromTemplate(FileInfo template, string password) | 
 |         { | 
 |             if (template != null) template.Refresh(); | 
 |             if (template.Exists) | 
 |             { | 
 |                 if(_stream==null) _stream=new MemoryStream(); | 
 |                 var ms = new MemoryStream(); | 
 |                 if (password != null) | 
 |                 { | 
 | #if !MONO | 
 |                     Encryption.IsEncrypted = true; | 
 |                     Encryption.Password = password; | 
 |                     var encrHandler = new EncryptedPackageHandler(); | 
 |                     ms = encrHandler.DecryptPackage(template, Encryption); | 
 |                     encrHandler = null; | 
 | #endif | 
 | #if MONO | 
 | 	                throw (new NotImplementedException("No support for Encrypted packages in Mono")); | 
 | #endif | 
 | 	                //throw (new NotImplementedException("No support for Encrypted packages in this version")); | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     byte[] b = System.IO.File.ReadAllBytes(template.FullName); | 
 |                     ms.Write(b, 0, b.Length); | 
 |                 } | 
 |                 try | 
 |                 { | 
 |                     //_package = Package.Open(_stream, FileMode.Open, FileAccess.ReadWrite); | 
 |                     _package = new Packaging.ZipPackage(ms); | 
 |                 } | 
 |                 catch (Exception ex) | 
 |                 { | 
 | #if !MONO | 
 |                     if (password == null && CompoundDocument.IsStorageFile(template.FullName)==0) | 
 |                     { | 
 |                         throw new Exception("Can not open the package. Package is an OLE compound document. If this is an encrypted package, please supply the password", ex); | 
 |                     } | 
 |                     else | 
 |                     { | 
 |                         throw; | 
 |                     } | 
 | #endif | 
 | #if MONO | 
 |                     throw; | 
 | #endif | 
 |                 } | 
 |             } | 
 |             else | 
 |                 throw new Exception("Passed invalid TemplatePath to Excel Template"); | 
 |             //return newFile; | 
 |         } | 
 |         private void ConstructNewFile(string password) | 
 |         { | 
 |             var ms = new MemoryStream(); | 
 |             if (_stream == null) _stream = new MemoryStream(); | 
 |             if (File != null) File.Refresh(); | 
 |             if (File != null && File.Exists) | 
 |             { | 
 |                 if (password != null) | 
 |                 { | 
 | #if !MONO | 
 |                     var encrHandler = new EncryptedPackageHandler(); | 
 |                     Encryption.IsEncrypted = true; | 
 |                     Encryption.Password = password; | 
 |                     ms = encrHandler.DecryptPackage(File, Encryption); | 
 |                     encrHandler = null; | 
 | #endif | 
 | #if MONO | 
 |                     throw new NotImplementedException("No support for Encrypted packages in Mono"); | 
 | #endif | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     byte[] b = System.IO.File.ReadAllBytes(File.FullName); | 
 |                     ms.Write(b, 0, b.Length); | 
 |                 } | 
 |                 try | 
 |                 { | 
 |                     //_package = Package.Open(_stream, FileMode.Open, FileAccess.ReadWrite); | 
 |                     _package = new Packaging.ZipPackage(ms); | 
 |                 } | 
 |                 catch (Exception ex) | 
 |                { | 
 | #if !MONO | 
 |                     if (password == null && CompoundDocument.IsStorageFile(File.FullName)==0) | 
 |                     { | 
 |                         throw new Exception("Can not open the package. Package is an OLE compound document. If this is an encrypted package, please supply the password", ex); | 
 |                     } | 
 |                     else | 
 |                     { | 
 |                         throw; | 
 |                     } | 
 | #endif | 
 | #if MONO | 
 |                     throw; | 
 | #endif | 
 |                 } | 
 |             } | 
 |             else | 
 |             { | 
 |                 //_package = Package.Open(_stream, FileMode.Create, FileAccess.ReadWrite); | 
 |                 _package = new Packaging.ZipPackage(ms); | 
 |                 CreateBlankWb(); | 
 |             } | 
 |         } | 
 |  | 
 |         private void CreateBlankWb() | 
 |         { | 
 |             XmlDocument workbook = Workbook.WorkbookXml; // this will create the workbook xml in the package | 
 |             // create the relationship to the main part | 
 |             _package.CreateRelationship(UriHelper.GetRelativeUri(new Uri("/xl", UriKind.Relative), Workbook.WorkbookUri), Packaging.TargetMode.Internal, schemaRelationships + "/officeDocument"); | 
 |         } | 
 |  | 
 | 		/// <summary> | 
 | 		/// Returns a reference to the package | 
 | 		/// </summary> | 
 | 		public Packaging.ZipPackage Package { get { return (_package); } } | 
 |         ExcelEncryption _encryption=null; | 
 |         /// <summary> | 
 |         /// Information how and if the package is encrypted | 
 |         /// </summary> | 
 |         public ExcelEncryption Encryption | 
 |         { | 
 |             get | 
 |             { | 
 |                 if (_encryption == null) | 
 |                 { | 
 |                     _encryption = new ExcelEncryption(); | 
 |                 } | 
 |                 return _encryption; | 
 |             } | 
 |         } | 
 | 		/// <summary> | 
 | 		/// Returns a reference to the workbook component within the package. | 
 | 		/// All worksheets and cells can be accessed through the workbook. | 
 | 		/// </summary> | 
 | 		public ExcelWorkbook Workbook | 
 | 		{ | 
 | 			get | 
 | 			{ | 
 |                 if (_workbook == null) | 
 |                 { | 
 |                     var nsm = CreateDefaultNSM(); | 
 |  | 
 |                     _workbook = new ExcelWorkbook(this, nsm); | 
 |  | 
 |                     _workbook.GetExternalReferences(); | 
 |                     _workbook.GetDefinedNames(); | 
 |  | 
 |                 } | 
 |                 return (_workbook); | 
 | 			} | 
 | 		} | 
 |         /// <summary> | 
 |         /// Automaticlly adjust drawing size when column width/row height are adjusted, depending on the drawings editBy property. | 
 |         /// Default True | 
 |         /// </summary> | 
 |         public bool DoAdjustDrawings | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |         private XmlNamespaceManager CreateDefaultNSM() | 
 |         { | 
 |             //  Create a NamespaceManager to handle the default namespace,  | 
 |             //  and create a prefix for the default namespace: | 
 |             NameTable nt = new NameTable(); | 
 |             var ns = new XmlNamespaceManager(nt); | 
 |             ns.AddNamespace(string.Empty, ExcelPackage.schemaMain); | 
 |             ns.AddNamespace("d", ExcelPackage.schemaMain); | 
 |             ns.AddNamespace("r", ExcelPackage.schemaRelationships); | 
 |             ns.AddNamespace("c", ExcelPackage.schemaChart); | 
 |             ns.AddNamespace("vt", schemaVt); | 
 |             // extended properties (app.xml) | 
 |             ns.AddNamespace("xp", schemaExtended); | 
 |             // custom properties | 
 |             ns.AddNamespace("ctp", schemaCustom); | 
 |             // core properties | 
 |             ns.AddNamespace("cp", schemaCore); | 
 |             // core property namespaces  | 
 |             ns.AddNamespace("dc", schemaDc); | 
 |             ns.AddNamespace("dcterms", schemaDcTerms); | 
 |             ns.AddNamespace("dcmitype", schemaDcmiType); | 
 |             ns.AddNamespace("xsi", schemaXsi); | 
 |             return ns; | 
 |         } | 
 | 		 | 
 | 		#region SavePart | 
 | 		/// <summary> | 
 | 		/// Saves the XmlDocument into the package at the specified Uri. | 
 | 		/// </summary> | 
 | 		/// <param name="uri">The Uri of the component</param> | 
 | 		/// <param name="xmlDoc">The XmlDocument to save</param> | 
 | 		internal void SavePart(Uri uri, XmlDocument xmlDoc) | 
 | 		{ | 
 |             Packaging.ZipPackagePart part = _package.GetPart(uri); | 
 | 			xmlDoc.Save(part.GetStream(FileMode.Create, FileAccess.Write)); | 
 | 		} | 
 |         /// <summary> | 
 | 		/// Saves the XmlDocument into the package at the specified Uri. | 
 | 		/// </summary> | 
 | 		/// <param name="uri">The Uri of the component</param> | 
 | 		/// <param name="xmlDoc">The XmlDocument to save</param> | 
 |         internal void SaveWorkbook(Uri uri, XmlDocument xmlDoc) | 
 | 		{ | 
 |             Packaging.ZipPackagePart part = _package.GetPart(uri); | 
 |             if(Workbook.VbaProject==null) | 
 |             { | 
 |                 if (part.ContentType != contentTypeWorkbookDefault) | 
 |                 { | 
 |                     part = _package.CreatePart(uri, contentTypeWorkbookDefault, Compression); | 
 |                 } | 
 |             } | 
 |             else | 
 |             { | 
 |                 if (part.ContentType != contentTypeWorkbookMacroEnabled) | 
 |                 { | 
 |                     var rels = part.GetRelationships(); | 
 |                     _package.DeletePart(uri); | 
 |                     part = Package.CreatePart(uri, contentTypeWorkbookMacroEnabled); | 
 |                     foreach (var rel in rels) | 
 |                     { | 
 |                         Package.DeleteRelationship(rel.Id); | 
 |                         part.CreateRelationship(rel.TargetUri, rel.TargetMode, rel.RelationshipType); | 
 |                     } | 
 |                 } | 
 |             } | 
 | 			xmlDoc.Save(part.GetStream(FileMode.Create, FileAccess.Write)); | 
 | 		} | 
 |  | 
 |         #endregion | 
 |  | 
 | 		#region Dispose | 
 | 		/// <summary> | 
 | 		/// Closes the package. | 
 | 		/// </summary> | 
 | 		public void Dispose() | 
 | 		{ | 
 |             if(_package != null) | 
 |             { | 
 |                 if (_isExternalStream==false && Stream != null && (Stream.CanRead || Stream.CanWrite)) | 
 |                 { | 
 |                     Stream.Close(); | 
 |                 } | 
 |                 _package.Close(); | 
 |                 if(_isExternalStream==false) ((IDisposable)_stream).Dispose(); | 
 |                 if(_workbook != null) | 
 |                 { | 
 |                     _workbook.Dispose(); | 
 |                 } | 
 |                 _package = null; | 
 |                 _images = null; | 
 |                 _file = null; | 
 |                 _workbook = null; | 
 |                 _stream = null; | 
 |                 _workbook = null; | 
 |             } | 
 | 		} | 
 | 		#endregion | 
 |  | 
 | 		#region Save  // ExcelPackage save | 
 |         /// <summary> | 
 |         /// Saves all the components back into the package. | 
 |         /// This method recursively calls the Save method on all sub-components. | 
 |         /// We close the package after the save is done. | 
 |         /// </summary> | 
 |         public void Save() | 
 |         { | 
 |             try | 
 |             { | 
 |                 Workbook.Save(); | 
 |                 if (File == null) | 
 |                 { | 
 |                     if(Encryption.IsEncrypted) | 
 |                     { | 
 | #if !MONO | 
 |                         var ms = new MemoryStream(); | 
 |                         _package.Save(ms); | 
 |                         byte[] file = ms.ToArray(); | 
 |                         EncryptedPackageHandler eph = new EncryptedPackageHandler(); | 
 |                         var msEnc = eph.EncryptPackage(file, Encryption); | 
 |                         CopyStream(msEnc, ref _stream); | 
 | #endif | 
 | #if MONO | 
 |                         throw new NotSupportedException("Encryption is not supported under Mono."); | 
 | #endif | 
 |                     } | 
 |                     else | 
 |                     { | 
 |                         _package.Save(_stream); | 
 |                     } | 
 |                     _stream.Flush(); | 
 |                     _package.Close(); | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     if (System.IO.File.Exists(File.FullName)) | 
 |                     { | 
 |                         try | 
 |                         { | 
 |                             System.IO.File.Delete(File.FullName); | 
 |                         } | 
 |                         catch (Exception ex) | 
 |                         { | 
 |                             throw (new Exception(string.Format("Error overwriting file {0}", File.FullName), ex)); | 
 |                         } | 
 |                     } | 
 |  | 
 |                     _package.Save(_stream); | 
 |                     _package.Close(); | 
 |                     if (Stream is MemoryStream) | 
 |                     { | 
 |                         var fi = new FileStream(File.FullName, FileMode.Create); | 
 |                         //EncryptPackage | 
 |                         if (Encryption.IsEncrypted) | 
 |                         { | 
 | #if !MONO | 
 |                             byte[] file = ((MemoryStream)Stream).ToArray(); | 
 |                             EncryptedPackageHandler eph = new EncryptedPackageHandler(); | 
 |                             var ms = eph.EncryptPackage(file, Encryption); | 
 |  | 
 |                             fi.Write(ms.GetBuffer(), 0, (int)ms.Length); | 
 | #endif | 
 | #if MONO | 
 |                             throw new NotSupportedException("Encryption is not supported under Mono."); | 
 | #endif | 
 |                         } | 
 |                         else | 
 |                         {                             | 
 |                             fi.Write(((MemoryStream)Stream).GetBuffer(), 0, (int)Stream.Length); | 
 |                         } | 
 |                         fi.Close(); | 
 |                     } | 
 |                     else | 
 |                     { | 
 |                         System.IO.File.WriteAllBytes(File.FullName, GetAsByteArray(false)); | 
 |                     } | 
 |                 } | 
 |             } | 
 |             catch (Exception ex) | 
 |             { | 
 |                 if (File == null) | 
 |                 { | 
 |                     throw; | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     throw (new InvalidOperationException(string.Format("Error saving file {0}", File.FullName), ex)); | 
 |                 } | 
 |             } | 
 |         } | 
 |         /// <summary> | 
 |         /// Saves all the components back into the package. | 
 |         /// This method recursively calls the Save method on all sub-components. | 
 |         /// The package is closed after it ha | 
 |         /// d to encrypt the workbook with.  | 
 |         /// </summary> | 
 |         /// <param name="password">This parameter overrides the Workbook.Encryption.Password.</param> | 
 |         public void Save(string password) | 
 | 		{ | 
 |             Encryption.Password = password; | 
 |             Save(); | 
 |         } | 
 |         /// <summary> | 
 |         /// Saves the workbook to a new file | 
 |         /// The package is closed after it has been saved         | 
 |         /// </summary> | 
 |         /// <param name="file">The file location</param> | 
 |         public void SaveAs(FileInfo file) | 
 |         { | 
 |             File = file; | 
 |             Save(); | 
 |         } | 
 |         /// <summary> | 
 |         /// Saves the workbook to a new file | 
 |         /// The package is closed after it has been saved | 
 |         /// </summary> | 
 |         /// <param name="file">The file</param> | 
 |         /// <param name="password">The password to encrypt the workbook with.  | 
 |         /// This parameter overrides the Encryption.Password.</param> | 
 |         public void SaveAs(FileInfo file, string password) | 
 |         { | 
 |             File = file; | 
 |             Encryption.Password = password; | 
 |             Save(); | 
 |         } | 
 |         /// <summary> | 
 |         /// Copies the Package to the Outstream | 
 |         /// The package is closed after it has been saved | 
 |         /// </summary> | 
 |         /// <param name="OutputStream">The stream to copy the package to</param> | 
 |         public void SaveAs(Stream OutputStream) | 
 |         { | 
 |             File = null; | 
 |             Save(); | 
 |  | 
 |             if (OutputStream != _stream) | 
 |             { | 
 |                 if (Encryption.IsEncrypted) | 
 |                 { | 
 | #if !MONO | 
 |                     //Encrypt Workbook | 
 |                     Byte[] file = new byte[Stream.Length]; | 
 |                     long pos = Stream.Position; | 
 |                     Stream.Seek(0, SeekOrigin.Begin); | 
 |                     Stream.Read(file, 0, (int) Stream.Length); | 
 |                     EncryptedPackageHandler eph = new EncryptedPackageHandler(); | 
 |                     var ms = eph.EncryptPackage(file, Encryption); | 
 |                     CopyStream(ms, ref OutputStream); | 
 | #endif | 
 | #if MONO | 
 |                 throw new NotSupportedException("Encryption is not supported under Mono."); | 
 | #endif | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     CopyStream(_stream, ref OutputStream); | 
 |                 } | 
 |             } | 
 |         } | 
 |         /// <summary> | 
 |         /// Copies the Package to the Outstream | 
 |         /// The package is closed after it has been saved | 
 |         /// </summary> | 
 |         /// <param name="OutputStream">The stream to copy the package to</param> | 
 |         /// <param name="password">The password to encrypt the workbook with.  | 
 |         /// This parameter overrides the Encryption.Password.</param> | 
 |         public void SaveAs(Stream OutputStream, string password) | 
 |         { | 
 |             Encryption.Password = password; | 
 |             SaveAs(OutputStream); | 
 |         } | 
 |         FileInfo _file = null; | 
 |  | 
 |         /// <summary> | 
 |         /// The output file. Null if no file is used | 
 |         /// </summary> | 
 |         public FileInfo File | 
 |         { | 
 |             get | 
 |             { | 
 |                 return _file; | 
 |             } | 
 |             set | 
 |             { | 
 |                 _file = value; | 
 |             } | 
 |         } | 
 |         /// <summary> | 
 |         /// The output stream. This stream is the not the encrypted package. | 
 |         /// To get the encrypted package use the SaveAs(stream) method. | 
 |         /// </summary> | 
 |         public Stream Stream | 
 |         { | 
 |             get | 
 |             { | 
 |                 return _stream; | 
 |             } | 
 |         } | 
 | 		#endregion | 
 |         /// <summary> | 
 |         /// Compression option for the package | 
 |         /// </summary>         | 
 |         public CompressionLevel Compression  | 
 |         {  | 
 |             get | 
 |             { | 
 |                 return Package.Compression; | 
 |             } | 
 |             set | 
 |             { | 
 |                 Package.Compression = value; | 
 |             } | 
 |         } | 
 | 		#region GetXmlFromUri | 
 | 		/// <summary> | 
 | 		/// Get the XmlDocument from an URI | 
 | 		/// </summary> | 
 | 		/// <param name="uri">The Uri to the part</param> | 
 | 		/// <returns>The XmlDocument</returns> | 
 | 		internal XmlDocument GetXmlFromUri(Uri uri) | 
 | 		{ | 
 | 			XmlDocument xml = new XmlDocument(); | 
 | 			Packaging.ZipPackagePart part = _package.GetPart(uri); | 
 |             XmlHelper.LoadXmlSafe(xml, part.GetStream());  | 
 | 			return (xml); | 
 | 		} | 
 | 		#endregion | 
 |  | 
 |         /// <summary> | 
 |         /// Saves and returns the Excel files as a bytearray. | 
 |         /// Note that the package is closed upon save | 
 |         /// </summary> | 
 |         /// <example>       | 
 |         /// Example how to return a document from a Webserver... | 
 |         /// <code>  | 
 |         ///  ExcelPackage package=new ExcelPackage(); | 
 |         ///  /**** ... Create the document ****/ | 
 |         ///  Byte[] bin = package.GetAsByteArray(); | 
 |         ///  Response.ContentType = "Application/vnd.ms-Excel"; | 
 |         ///  Response.AddHeader("content-disposition", "attachment;  filename=TheFile.xlsx"); | 
 | 		///  Response.BinaryWrite(bin); | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// <returns></returns> | 
 |         public byte[] GetAsByteArray() | 
 |         { | 
 |            return GetAsByteArray(true); | 
 |         } | 
 |         /// <summary> | 
 |         /// Saves and returns the Excel files as a bytearray | 
 |         /// Note that the package is closed upon save | 
 |         /// </summary> | 
 |         /// <example>       | 
 |         /// Example how to return a document from a Webserver... | 
 |         /// <code>  | 
 |         ///  ExcelPackage package=new ExcelPackage(); | 
 |         ///  /**** ... Create the document ****/ | 
 |         ///  Byte[] bin = package.GetAsByteArray(); | 
 |         ///  Response.ContentType = "Application/vnd.ms-Excel"; | 
 |         ///  Response.AddHeader("content-disposition", "attachment;  filename=TheFile.xlsx"); | 
 |         ///  Response.BinaryWrite(bin); | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// <param name="password">The password to encrypt the workbook with.  | 
 |         /// This parameter overrides the Encryption.Password.</param> | 
 |         /// <returns></returns> | 
 |         public byte[] GetAsByteArray(string password) | 
 |         { | 
 |             if (password != null) | 
 |             { | 
 |                 Encryption.Password = password; | 
 |             } | 
 |             return GetAsByteArray(true); | 
 |         } | 
 |         internal byte[] GetAsByteArray(bool save) | 
 |         { | 
 |             if (save) | 
 |             { | 
 |                 Workbook.Save(); | 
 |                 _package.Close(); | 
 |                 _package.Save(_stream); | 
 |             } | 
 |             Byte[] byRet = new byte[Stream.Length]; | 
 |             long pos = Stream.Position;             | 
 |             Stream.Seek(0, SeekOrigin.Begin); | 
 |             Stream.Read(byRet, 0, (int)Stream.Length); | 
 |  | 
 |             //Encrypt Workbook? | 
 |             if (Encryption.IsEncrypted) | 
 |             { | 
 | #if !MONO | 
 |                 EncryptedPackageHandler eph=new EncryptedPackageHandler(); | 
 |                 var ms = eph.EncryptPackage(byRet, Encryption); | 
 |                 byRet = ms.ToArray(); | 
 | #endif | 
 |             } | 
 |  | 
 |             Stream.Seek(pos, SeekOrigin.Begin); | 
 |             Stream.Close(); | 
 |             return byRet; | 
 |         } | 
 |         /// <summary> | 
 |         /// Loads the specified package data from a stream. | 
 |         /// </summary> | 
 |         /// <param name="input">The input.</param> | 
 |         public void Load(Stream input) | 
 |         { | 
 |             Load(input, new MemoryStream(), null); | 
 |         } | 
 |         /// <summary> | 
 |         /// Loads the specified package data from a stream. | 
 |         /// </summary> | 
 |         /// <param name="input">The input.</param> | 
 |         /// <param name="Password">The password to decrypt the document</param> | 
 |         public void Load(Stream input, string Password) | 
 |         { | 
 |             Load(input, new MemoryStream(), Password); | 
 |         } | 
 |         /// <summary> | 
 |         ///  | 
 |         /// </summary> | 
 |         /// <param name="input"></param>     | 
 |         /// <param name="output"></param> | 
 |         /// <param name="Password"></param> | 
 |         private void Load(Stream input, Stream output, string Password) | 
 |         { | 
 |             //Release some resources: | 
 |             if (this._package != null) | 
 |             { | 
 |                 this._package.Close(); | 
 |                 this._package = null; | 
 |             } | 
 |             if (this._stream != null) | 
 |             { | 
 |                 this._stream.Close(); | 
 |                 this._stream.Dispose(); | 
 |                 this._stream = null; | 
 |             } | 
 |             _isExternalStream = true; | 
 |             if (input.Length == 0) // Template is blank, Construct new | 
 |             { | 
 |                 _stream = output; | 
 |                 ConstructNewFile(Password); | 
 |             } | 
 |             else | 
 |             { | 
 |                 Stream ms; | 
 |                 this._stream = output; | 
 |                 if (Password != null) | 
 |                 { | 
 | #if !MONO | 
 |                     Stream encrStream = new MemoryStream(); | 
 |                     CopyStream(input, ref encrStream); | 
 |                     EncryptedPackageHandler eph = new EncryptedPackageHandler(); | 
 |                     Encryption.Password = Password; | 
 |                     ms = eph.DecryptPackage((MemoryStream)encrStream, Encryption); | 
 | #endif | 
 | #if MONO | 
 |                     throw new NotSupportedException("Encryption is not supported under Mono."); | 
 | #endif | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     ms = new MemoryStream(); | 
 |                     CopyStream(input, ref ms); | 
 |                 } | 
 |  | 
 |                 try | 
 |                 { | 
 |                     //this._package = Package.Open(this._stream, FileMode.Open, FileAccess.ReadWrite); | 
 |                     _package = new Packaging.ZipPackage(ms); | 
 |                 } | 
 |                 catch (Exception ex) | 
 |                 { | 
 | #if !MONO | 
 |                     EncryptedPackageHandler eph = new EncryptedPackageHandler(); | 
 |                     if (Password == null && CompoundDocument.IsStorageILockBytes(CompoundDocument.GetLockbyte((MemoryStream)_stream)) == 0) | 
 |                     { | 
 |                         throw new Exception("Can not open the package. Package is an OLE compound document. If this is an encrypted package, please supply the password", ex); | 
 |                     } | 
 |                     else | 
 |                     { | 
 |                         throw; | 
 |                     } | 
 | #endif | 
 | #if MONO | 
 |                     throw; | 
 | #endif | 
 |                 } | 
 |             }             | 
 |             //Clear the workbook so that it gets reinitialized next time | 
 |             this._workbook = null; | 
 |         } | 
 |         static object _lock=new object(); | 
 |         /// <summary> | 
 |         /// Copies the input stream to the output stream. | 
 |         /// </summary> | 
 |         /// <param name="inputStream">The input stream.</param> | 
 |         /// <param name="outputStream">The output stream.</param> | 
 |         internal static void CopyStream(Stream inputStream, ref Stream outputStream) | 
 |         { | 
 |             if (!inputStream.CanRead) | 
 |             { | 
 |                 throw (new Exception("Can not read from inputstream")); | 
 |             } | 
 |             if (!outputStream.CanWrite) | 
 |             { | 
 |                 throw (new Exception("Can not write to outputstream")); | 
 |             } | 
 |             if (inputStream.CanSeek) | 
 |             { | 
 |                 inputStream.Seek(0, SeekOrigin.Begin); | 
 |             } | 
 |  | 
 |                 const int bufferLength = 8096; | 
 |                 var buffer = new Byte[bufferLength]; | 
 |                 lock (_lock) | 
 |                 { | 
 |                     int bytesRead = inputStream.Read(buffer, 0, bufferLength); | 
 |                     // write the required bytes | 
 |                     while (bytesRead > 0) | 
 |                     { | 
 |                         outputStream.Write(buffer, 0, bytesRead); | 
 |                         bytesRead = inputStream.Read(buffer, 0, bufferLength); | 
 |                     } | 
 |                     outputStream.Flush(); | 
 |             } | 
 |         } | 
 |     } | 
 | } |