Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Async/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/3.1.3/EPPlus-3.1.3/ExcelPackage.cs @ 11642

Last change on this file since 11642 was 9580, checked in by sforsten, 11 years ago

#1730:

  • added SymbolicDataAnalysisExpressionExcelFormatter
  • changed modifiers in SymbolicExpressionTreeChart of methods SaveImageAsBitmap and SaveImageAsEmf to public
  • added menu item ExportSymbolicSolutionToExcelMenuItem to export a symbolic solution to an excel file
  • added EPPlus-3.1.3 to ExtLibs
File size: 43.0 KB
Line 
1/*******************************************************************************
2 * You may amend and distribute as you like, but don't remove this header!
3 *
4 * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
5 * See http://www.codeplex.com/EPPlus for details.
6 *
7 * Copyright (C) 2011  Jan Källman
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
17 * See the GNU Lesser General Public License for more details.
18 *
19 * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
20 * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
21 *
22 * All code and executables are provided "as is" with no warranty either express or implied.
23 * The author accepts no liability for any damage or loss of business that this product may cause.
24 *
25 * Code change notes:
26 *
27 * Author             Change            Date
28 * ******************************************************************************
29 * Jan Källman                    Initial Release           2009-10-01
30 * Starnuto Di Topo & Jan Källman   Added stream constructors
31 *                                  and Load method Save as
32 *                                  stream                      2010-03-14
33 * Jan Källman    License changed GPL-->LGPL 2011-12-27
34 *******************************************************************************/
35using System;
36using System.Xml;
37using System.IO;
38using System.IO.Packaging;
39using System.Collections.Generic;
40using System.Security.Cryptography;
41using OfficeOpenXml.Drawing;
42using OfficeOpenXml.Utils;
43namespace OfficeOpenXml
44{
45    /// <summary>
46    /// Represents an Excel 2007/2010 XLSX file package. 
47    /// This is the top-level object to access all parts of the document.
48    /// <code>
49  ///     FileInfo newFile = new FileInfo(outputDir.FullName + @"\sample1.xlsx");
50  ///   if (newFile.Exists)
51  ///   {
52  ///     newFile.Delete();  // ensures we create a new workbook
53  ///     newFile = new FileInfo(outputDir.FullName + @"\sample1.xlsx");
54  ///   }
55  ///   using (ExcelPackage package = new ExcelPackage(newFile))
56    ///     {
57    ///         // add a new worksheet to the empty workbook
58    ///         ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Inventory");
59    ///         //Add the headers
60    ///         worksheet.Cells[1, 1].Value = "ID";
61    ///         worksheet.Cells[1, 2].Value = "Product";
62    ///         worksheet.Cells[1, 3].Value = "Quantity";
63    ///         worksheet.Cells[1, 4].Value = "Price";
64    ///         worksheet.Cells[1, 5].Value = "Value";
65    ///
66    ///         //Add some items...
67    ///         worksheet.Cells["A2"].Value = "12001";
68    ///         worksheet.Cells["B2"].Value = "Nails";
69    ///         worksheet.Cells["C2"].Value = 37;
70    ///         worksheet.Cells["D2"].Value = 3.99;
71    ///
72    ///         worksheet.Cells["A3"].Value = "12002";
73    ///         worksheet.Cells["B3"].Value = "Hammer";
74    ///         worksheet.Cells["C3"].Value = 5;
75    ///         worksheet.Cells["D3"].Value = 12.10;
76    ///
77    ///         worksheet.Cells["A4"].Value = "12003";
78    ///         worksheet.Cells["B4"].Value = "Saw";
79    ///         worksheet.Cells["C4"].Value = 12;
80    ///         worksheet.Cells["D4"].Value = 15.37;
81    ///
82    ///         //Add a formula for the value-column
83    ///         worksheet.Cells["E2:E4"].Formula = "C2*D2";
84    ///
85    ///            //Ok now format the values;
86    ///         using (var range = worksheet.Cells[1, 1, 1, 5])
87    ///          {
88    ///             range.Style.Font.Bold = true;
89    ///             range.Style.Fill.PatternType = ExcelFillStyle.Solid;
90    ///             range.Style.Fill.BackgroundColor.SetColor(Color.DarkBlue);
91    ///             range.Style.Font.Color.SetColor(Color.White);
92    ///         }
93    ///
94    ///         worksheet.Cells["A5:E5"].Style.Border.Top.Style = ExcelBorderStyle.Thin;
95    ///         worksheet.Cells["A5:E5"].Style.Font.Bold = true;
96    ///
97    ///         worksheet.Cells[5, 3, 5, 5].Formula = string.Format("SUBTOTAL(9,{0})", new ExcelAddress(2,3,4,3).Address);
98    ///         worksheet.Cells["C2:C5"].Style.Numberformat.Format = "#,##0";
99    ///         worksheet.Cells["D2:E5"].Style.Numberformat.Format = "#,##0.00";
100    ///
101    ///         //Create an autofilter for the range
102    ///         worksheet.Cells["A1:E4"].AutoFilter = true;
103    ///
104    ///         worksheet.Cells["A1:E5"].AutoFitColumns(0);
105    ///
106    ///         // lets set the header text
107    ///         worksheet.HeaderFooter.oddHeader.CenteredText = "&amp;24&amp;U&amp;\"Arial,Regular Bold\" Inventory";
108    ///         // add the page number to the footer plus the total number of pages
109    ///         worksheet.HeaderFooter.oddFooter.RightAlignedText =
110    ///         string.Format("Page {0} of {1}", ExcelHeaderFooter.PageNumber, ExcelHeaderFooter.NumberOfPages);
111    ///         // add the sheet name to the footer
112    ///         worksheet.HeaderFooter.oddFooter.CenteredText = ExcelHeaderFooter.SheetName;
113    ///         // add the file path to the footer
114    ///         worksheet.HeaderFooter.oddFooter.LeftAlignedText = ExcelHeaderFooter.FilePath + ExcelHeaderFooter.FileName;
115    ///
116    ///         worksheet.PrinterSettings.RepeatRows = worksheet.Cells["1:2"];
117    ///         worksheet.PrinterSettings.RepeatColumns = worksheet.Cells["A:G"];
118    ///
119    ///          // Change the sheet view to show it in page layout mode
120    ///           worksheet.View.PageLayoutView = true;
121    ///
122    ///         // set some document properties
123    ///         package.Workbook.Properties.Title = "Invertory";
124    ///         package.Workbook.Properties.Author = "Jan Källman";
125    ///         package.Workbook.Properties.Comments = "This sample demonstrates how to create an Excel 2007 workbook using EPPlus";
126    ///
127    ///         // set some extended property values
128    ///         package.Workbook.Properties.Company = "AdventureWorks Inc.";
129    ///
130    ///         // set some custom property values
131    ///         package.Workbook.Properties.SetCustomPropertyValue("Checked by", "Jan Källman");
132    ///         package.Workbook.Properties.SetCustomPropertyValue("AssemblyName", "EPPlus");
133    ///
134    ///         // save our new workbook and we are done!
135    ///         package.Save();
136    ///
137    ///       }
138    ///
139    ///       return newFile.FullName;
140    /// </code>
141    /// More samples can be found at  <a href="http://epplus.codeplex.com/">http://epplus.codeplex.com/</a>
142    /// </summary>
143  public sealed class ExcelPackage : IDisposable
144  {
145        internal const bool preserveWhitespace=false;
146        Stream _stream = null;
147        internal class ImageInfo
148        {
149            internal string Hash { get; set; }
150            internal Uri Uri{get;set;}
151            internal int RefCount { get; set; }
152            internal PackagePart Part { get; set; }
153        }
154        internal Dictionary<string, ImageInfo> _images = new Dictionary<string, ImageInfo>();
155    #region Properties
156    /// <summary>
157    /// Main Xml schema name
158    /// </summary>
159    internal const string schemaMain = @"http://schemas.openxmlformats.org/spreadsheetml/2006/main";
160    /// <summary>
161    /// Relationship schema name
162    /// </summary>
163    internal const string schemaRelationships = @"http://schemas.openxmlformats.org/officeDocument/2006/relationships";
164                                                                             
165        internal const string schemaDrawings = @"http://schemas.openxmlformats.org/drawingml/2006/main";
166        internal const string schemaSheetDrawings = @"http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing";
167       
168        internal const string schemaMicrosoftVml = @"urn:schemas-microsoft-com:vml";
169        internal const string schemaMicrosoftOffice = "urn:schemas-microsoft-com:office:office";
170        internal const string schemaMicrosoftExcel = "urn:schemas-microsoft-com:office:excel";
171
172        internal const string schemaChart = @"http://schemas.openxmlformats.org/drawingml/2006/chart";                                                       
173        internal const string schemaHyperlink = @"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
174        internal const string schemaComment = @"http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
175        internal const string schemaImage = @"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
176        //Office properties
177        internal const string schemaCore = @"http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
178        internal const string schemaExtended = @"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
179        internal const string schemaCustom = @"http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
180        internal const string schemaDc = @"http://purl.org/dc/elements/1.1/";
181        internal const string schemaDcTerms = @"http://purl.org/dc/terms/";
182        internal const string schemaDcmiType = @"http://purl.org/dc/dcmitype/";
183        internal const string schemaXsi = @"http://www.w3.org/2001/XMLSchema-instance";
184        internal const string schemaVt = @"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes";
185
186        //Pivottables
187        internal const string schemaPivotTable = @"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml";
188        internal const string schemaPivotCacheDefinition = @"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml";
189        internal const string schemaPivotCacheRecords = @"application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml";
190
191        //VBA
192        internal const string schemaVBA = @"application/vnd.ms-office.vbaProject";
193        internal const string schemaVBASignature = @"application/vnd.ms-office.vbaProjectSignature";
194
195        internal const string contentTypeWorkbookDefault = @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
196        internal const string contentTypeWorkbookMacroEnabled = "application/vnd.ms-excel.sheet.macroEnabled.main+xml";
197        //Package reference
198        private Package _package;
199    private ExcelWorkbook _workbook;
200        /// <summary>
201        /// Maximum number of columns in a worksheet (16384).
202        /// </summary>
203        public const int MaxColumns = 16384;
204        /// <summary>
205        /// Maximum number of rows in a worksheet (1048576).
206        /// </summary>
207        public const int MaxRows = 1048576;
208    #endregion
209
210    #region ExcelPackage Constructors
211        /// <summary>
212        /// Create a new instance of the ExcelPackage. Output is accessed through the Stream property.
213        /// </summary>
214        public ExcelPackage()
215        {
216            Init();
217            ConstructNewFile(new MemoryStream(), null);
218        }
219        /// <summary>
220    /// Create a new instance of the ExcelPackage class based on a existing file or creates a new file.
221    /// </summary>
222    /// <param name="newFile">If newFile exists, it is opened.  Otherwise it is created from scratch.</param>
223        public ExcelPackage(FileInfo newFile)
224    {
225            Init();
226            File = newFile;
227            ConstructNewFile(new MemoryStream(), null);
228        }
229        /// <summary>
230        /// Create a new instance of the ExcelPackage class based on a existing file or creates a new file.
231        /// </summary>
232        /// <param name="newFile">If newFile exists, it is opened.  Otherwise it is created from scratch.</param>
233        /// <param name="password">Password for an encrypted package</param>
234        public ExcelPackage(FileInfo newFile, string password)
235        {
236            Init();
237            File = newFile;
238            ConstructNewFile(new MemoryStream(), password);
239        }
240    /// <summary>
241    /// Create a new instance of the ExcelPackage class based on a existing template.
242    /// If newFile exists, it will be overwritten when the Save method is called
243    /// </summary>
244    /// <param name="newFile">The name of the Excel file to be created</param>
245    /// <param name="template">The name of the Excel template to use as the basis of the new Excel file</param>
246    public ExcelPackage(FileInfo newFile, FileInfo template)
247    {
248            Init();
249            File = newFile;
250            CreateFromTemplate(template, null);
251    }
252        /// <summary>
253        /// Create a new instance of the ExcelPackage class based on a existing template.
254        /// If newFile exists, it will be overwritten when the Save method is called
255        /// </summary>
256        /// <param name="newFile">The name of the Excel file to be created</param>
257        /// <param name="template">The name of the Excel template to use as the basis of the new Excel file</param>
258        /// <param name="password">Password to decrypted the template</param>
259        public ExcelPackage(FileInfo newFile, FileInfo template, string password)
260        {
261            Init();
262            File = newFile;
263            CreateFromTemplate(template, password);
264        }
265        /// <summary>
266        /// Create a new instance of the ExcelPackage class based on a existing template.
267        /// </summary>
268        /// <param name="template">The name of the Excel template to use as the basis of the new Excel file</param>
269        /// <param name="useStream">if true use a stream. If false create a file in the temp dir with a random name</param>
270        public ExcelPackage(FileInfo template, bool useStream)
271        {
272            Init();
273            CreateFromTemplate(template, null);
274            if (useStream == false)
275            {
276                File = new FileInfo(Path.GetTempPath() + Guid.NewGuid().ToString() + ".xlsx");
277            }
278        }
279        /// <summary>
280        /// Create a new instance of the ExcelPackage class based on a existing template.
281        /// </summary>
282        /// <param name="template">The name of the Excel template to use as the basis of the new Excel file</param>
283        /// <param name="useStream">if true use a stream. If false create a file in the temp dir with a random name</param>
284        /// <param name="password">Password to decrypted the template</param>
285        public ExcelPackage(FileInfo template, bool useStream, string password)
286        {
287            Init();
288            CreateFromTemplate(template, password);
289            if (useStream == false)
290            {
291                File = new FileInfo(Path.GetTempPath() + Guid.NewGuid().ToString() + ".xlsx");
292            }
293        }
294        /// <summary>
295        /// Create a new instance of the ExcelPackage class based on a stream
296        /// </summary>
297        /// <param name="newStream">The stream object can be empty or contain a package. The stream must be Read/Write</param>
298        public ExcelPackage(Stream newStream)
299        {
300            Init();
301            if (newStream.Length == 0)
302            {
303                ConstructNewFile(newStream, null);
304            }
305            else
306            {
307                Load(newStream);
308            }
309        }
310        /// <summary>
311        /// Create a new instance of the ExcelPackage class based on a stream
312        /// </summary>
313        /// <param name="newStream">The stream object can be empty or contain a package. The stream must be Read/Write</param>
314        /// <param name="Password">The password to decrypt the document</param>
315        public ExcelPackage(Stream newStream, string Password)
316        {
317            if (!(newStream.CanRead && newStream.CanWrite))
318            {
319                throw new Exception("The stream must be read/write");
320            }
321
322            Init();
323            if (newStream.Length > 0)
324            {
325                Load(newStream,Password);
326            }
327            else
328            {
329                _stream = newStream;
330                _package = Package.Open(_stream, FileMode.Create, FileAccess.ReadWrite);
331                CreateBlankWb();
332            }
333        }
334        /// <summary>
335        /// Create a new instance of the ExcelPackage class based on a stream
336        /// </summary>
337        /// <param name="newStream">The output stream. Must be an empty read/write stream.</param>
338        /// <param name="templateStream">This stream is copied to the output stream at load</param>
339        public ExcelPackage(Stream newStream, Stream templateStream)
340        {
341            if (newStream.Length > 0)
342            {
343                throw(new Exception("The output stream must be empty. Length > 0"));
344            }
345            else if (!(newStream.CanRead && newStream.CanWrite))
346            {
347                throw new Exception("The stream must be read/write");
348            }
349            Init();
350            Load(templateStream, newStream, null);
351        }
352        /// <summary>
353        /// Create a new instance of the ExcelPackage class based on a stream
354        /// </summary>
355        /// <param name="newStream">The output stream. Must be an empty read/write stream.</param>
356        /// <param name="templateStream">This stream is copied to the output stream at load</param>
357        /// <param name="Password">Password to decrypted the template</param>
358        public ExcelPackage(Stream newStream, Stream templateStream, string Password)
359        {
360            if (newStream.Length > 0)
361            {
362                throw (new Exception("The output stream must be empty. Length > 0"));
363            }
364            else if (!(newStream.CanRead && newStream.CanWrite))
365            {
366                throw new Exception("The stream must be read/write");
367            }
368            Init();
369            Load(templateStream, newStream, Password);
370        }
371        #endregion
372        internal ImageInfo AddImage(byte[] image)
373        {
374            return AddImage(image, null, "");
375        }
376        internal ImageInfo AddImage(byte[] image, Uri uri, string contentType)
377        {
378            var hashProvider = new SHA1CryptoServiceProvider();
379            var hash = BitConverter.ToString(hashProvider.ComputeHash(image)).Replace("-","");
380            lock (_images)
381            {
382                if (_images.ContainsKey(hash))
383                {
384                    _images[hash].RefCount++;
385                }
386                else
387                {
388                    PackagePart imagePart;
389                    if (uri == null)
390                    {
391                        uri = GetNewUri(Package, "/xl/media/image{0}.jpg");
392                        imagePart = Package.CreatePart(uri, "image/jpeg", CompressionOption.NotCompressed);
393                    }
394                    else
395                    {
396                        imagePart = Package.CreatePart(uri, contentType, CompressionOption.NotCompressed);
397                    }
398                    var stream = imagePart.GetStream(FileMode.Create, FileAccess.Write);
399                    stream.Write(image, 0, image.GetLength(0));
400
401                    _images.Add(hash, new ImageInfo() { Uri = uri, RefCount = 1, Hash = hash, Part = imagePart });
402                }
403            }
404            return _images[hash];
405        }
406        internal ImageInfo LoadImage(byte[] image, Uri uri, PackagePart imagePart)
407        {
408            var hashProvider = new SHA1CryptoServiceProvider();
409            var hash = BitConverter.ToString(hashProvider.ComputeHash(image)).Replace("-", "");
410            if (_images.ContainsKey(hash))
411            {
412                _images[hash].RefCount++;
413            }
414            else
415            {
416                _images.Add(hash, new ImageInfo() { Uri = uri, RefCount = 1, Hash = hash, Part = imagePart });
417            }
418            return _images[hash];
419        }
420        internal void RemoveImage(string hash)
421        {
422            lock (_images)
423            {
424                if (_images.ContainsKey(hash))
425                {
426                    var ii = _images[hash];
427                    ii.RefCount--;
428                    if (ii.RefCount == 0)
429                    {
430                        Package.DeletePart(ii.Uri);
431                        _images.Remove(hash);
432                    }
433                }
434            }
435        }
436        internal ImageInfo GetImageInfo(byte[] image)
437        {
438            var hashProvider = new SHA1CryptoServiceProvider();
439            var hash = BitConverter.ToString(hashProvider.ComputeHash(image)).Replace("-","");
440
441            if (_images.ContainsKey(hash))
442            {
443                return _images[hash];
444            }
445            else
446            {
447                return null;
448            }
449        }
450        private Uri GetNewUri(Package package, string sUri)
451        {
452            int id = 1;
453            Uri uri;
454            do
455            {
456                uri = new Uri(string.Format(sUri, id++), UriKind.Relative);
457            }
458            while (package.PartExists(uri));
459            return uri;
460        }
461        /// <summary>
462        /// Init values here
463        /// </summary>
464        private void Init()
465        {
466            Compression = CompressionOption.Normal;
467            DoAdjustDrawings = true;
468        }
469        /// <summary>
470        /// Create a new file from a template
471        /// </summary>
472        /// <param name="template">An existing xlsx file to use as a template</param>
473        /// <param name="password">The password to decrypt the package.</param>
474        /// <returns></returns>
475        private void CreateFromTemplate(FileInfo template, string password)
476        {
477            if (template != null) template.Refresh();
478            if (template.Exists)
479            {
480                _stream = new MemoryStream();
481                if (password != null)
482                {
483                    Encryption.IsEncrypted = true;
484                    Encryption.Password = password;
485                    var encrHandler = new EncryptedPackageHandler();
486                    _stream = encrHandler.DecryptPackage(template, Encryption);
487                    encrHandler = null;
488                    //throw (new NotImplementedException("No support for Encrypted packages in this version"));
489                }
490                else
491                {
492                    byte[] b = System.IO.File.ReadAllBytes(template.FullName);
493                    _stream.Write(b, 0, b.Length);
494                }
495                try
496                {
497                    _package = Package.Open(_stream, FileMode.Open, FileAccess.ReadWrite);
498                }
499                catch (Exception ex)
500                {
501                    if (password == null && EncryptedPackageHandler.IsStorageFile(template.FullName)==0)
502                    {
503                        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);
504                    }
505                    else
506                    {
507                        throw (ex);
508                    }
509                }
510            }
511            else
512                throw new Exception("Passed invalid TemplatePath to Excel Template");
513            //return newFile;
514        }
515        private void ConstructNewFile(Stream stream, string password)
516        {
517            _stream = stream;
518            if (File != null) File.Refresh();
519            if (File != null && File.Exists)
520            {
521                if (password != null)
522                {
523                    var encrHandler = new EncryptedPackageHandler();
524                    Encryption.IsEncrypted = true;
525                    Encryption.Password = password;
526                    _stream = encrHandler.DecryptPackage(File, Encryption);
527                    encrHandler = null;
528                }
529                else
530                {
531                    ReadFile();
532                }
533                try
534                {
535                    _package = Package.Open(_stream, FileMode.Open, FileAccess.ReadWrite);
536                }
537                catch (Exception ex)
538               {
539                   if (password == null && EncryptedPackageHandler.IsStorageFile(File.FullName) == 0)
540                   {
541                       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);
542                   }
543                   else
544                   {
545                       throw (ex);
546                   }
547                }
548            }
549            else
550            {
551                _package = Package.Open(_stream, FileMode.Create, FileAccess.ReadWrite);
552                CreateBlankWb();
553            }
554        }
555
556        private void ReadFile()
557        {
558            byte[] b = System.IO.File.ReadAllBytes(File.FullName);
559            _stream.Write(b, 0, b.Length);
560        }
561        private void CreateBlankWb()
562        {
563            XmlDocument workbook = Workbook.WorkbookXml; // this will create the workbook xml in the package
564            // create the relationship to the main part
565            _package.CreateRelationship(PackUriHelper.GetRelativeUri(new Uri("/xl", UriKind.Relative), Workbook.WorkbookUri), TargetMode.Internal, schemaRelationships + "/officeDocument");
566        }
567
568    /// <summary>
569    /// Returns a reference to the package
570    /// </summary>
571    public Package Package { get { return (_package); } }
572        ExcelEncryption _encryption=null;
573        /// <summary>
574        /// Information how and if the package is encrypted
575        /// </summary>
576        public ExcelEncryption Encryption
577        {
578            get
579            {
580                if (_encryption == null)
581                {
582                    _encryption = new ExcelEncryption();
583                }
584                return _encryption;
585            }
586        }
587    /// <summary>
588    /// Returns a reference to the workbook component within the package.
589    /// All worksheets and cells can be accessed through the workbook.
590    /// </summary>
591    public ExcelWorkbook Workbook
592    {
593      get
594      {
595                if (_workbook == null)
596                {
597                    var nsm = CreateDefaultNSM();
598
599                    _workbook = new ExcelWorkbook(this, nsm);
600
601                    _workbook.GetExternalReferences();
602                    _workbook.GetDefinedNames();
603
604                }
605                return (_workbook);
606      }
607    }
608        /// <summary>
609        /// Automaticlly adjust drawing size when column width/row height are adjusted, depending on the drawings editBy property.
610        /// Default True
611        /// </summary>
612        public bool DoAdjustDrawings
613        {
614            get;
615            set;
616        }
617        private XmlNamespaceManager CreateDefaultNSM()
618        {
619            //  Create a NamespaceManager to handle the default namespace,
620            //  and create a prefix for the default namespace:
621            NameTable nt = new NameTable();
622            var ns = new XmlNamespaceManager(nt);
623            ns.AddNamespace(string.Empty, ExcelPackage.schemaMain);
624            ns.AddNamespace("d", ExcelPackage.schemaMain);
625            ns.AddNamespace("r", ExcelPackage.schemaRelationships);
626            ns.AddNamespace("c", ExcelPackage.schemaChart);
627            ns.AddNamespace("vt", schemaVt);
628            // extended properties (app.xml)
629            ns.AddNamespace("xp", schemaExtended);
630            // custom properties
631            ns.AddNamespace("ctp", schemaCustom);
632            // core properties
633            ns.AddNamespace("cp", schemaCore);
634            // core property namespaces
635            ns.AddNamespace("dc", schemaDc);
636            ns.AddNamespace("dcterms", schemaDcTerms);
637            ns.AddNamespace("dcmitype", schemaDcmiType);
638            ns.AddNamespace("xsi", schemaXsi);
639            return ns;
640        }
641   
642    #region SavePart
643    /// <summary>
644    /// Saves the XmlDocument into the package at the specified Uri.
645    /// </summary>
646    /// <param name="uri">The Uri of the component</param>
647    /// <param name="xmlDoc">The XmlDocument to save</param>
648    internal void SavePart(Uri uri, XmlDocument xmlDoc)
649    {
650            PackagePart part = _package.GetPart(uri);
651      xmlDoc.Save(part.GetStream(FileMode.Create, FileAccess.Write));
652    }
653        /// <summary>
654    /// Saves the XmlDocument into the package at the specified Uri.
655    /// </summary>
656    /// <param name="uri">The Uri of the component</param>
657    /// <param name="xmlDoc">The XmlDocument to save</param>
658        internal void SaveWorkbook(Uri uri, XmlDocument xmlDoc)
659    {
660            PackagePart part = _package.GetPart(uri);
661            if(Workbook.VbaProject==null)
662            {
663                if (part.ContentType != contentTypeWorkbookDefault)
664                {
665                    part = _package.CreatePart(uri, contentTypeWorkbookDefault, Compression);
666                }
667            }
668            else
669            {
670                if (part.ContentType != contentTypeWorkbookMacroEnabled)
671                {
672                    var rels = part.GetRelationships();
673                    _package.DeletePart(uri);
674                    part = Package.CreatePart(uri, contentTypeWorkbookMacroEnabled);
675                    foreach (var rel in rels)
676                    {
677                        Package.DeleteRelationship(rel.Id);
678                        part.CreateRelationship(rel.TargetUri, rel.TargetMode, rel.RelationshipType);
679                    }
680                }
681            }
682      xmlDoc.Save(part.GetStream(FileMode.Create, FileAccess.Write));
683    }
684
685        #endregion
686
687    #region Dispose
688    /// <summary>
689    /// Closes the package.
690    /// </summary>
691    public void Dispose()
692    {
693            if (_package != null)
694            {
695                _package.Close();
696            }
697    }
698    #endregion
699
700    #region Save  // ExcelPackage save
701        /// <summary>
702        /// Saves all the components back into the package.
703        /// This method recursively calls the Save method on all sub-components.
704        /// We close the package after the save is done.
705        /// </summary>
706        public void Save()
707        {
708            try
709            {
710                Workbook.Save();
711                if (File == null)
712                {
713                    _package.Close();
714                }
715                else
716                {
717                    if (System.IO.File.Exists(File.FullName))
718                    {
719                        try
720                        {
721                            System.IO.File.Delete(File.FullName);
722                        }
723                        catch (Exception ex)
724                        {
725                            throw (new Exception(string.Format("Error overwriting file {0}", File.FullName), ex));
726                        }
727                    }
728                    if (Stream is MemoryStream)
729                    {
730                        _package.Close();
731                        var fi = new FileStream(File.FullName, FileMode.Create);
732                        //EncryptPackage
733                        if (Encryption.IsEncrypted)
734                        {
735                            byte[] file = ((MemoryStream)Stream).ToArray();
736                            EncryptedPackageHandler eph = new EncryptedPackageHandler();
737                            var ms = eph.EncryptPackage(file, Encryption);
738
739                            fi.Write(ms.GetBuffer(), 0, (int)ms.Length);
740                            ms.Close();
741                        }
742                        else
743                        {
744                            fi.Write(((MemoryStream)Stream).GetBuffer(), 0, (int)Stream.Length);
745                            Stream.Close();
746                        }
747                        fi.Close();
748                    }
749                    else
750                    {
751                        System.IO.File.WriteAllBytes(File.FullName, GetAsByteArray(false));
752                    }
753                }
754            }
755            catch (Exception ex)
756            {
757                if (File == null)
758                {
759                    throw (ex);
760                }
761                else
762                {
763                    throw (new InvalidOperationException(string.Format("Error saving file {0}", File.FullName), ex));
764                }
765            }
766        }
767        /// <summary>
768        /// Saves all the components back into the package.
769        /// This method recursively calls the Save method on all sub-components.
770        /// The package is closed after it has been saved
771        /// </summary>
772        /// <param name="password">The password to encrypt the workbook with.
773        /// This parameter overrides the Workbook.Encryption.Password.</param>
774        public void Save(string password)
775    {
776            Encryption.Password = password;
777            Save();
778        }
779        /// <summary>
780        /// Saves the workbook to a new file
781        /// The package is closed after it has been saved
782        /// </summary>
783        public void SaveAs(FileInfo file)
784        {
785            File = file;
786            Save();
787        }
788        /// <summary>
789        /// Saves the workbook to a new file
790        /// The package is closed after it has been saved
791        /// </summary>
792        /// <param name="file">The file</param>
793        /// <param name="password">The password to encrypt the workbook with.
794        /// This parameter overrides the Encryption.Password.</param>
795        public void SaveAs(FileInfo file, string password)
796        {
797            File = file;
798            Encryption.Password = password;
799            Save();
800        }
801        /// <summary>
802        /// Copies the Package to the Outstream
803        /// The package is closed after it has been saved
804        /// </summary>
805        /// <param name="OutputStream">The stream to copy the package to</param>
806        public void SaveAs(Stream OutputStream)
807        {
808            File = null;
809            Save();
810
811            if (Encryption.IsEncrypted)
812            {
813                //Encrypt Workbook
814                Byte[] file = new byte[Stream.Length];
815                long pos = Stream.Position;
816                Stream.Seek(0, SeekOrigin.Begin);
817                Stream.Read(file, 0, (int)Stream.Length);
818
819                EncryptedPackageHandler eph = new EncryptedPackageHandler();
820                var ms = eph.EncryptPackage(file, Encryption);
821                CopyStream(ms, ref OutputStream);
822            }
823            else
824            {
825                CopyStream(_stream, ref OutputStream);
826            }
827        }
828        /// <summary>
829        /// Copies the Package to the Outstream
830        /// The package is closed after it has been saved
831        /// </summary>
832        /// <param name="OutputStream">The stream to copy the package to</param>
833        /// <param name="password">The password to encrypt the workbook with.
834        /// This parameter overrides the Encryption.Password.</param>
835        public void SaveAs(Stream OutputStream, string password)
836        {
837            Encryption.Password = password;
838            SaveAs(OutputStream);
839        }
840        FileInfo _file = null;
841
842        /// <summary>
843        /// The output file. Null if no file is used
844        /// </summary>
845        public FileInfo File
846        {
847            get
848            {
849                return _file;
850            }
851            set
852            {
853                _file = value;
854            }
855        }
856        /// <summary>
857        /// The output stream. This stream is the not the encrypted package.
858        /// To get the encrypted package use the SaveAs(stream) method.
859        /// </summary>
860        public Stream Stream
861        {
862            get
863            {
864                return _stream;
865            }
866        }
867    #endregion
868        /// <summary>
869        /// Compression option for the package
870        /// </summary>
871        public CompressionOption Compression { get; set; }
872    #region GetXmlFromUri
873    /// <summary>
874    /// Get the XmlDocument from an URI
875    /// </summary>
876    /// <param name="uri">The Uri to the part</param>
877    /// <returns>The XmlDocument</returns>
878    internal XmlDocument GetXmlFromUri(Uri uri)
879    {
880      XmlDocument xml = new XmlDocument();
881      PackagePart part = _package.GetPart(uri);
882            XmlHelper.LoadXmlSafe(xml, part.GetStream());
883      return (xml);
884    }
885    #endregion
886
887        /// <summary>
888        /// Saves and returns the Excel files as a bytearray.
889        /// Note that the package is closed upon save
890        /// </summary>
891        /// <example>     
892        /// Example how to return a document from a Webserver...
893        /// <code>
894        ///  ExcelPackage package=new ExcelPackage();
895        ///  /**** ... Create the document ****/
896        ///  Byte[] bin = package.GetAsByteArray();
897        ///  Response.ContentType = "Application/vnd.ms-Excel";
898        ///  Response.AddHeader("content-disposition", "attachment;  filename=TheFile.xlsx");
899    ///  Response.BinaryWrite(bin);
900        /// </code>
901        /// </example>
902        /// <returns></returns>
903        public byte[] GetAsByteArray()
904        {
905           return GetAsByteArray(true);
906        }
907        /// <summary>
908        /// Saves and returns the Excel files as a bytearray
909        /// Note that the package is closed upon save
910        /// </summary>
911        /// <example>     
912        /// Example how to return a document from a Webserver...
913        /// <code>
914        ///  ExcelPackage package=new ExcelPackage();
915        ///  /**** ... Create the document ****/
916        ///  Byte[] bin = package.GetAsByteArray();
917        ///  Response.ContentType = "Application/vnd.ms-Excel";
918        ///  Response.AddHeader("content-disposition", "attachment;  filename=TheFile.xlsx");
919        ///  Response.BinaryWrite(bin);
920        /// </code>
921        /// </example>
922        /// <param name="password">The password to encrypt the workbook with.
923        /// This parameter overrides the Encryption.Password.</param>
924        /// <returns></returns>
925        public byte[] GetAsByteArray(string password)
926        {
927            if (password != null)
928            {
929                Encryption.Password = password;
930            }
931            return GetAsByteArray(true);
932        }
933        internal byte[] GetAsByteArray(bool save)
934        {
935            if(save) Workbook.Save();
936            _package.Close();
937
938            Byte[] byRet = new byte[Stream.Length];
939            long pos = Stream.Position;           
940            Stream.Seek(0, SeekOrigin.Begin);
941            Stream.Read(byRet, 0, (int)Stream.Length);
942
943            //Encrypt Workbook?
944            if (Encryption.IsEncrypted)
945            {
946                EncryptedPackageHandler eph=new EncryptedPackageHandler();
947                var ms = eph.EncryptPackage(byRet, Encryption);
948                byRet = ms.ToArray();
949            }
950
951            Stream.Seek(pos, SeekOrigin.Begin);
952            Stream.Close();
953            return byRet;
954        }
955        /// <summary>
956        /// Loads the specified package data from a stream.
957        /// </summary>
958        /// <param name="input">The input.</param>
959        public void Load(Stream input)
960        {
961            Load(input, new MemoryStream(), null);
962        }
963        /// <summary>
964        /// Loads the specified package data from a stream.
965        /// </summary>
966        /// <param name="input">The input.</param>
967        /// <param name="Password">The password to decrypt the document</param>
968        public void Load(Stream input, string Password)
969        {
970            Load(input, new MemoryStream(), Password);
971        }
972        /// <summary>
973        ///
974        /// </summary>
975        /// <param name="input"></param>
976        /// <param name="output"></param>
977        /// <param name="Password"></param>
978        private void Load(Stream input, Stream output, string Password)
979        {
980            //Release some resources:
981            if (this._package != null)
982            {
983                this._package.Close();
984                this._package = null;
985            }
986            if (this._stream != null)
987            {
988                this._stream.Close();
989                this._stream.Dispose();
990                this._stream = null;
991            }
992
993            if (Password != null)
994            {
995                Stream encrStream = new MemoryStream();
996                CopyStream(input, ref encrStream);
997                EncryptedPackageHandler eph=new EncryptedPackageHandler();
998                Encryption.Password = Password;
999                this._stream = eph.DecryptPackage((MemoryStream)encrStream, Encryption);
1000            }
1001            else
1002            {
1003                this._stream = output;
1004                CopyStream(input, ref this._stream);
1005            }
1006
1007            try
1008            {
1009                this._package = Package.Open(this._stream, FileMode.Open, FileAccess.ReadWrite);
1010            }
1011            catch (Exception ex)
1012            {
1013                EncryptedPackageHandler eph = new EncryptedPackageHandler();
1014                if (Password == null && EncryptedPackageHandler.IsStorageILockBytes(eph.GetLockbyte((MemoryStream)_stream)) == 0)
1015                {
1016                    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);
1017                }
1018                else
1019                {
1020                    throw (ex);
1021                }
1022            }
1023           
1024            //Clear the workbook so that it gets reinitialized next time
1025            this._workbook = null;
1026        }
1027        /// <summary>
1028        /// Copies the input stream to the output stream.
1029        /// </summary>
1030        /// <param name="inputStream">The input stream.</param>
1031        /// <param name="outputStream">The output stream.</param>
1032        private static void CopyStream(Stream inputStream, ref Stream outputStream)
1033        {
1034            if (!inputStream.CanRead)
1035            {
1036                throw (new Exception("Can not read from inputstream"));
1037            }
1038            if (!outputStream.CanWrite)
1039            {
1040                throw (new Exception("Can not write to outputstream"));
1041            }
1042            if (inputStream.CanSeek)
1043            {
1044                inputStream.Seek(0, SeekOrigin.Begin);
1045            }
1046
1047            int bufferLength = 8096;
1048            Byte[] buffer = new Byte[bufferLength];
1049            int bytesRead = inputStream.Read(buffer, 0, bufferLength);
1050            // write the required bytes
1051            while (bytesRead > 0)
1052            {
1053                outputStream.Write(buffer, 0, bytesRead);
1054                bytesRead = inputStream.Read(buffer, 0, bufferLength);
1055            }
1056            outputStream.Flush();
1057        }
1058    }
1059}
Note: See TracBrowser for help on using the repository browser.