| /******************************************************************************* | 
 |  * 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-12-22 | 
 |  * Jan Källman		License changed GPL-->LGPL 2011-12-16 | 
 |  *******************************************************************************/ | 
 | using System; | 
 | using System.Collections.Generic; | 
 | using System.Text; | 
 | using System.Xml; | 
 | using System.Collections; | 
 | using System.IO; | 
 | using System.Drawing; | 
 | using System.Linq; | 
 | using OfficeOpenXml.Drawing.Chart; | 
 | using OfficeOpenXml.Table.PivotTable; | 
 | using OfficeOpenXml.Utils; | 
 | namespace OfficeOpenXml.Drawing | 
 | { | 
 |     /// <summary> | 
 |     /// Collection for Drawing objects. | 
 |     /// </summary> | 
 |     public class ExcelDrawings : IEnumerable<ExcelDrawing>, IDisposable | 
 |     { | 
 |         private XmlDocument _drawingsXml=new XmlDocument(); | 
 |         private Dictionary<string, int> _drawingNames; | 
 |         private List<ExcelDrawing> _drawings; | 
 |         internal class ImageCompare | 
 |         { | 
 |             internal byte[] image { get; set; } | 
 |             internal string relID { get; set; } | 
 |  | 
 |             internal bool Comparer(byte[] compareImg) | 
 |             { | 
 |                 if (compareImg.Length != image.Length) | 
 |                 { | 
 |                     return false; | 
 |                 } | 
 |  | 
 |                 for (int i = 0; i < image.Length; i++) | 
 |                 { | 
 |                     if (image[i] != compareImg[i]) | 
 |                     { | 
 |                         return false; | 
 |                     } | 
 |                 } | 
 |                 return true; //Equal | 
 |             } | 
 |         } | 
 |         //internal List<ImageCompare> _pics = new List<ImageCompare>(); | 
 |         internal Dictionary<string, string> _hashes = new Dictionary<string, string>(); | 
 |         internal ExcelPackage _package; | 
 |         internal Packaging.ZipPackageRelationship _drawingRelation = null; | 
 |         internal ExcelDrawings(ExcelPackage xlPackage, ExcelWorksheet sheet) | 
 |         { | 
 |                 _drawingsXml = new XmlDocument();                 | 
 |                 _drawingsXml.PreserveWhitespace = false; | 
 |                 _drawings = new List<ExcelDrawing>(); | 
 |                 _drawingNames = new Dictionary<string,int>(StringComparer.InvariantCultureIgnoreCase); | 
 |                 _package = xlPackage; | 
 |                 Worksheet = sheet; | 
 |                 XmlNode node = sheet.WorksheetXml.SelectSingleNode("//d:drawing", sheet.NameSpaceManager); | 
 |                 CreateNSM(); | 
 |                 if (node != null) | 
 |                 { | 
 |                     _drawingRelation = sheet.Part.GetRelationship(node.Attributes["r:id"].Value); | 
 |                     _uriDrawing = UriHelper.ResolvePartUri(sheet.WorksheetUri, _drawingRelation.TargetUri); | 
 |  | 
 |                     _part = xlPackage.Package.GetPart(_uriDrawing); | 
 |                     XmlHelper.LoadXmlSafe(_drawingsXml, _part.GetStream());  | 
 |  | 
 |                     AddDrawings(); | 
 |                 } | 
 |          } | 
 |         internal ExcelWorksheet Worksheet { get; set; } | 
 |         /// <summary> | 
 |         /// A reference to the drawing xml document | 
 |         /// </summary> | 
 |         public XmlDocument DrawingXml | 
 |         { | 
 |             get | 
 |             { | 
 |                 return _drawingsXml; | 
 |             } | 
 |         } | 
 |         private void AddDrawings() | 
 |         { | 
 |             // Look inside all children for the drawings because they could be inside | 
 |             // Markup Compatibility AlternativeContent/Choice or AlternativeContent/Fallback nodes. | 
 |             // The code below currently pretends that loading all Choice alternative drawings doesn't cause a problem | 
 |             // elsewhere. This seems to be ok for the time being as encountered drawing files so far only seem to have | 
 |             // one Choice node (and no Fallback) underneath the AlternativeContent node. (Excel 2013 that is.) | 
 |             // This change prevents CodePlex issue #15028 from occurring.  | 
 |             // (the drawing xml part (that ONLY contained AlternativeContent nodes) was incorrectly being garbage collected when the package was saved) | 
 |             XmlNodeList list = _drawingsXml.SelectNodes("//*[self::xdr:twoCellAnchor or self::xdr:oneCellAnchor or self::xdr:absoluteAnchor]", NameSpaceManager); | 
 |  | 
 |             foreach (XmlNode node in list) | 
 |             { | 
 |                  | 
 |                 ExcelDrawing dr; | 
 |                 switch(node.LocalName) | 
 |                 { | 
 |                     case "oneCellAnchor": | 
 |                         dr = new ExcelDrawing(this, node, "xdr:sp/xdr:nvSpPr/xdr:cNvPr/@name"); | 
 |                         break; | 
 |                     case "twoCellAnchor": | 
 |                         dr = ExcelDrawing.GetDrawing(this, node); | 
 |                         break; | 
 |                     case "absoluteAnchor": | 
 |                         dr = ExcelDrawing.GetDrawing(this, node); | 
 |                         break; | 
 |                     default: //"absoluteCellAnchor": | 
 |                         dr = null; | 
 |                         break; | 
 |                 } | 
 |                 if (dr != null) | 
 |                 { | 
 |                     _drawings.Add(dr); | 
 |                     if (!_drawingNames.ContainsKey(dr.Name)) | 
 |                     { | 
 |                         _drawingNames.Add(dr.Name, _drawings.Count - 1); | 
 |                     } | 
 |                 } | 
 |             } | 
 |         } | 
 |  | 
 |  | 
 |         #region NamespaceManager | 
 |         /// <summary> | 
 |         /// Creates the NamespaceManager.  | 
 |         /// </summary> | 
 |         private void CreateNSM() | 
 |         { | 
 |             NameTable nt = new NameTable(); | 
 |             _nsManager = new XmlNamespaceManager(nt); | 
 |             _nsManager.AddNamespace("a", ExcelPackage.schemaDrawings); | 
 |             _nsManager.AddNamespace("xdr", ExcelPackage.schemaSheetDrawings); | 
 |             _nsManager.AddNamespace("c", ExcelPackage.schemaChart); | 
 |             _nsManager.AddNamespace("r", ExcelPackage.schemaRelationships); | 
 |         } | 
 |         /// <summary> | 
 |         /// Provides access to a namespace manager instance to allow XPath searching | 
 |         /// </summary> | 
 |         XmlNamespaceManager _nsManager=null; | 
 |         public XmlNamespaceManager NameSpaceManager | 
 |         { | 
 |             get | 
 |             { | 
 |                 return _nsManager; | 
 |             } | 
 |         } | 
 |         #endregion | 
 |         #region IEnumerable Members | 
 |  | 
 |         public IEnumerator GetEnumerator() | 
 |         { | 
 |             return (_drawings.GetEnumerator()); | 
 |         } | 
 |         #region IEnumerable<ExcelDrawing> Members | 
 |  | 
 |         IEnumerator<ExcelDrawing> IEnumerable<ExcelDrawing>.GetEnumerator() | 
 |         { | 
 |             return (_drawings.GetEnumerator()); | 
 |         } | 
 |  | 
 |         #endregion | 
 |  | 
 |         /// <summary> | 
 |         /// Returns the drawing at the specified position.   | 
 |         /// </summary> | 
 |         /// <param name="PositionID">The position of the drawing. 0-base</param> | 
 |         /// <returns></returns> | 
 |         public ExcelDrawing this[int PositionID] | 
 |         { | 
 |             get | 
 |             { | 
 |                 return (_drawings[PositionID]); | 
 |             } | 
 |         } | 
 |  | 
 |         /// <summary> | 
 |         /// Returns the drawing matching the specified name | 
 |         /// </summary> | 
 |         /// <param name="Name">The name of the worksheet</param> | 
 |         /// <returns></returns> | 
 |         public ExcelDrawing this[string Name] | 
 |         { | 
 |             get | 
 |             { | 
 |                 if (_drawingNames.ContainsKey(Name)) | 
 |                 { | 
 |                     return _drawings[_drawingNames[Name]]; | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     return null; | 
 |                 } | 
 |             } | 
 |         } | 
 |         public int Count | 
 |         { | 
 |             get | 
 |             { | 
 |                 if (_drawings == null) | 
 |                 { | 
 |                     return 0; | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     return _drawings.Count; | 
 |                 } | 
 |             } | 
 |         } | 
 |         Packaging.ZipPackagePart _part=null; | 
 |         internal Packaging.ZipPackagePart Part | 
 |         { | 
 |             get | 
 |             { | 
 |                 return _part; | 
 |             }         | 
 |         } | 
 |         Uri _uriDrawing=null; | 
 |         public Uri UriDrawing | 
 |         { | 
 |             get | 
 |             { | 
 |                 return _uriDrawing; | 
 |             } | 
 |         } | 
 |         #endregion | 
 |         #region Add functions | 
 |             /// <summary> | 
 |             /// Add a new chart to the worksheet. | 
 |             /// Do not support Bubble-, Radar-, Stock- or Surface charts.  | 
 |             /// </summary> | 
 |             /// <param name="Name"></param> | 
 |             /// <param name="ChartType">Type of chart</param> | 
 |             /// <param name="PivotTableSource">The pivottable source for a pivotchart</param>     | 
 |             /// <returns>The chart</returns> | 
 |             public ExcelChart AddChart(string Name, eChartType ChartType, ExcelPivotTable PivotTableSource) | 
 |             { | 
 |                 if(_drawingNames.ContainsKey(Name)) | 
 |                 { | 
 |                     throw new Exception("Name already exists in the drawings collection"); | 
 |                 } | 
 |  | 
 |                 if (ChartType == eChartType.StockHLC || | 
 |                     ChartType == eChartType.StockOHLC || | 
 |                     ChartType == eChartType.StockVOHLC) | 
 |                 { | 
 |                     throw(new NotImplementedException("Chart type is not supported in the current version")); | 
 |                 } | 
 |                 if (Worksheet is ExcelChartsheet && _drawings.Count > 0) | 
 |                 { | 
 |                     throw new InvalidOperationException("Chart Worksheets can't have more than one chart");                 | 
 |                 } | 
 |                 XmlElement drawNode = CreateDrawingXml(); | 
 |  | 
 |                 ExcelChart chart = ExcelChart.GetNewChart(this, drawNode, ChartType, null, PivotTableSource); | 
 |                 chart.Name = Name; | 
 |                 _drawings.Add(chart); | 
 |                 _drawingNames.Add(Name, _drawings.Count - 1); | 
 |                 return chart; | 
 |             } | 
 |             /// <summary> | 
 |             /// Add a new chart to the worksheet. | 
 |             /// Do not support Bubble-, Radar-, Stock- or Surface charts.  | 
 |             /// </summary> | 
 |             /// <param name="Name"></param> | 
 |             /// <param name="ChartType">Type of chart</param> | 
 |             /// <returns>The chart</returns> | 
 |             public ExcelChart AddChart(string Name, eChartType ChartType) | 
 |             { | 
 |                 return AddChart(Name, ChartType, null); | 
 |             } | 
 |             /// <summary> | 
 |             /// Add a picure to the worksheet | 
 |             /// </summary> | 
 |             /// <param name="Name"></param> | 
 |             /// <param name="image">An image. Allways saved in then JPeg format</param> | 
 |             /// <returns></returns> | 
 |             public ExcelPicture AddPicture(string Name, Image image) | 
 |             { | 
 |                return AddPicture(Name, image, null); | 
 |             } | 
 |             /// <summary> | 
 |             /// Add a picure to the worksheet | 
 |             /// </summary> | 
 |             /// <param name="Name"></param> | 
 |             /// <param name="image">An image. Allways saved in then JPeg format</param> | 
 |             /// <param name="Hyperlink">Picture Hyperlink</param> | 
 |             /// <returns></returns> | 
 |             public ExcelPicture AddPicture(string Name, Image image, Uri Hyperlink) | 
 |             { | 
 |                 if (image != null) | 
 |                 { | 
 |                     if (_drawingNames.ContainsKey(Name)) | 
 |                     { | 
 |                         throw new Exception("Name already exists in the drawings collection"); | 
 |                     } | 
 |                     XmlElement drawNode = CreateDrawingXml(); | 
 |                     drawNode.SetAttribute("editAs", "oneCell"); | 
 |                     ExcelPicture pic = new ExcelPicture(this, drawNode, image, Hyperlink); | 
 |                     pic.Name = Name; | 
 |                     _drawings.Add(pic); | 
 |                     _drawingNames.Add(Name, _drawings.Count - 1); | 
 |                     return pic; | 
 |                 } | 
 |                 throw (new Exception("AddPicture: Image can't be null")); | 
 |             } | 
 |             /// <summary> | 
 |             /// Add a picure to the worksheet | 
 |             /// </summary> | 
 |             /// <param name="Name"></param> | 
 |             /// <param name="ImageFile">The image file</param> | 
 |             /// <returns></returns> | 
 |             public ExcelPicture AddPicture(string Name, FileInfo ImageFile) | 
 |             { | 
 |                return AddPicture(Name, ImageFile, null); | 
 |             } | 
 |             /// <summary> | 
 |             /// Add a picure to the worksheet | 
 |             /// </summary> | 
 |             /// <param name="Name"></param> | 
 |             /// <param name="ImageFile">The image file</param> | 
 |             /// <param name="Hyperlink">Picture Hyperlink</param> | 
 |             /// <returns></returns> | 
 |             public ExcelPicture AddPicture(string Name, FileInfo ImageFile, Uri Hyperlink) | 
 |             { | 
 |                 if (Worksheet is ExcelChartsheet && _drawings.Count > 0) | 
 |                 { | 
 |                     throw new InvalidOperationException("Chart worksheets can't have more than one drawing"); | 
 |                 } | 
 |                 if (ImageFile != null) | 
 |                { | 
 |                   if (_drawingNames.ContainsKey(Name)) | 
 |                   { | 
 |                      throw new Exception("Name already exists in the drawings collection"); | 
 |                   } | 
 |                   XmlElement drawNode = CreateDrawingXml(); | 
 |                   drawNode.SetAttribute("editAs", "oneCell"); | 
 |                   ExcelPicture pic = new ExcelPicture(this, drawNode, ImageFile, Hyperlink); | 
 |                   pic.Name = Name; | 
 |                   _drawings.Add(pic); | 
 |                   _drawingNames.Add(Name, _drawings.Count - 1); | 
 |                   return pic; | 
 |                } | 
 |                throw (new Exception("AddPicture: ImageFile can't be null")); | 
 |             } | 
 |  | 
 |         /// <summary> | 
 |         /// Add a new shape to the worksheet | 
 |         /// </summary> | 
 |         /// <param name="Name">Name</param> | 
 |         /// <param name="Style">Shape style</param> | 
 |         /// <returns>The shape object</returns> | 
 |      | 
 |         public ExcelShape AddShape(string Name, eShapeStyle Style) | 
 |             { | 
 |                 if (Worksheet is ExcelChartsheet && _drawings.Count > 0) | 
 |                 { | 
 |                     throw new InvalidOperationException("Chart worksheets can't have more than one drawing"); | 
 |                 } | 
 |                 if (_drawingNames.ContainsKey(Name)) | 
 |                 { | 
 |                     throw new Exception("Name already exists in the drawings collection"); | 
 |                 } | 
 |                 XmlElement drawNode = CreateDrawingXml(); | 
 |  | 
 |                 ExcelShape shape = new ExcelShape(this, drawNode, Style); | 
 |                 shape.Name = Name; | 
 |                 shape.Style = Style; | 
 |                 _drawings.Add(shape); | 
 |                 _drawingNames.Add(Name, _drawings.Count - 1); | 
 |                 return shape; | 
 |             } | 
 |         /// <summary> | 
 |         /// Add a new shape to the worksheet | 
 |         /// </summary> | 
 |         /// <param name="Name">Name</param> | 
 |         /// <param name="Source">Source shape</param> | 
 |         /// <returns>The shape object</returns> | 
 |         public ExcelShape AddShape(string Name, ExcelShape Source) | 
 |         { | 
 |             if (Worksheet is ExcelChartsheet && _drawings.Count > 0) | 
 |             { | 
 |                 throw new InvalidOperationException("Chart worksheets can't have more than one drawing"); | 
 |             } | 
 |             if (_drawingNames.ContainsKey(Name)) | 
 |             { | 
 |                 throw new Exception("Name already exists in the drawings collection"); | 
 |             } | 
 |             XmlElement drawNode = CreateDrawingXml(); | 
 |             drawNode.InnerXml = Source.TopNode.InnerXml; | 
 |  | 
 |             ExcelShape shape = new ExcelShape(this, drawNode); | 
 |             shape.Name = Name; | 
 |             shape.Style = Source.Style; | 
 |             _drawings.Add(shape); | 
 |             _drawingNames.Add(Name, _drawings.Count - 1); | 
 |             return shape; | 
 |         } | 
 |             private XmlElement CreateDrawingXml() | 
 |             { | 
 |                 if (DrawingXml.OuterXml == "") | 
 |                 { | 
 |                     DrawingXml.LoadXml(string.Format("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><xdr:wsDr xmlns:xdr=\"{0}\" xmlns:a=\"{1}\" />", ExcelPackage.schemaSheetDrawings, ExcelPackage.schemaDrawings)); | 
 |                     _uriDrawing = new Uri(string.Format("/xl/drawings/drawing{0}.xml", Worksheet.SheetID),UriKind.Relative); | 
 |  | 
 |                     Packaging.ZipPackage package = Worksheet._package.Package; | 
 |                     _part = package.CreatePart(_uriDrawing, "application/vnd.openxmlformats-officedocument.drawing+xml", _package.Compression); | 
 |  | 
 |                     StreamWriter streamChart = new StreamWriter(_part.GetStream(FileMode.Create, FileAccess.Write)); | 
 |                     DrawingXml.Save(streamChart); | 
 |                     streamChart.Close(); | 
 |                     package.Flush(); | 
 |  | 
 |                     _drawingRelation = Worksheet.Part.CreateRelationship(UriHelper.GetRelativeUri(Worksheet.WorksheetUri, _uriDrawing), Packaging.TargetMode.Internal, ExcelPackage.schemaRelationships + "/drawing"); | 
 |                     XmlElement e = Worksheet.WorksheetXml.CreateElement("drawing", ExcelPackage.schemaMain); | 
 |                     e.SetAttribute("id",ExcelPackage.schemaRelationships, _drawingRelation.Id); | 
 |  | 
 |                     Worksheet.WorksheetXml.DocumentElement.AppendChild(e); | 
 |                     package.Flush();                     | 
 |                 } | 
 |                 XmlNode colNode = _drawingsXml.SelectSingleNode("//xdr:wsDr", NameSpaceManager); | 
 |                 XmlElement drawNode; | 
 |                 if (this.Worksheet is ExcelChartsheet) | 
 |                 { | 
 |                     drawNode = _drawingsXml.CreateElement("xdr", "absoluteAnchor", ExcelPackage.schemaSheetDrawings); | 
 |                     XmlElement posNode = _drawingsXml.CreateElement("xdr", "pos", ExcelPackage.schemaSheetDrawings); | 
 |                     posNode.SetAttribute("y", "0"); | 
 |                     posNode.SetAttribute("x", "0"); | 
 |                     drawNode.AppendChild(posNode); | 
 |                     XmlElement extNode = _drawingsXml.CreateElement("xdr", "ext", ExcelPackage.schemaSheetDrawings); | 
 |                     extNode.SetAttribute("cy", "6072876"); | 
 |                     extNode.SetAttribute("cx", "9299263"); | 
 |                     drawNode.AppendChild(extNode); | 
 |                     colNode.AppendChild(drawNode); | 
 |                 } | 
 |                 else | 
 |                 { | 
 |                     drawNode = _drawingsXml.CreateElement("xdr", "twoCellAnchor", ExcelPackage.schemaSheetDrawings); | 
 |                     colNode.AppendChild(drawNode); | 
 |                     //Add from position Element; | 
 |                     XmlElement fromNode = _drawingsXml.CreateElement("xdr", "from", ExcelPackage.schemaSheetDrawings); | 
 |                     drawNode.AppendChild(fromNode); | 
 |                     fromNode.InnerXml = "<xdr:col>0</xdr:col><xdr:colOff>0</xdr:colOff><xdr:row>0</xdr:row><xdr:rowOff>0</xdr:rowOff>"; | 
 |  | 
 |                     //Add to position Element; | 
 |                     XmlElement toNode = _drawingsXml.CreateElement("xdr", "to", ExcelPackage.schemaSheetDrawings); | 
 |                     drawNode.AppendChild(toNode); | 
 |                     toNode.InnerXml = "<xdr:col>10</xdr:col><xdr:colOff>0</xdr:colOff><xdr:row>10</xdr:row><xdr:rowOff>0</xdr:rowOff>"; | 
 |                 } | 
 |  | 
 |                 return drawNode; | 
 |             } | 
 |         #endregion | 
 |         #region Remove methods | 
 |             /// <summary> | 
 |             /// Removes a drawing. | 
 |             /// </summary> | 
 |             /// <param name="Index">The index of the drawing</param> | 
 |         public void Remove(int Index) | 
 |         { | 
 |             if (Worksheet is ExcelChartsheet && _drawings.Count > 0) | 
 |             { | 
 |                 throw new InvalidOperationException("Can' remove charts from chart worksheets"); | 
 |             } | 
 |             RemoveDrawing(Index); | 
 |         } | 
 |  | 
 |         internal void RemoveDrawing(int Index) | 
 |         { | 
 |             var draw = _drawings[Index]; | 
 |             draw.DeleteMe(); | 
 |             for (int i = Index + 1; i < _drawings.Count; i++) | 
 |             { | 
 |                 _drawingNames[_drawings[i].Name]--; | 
 |             } | 
 |             _drawingNames.Remove(draw.Name); | 
 |             _drawings.Remove(draw); | 
 |         } | 
 |         /// <summary> | 
 |         /// Removes a drawing. | 
 |         /// </summary> | 
 |         /// <param name="Drawing">The drawing</param> | 
 |         public void Remove(ExcelDrawing Drawing) | 
 |         { | 
 |             Remove(_drawingNames[Drawing.Name]); | 
 |         } | 
 |         /// <summary> | 
 |         /// Removes a drawing. | 
 |         /// </summary> | 
 |         /// <param name="Name">The name of the drawing</param> | 
 |         public void Remove(string Name) | 
 |         { | 
 |             Remove(_drawingNames[Name]); | 
 |         } | 
 |         /// <summary> | 
 |         /// Removes all drawings from the collection | 
 |         /// </summary> | 
 |         public void Clear() | 
 |         { | 
 |             if (Worksheet is ExcelChartsheet && _drawings.Count > 0) | 
 |             { | 
 |                 throw new InvalidOperationException("Can' remove charts from chart worksheets"); | 
 |             } | 
 |             ClearDrawings(); | 
 |         } | 
 |  | 
 |         internal void ClearDrawings() | 
 |         { | 
 |             while (Count > 0) | 
 |             { | 
 |                 RemoveDrawing(0); | 
 |             } | 
 |         } | 
 |         #endregion | 
 |             internal void AdjustWidth(int[,] pos) | 
 |             { | 
 |                 var ix = 0; | 
 |                 //Now set the size for all drawings depending on the editAs property. | 
 |                 foreach (OfficeOpenXml.Drawing.ExcelDrawing d in this) | 
 |                 { | 
 |                     if (d.EditAs != Drawing.eEditAs.TwoCell) | 
 |                     { | 
 |                         if (d.EditAs == Drawing.eEditAs.Absolute) | 
 |                         { | 
 |                             d.SetPixelLeft(pos[ix, 0]); | 
 |                         } | 
 |                         d.SetPixelWidth(pos[ix, 1]); | 
 |                          | 
 |                     } | 
 |                     ix++; | 
 |                 } | 
 |             } | 
 |             internal void AdjustHeight(int[,] pos) | 
 |             { | 
 |                 var ix = 0; | 
 |                 //Now set the size for all drawings depending on the editAs property. | 
 |                 foreach (OfficeOpenXml.Drawing.ExcelDrawing d in this) | 
 |                 { | 
 |                     if (d.EditAs != Drawing.eEditAs.TwoCell) | 
 |                     { | 
 |                         if (d.EditAs == Drawing.eEditAs.Absolute) | 
 |                         { | 
 |                             d.SetPixelTop(pos[ix, 0]); | 
 |                         } | 
 |                         d.SetPixelHeight(pos[ix, 1]); | 
 |  | 
 |                     } | 
 |                     ix++; | 
 |                 } | 
 |             } | 
 |             internal int[,] GetDrawingWidths() | 
 |             { | 
 |                 int[,] pos = new int[Count, 2]; | 
 |                 int ix = 0; | 
 |                 //Save the size for all drawings | 
 |                 foreach (ExcelDrawing d in this) | 
 |                 { | 
 |                     pos[ix, 0] = d.GetPixelLeft(); | 
 |                     pos[ix++, 1] = d.GetPixelWidth(); | 
 |                 } | 
 |                 return pos; | 
 |             } | 
 |             internal int[,] GetDrawingHeight() | 
 |             { | 
 |                 int[,] pos = new int[Count, 2]; | 
 |                 int ix = 0; | 
 |                 //Save the size for all drawings | 
 |                 foreach (ExcelDrawing d in this) | 
 |                 { | 
 |                     pos[ix, 0] = d.GetPixelTop(); | 
 |                     pos[ix++, 1] = d.GetPixelHeight(); | 
 |                 } | 
 |                 return pos; | 
 |             } | 
 |  | 
 |             public void Dispose() | 
 |             { | 
 |                 _drawingsXml = null; | 
 |                 _hashes.Clear(); | 
 |                 _hashes = null; | 
 |                 _part = null; | 
 |                 _drawingNames.Clear(); | 
 |                 _drawingNames = null; | 
 |                 _drawingRelation = null; | 
 |                 foreach (var d in _drawings) | 
 |                 { | 
 |                     d.Dispose(); | 
 |                 } | 
 |                 _drawings.Clear(); | 
 |                 _drawings = null; | 
 |             } | 
 |     } | 
 | } |