Free cookie consent management tool by TermsFeed Policy Generator

source: branches/crossvalidation-2434/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/Drawing/ExcelDrawingBase.cs @ 13371

Last change on this file since 13371 was 12074, checked in by sraggl, 10 years ago

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 22.7 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           2010-06-01
30 * Jan Källman    License changed GPL-->LGPL 2011-12-16
31 *******************************************************************************/
32using System;
33using System.Collections;
34using System.Collections.Generic;
35using System.Globalization;
36using System.Text;
37using System.Xml;
38using OfficeOpenXml.Drawing.Chart;
39namespace OfficeOpenXml.Drawing
40{
41    /// <summary>
42    /// Text anchoring
43    /// </summary>
44    public enum eTextAnchoringType
45    {
46        Bottom,
47        Center,
48        Distributed,
49        Justify,
50        Top
51    }
52    /// <summary>
53    /// Vertical text type
54    /// </summary>
55    public enum eTextVerticalType
56    {
57        EastAsianVertical,
58        Horizontal,
59        MongolianVertical,
60        Vertical,
61        Vertical270,
62        WordArtVertical,
63        WordArtVerticalRightToLeft
64
65    }
66    /// <summary>
67    /// How the drawing will be resized.
68    /// </summary>
69    public enum eEditAs
70    {
71        /// <summary>
72        /// Specifies that the current start and end positions shall
73        /// be maintained with respect to the distances from the
74        /// absolute start point of the worksheet.
75        /// </summary>
76        Absolute,
77        /// <summary>
78        /// Specifies that the current drawing shall move with its
79        ///row and column (i.e. the object is anchored to the
80        /// actual from row and column), but that the size shall
81        ///remain absolute.
82        /// </summary>
83        OneCell,
84        /// <summary>
85        /// Specifies that the current drawing shall move and
86        /// resize to maintain its row and column anchors (i.e. the
87        /// object is anchored to the actual from and to row and column).
88        /// </summary>
89        TwoCell
90    }
91    /// <summary>
92    /// Base class for twoanchored drawings.
93    /// Drawings are Charts, shapes and Pictures.
94    /// </summary>
95    public class ExcelDrawing : XmlHelper, IDisposable
96    {
97        /// <summary>
98        /// Position of the a drawing.
99        /// </summary>
100        public class ExcelPosition : XmlHelper
101        {
102            XmlNode _node;
103            XmlNamespaceManager _ns;           
104            internal ExcelPosition(XmlNamespaceManager ns, XmlNode node) :
105                base (ns,node)
106            {
107                _node = node;
108                _ns = ns;
109            }
110            const string colPath="xdr:col";
111            public int Column
112            {
113                get
114                {
115                    return GetXmlNodeInt(colPath);
116                }
117                set
118                {
119                    SetXmlNodeString(colPath, value.ToString());
120                }
121            }
122            const string rowPath="xdr:row";
123            public int Row
124            {
125                get
126                {
127                    return GetXmlNodeInt(rowPath);
128                }
129                set
130                {
131                    SetXmlNodeString(rowPath, value.ToString());
132                }
133            }
134            const string colOffPath = "xdr:colOff";
135            /// <summary>
136            /// Column Offset
137            ///
138            /// EMU units   1cm         =   1/360000
139            ///             1US inch    =   1/914400
140            ///             1pixel      =   1/9525
141            /// </summary>
142            public int ColumnOff
143            {
144                get
145                {
146                    return GetXmlNodeInt(colOffPath);
147                }
148                set
149                {
150                    SetXmlNodeString(colOffPath, value.ToString());
151                }
152            }
153            const string rowOffPath = "xdr:rowOff";
154            /// <summary>
155            /// Row Offset
156            ///
157            /// EMU units   1cm         =   1/360000
158            ///             1US inch    =   1/914400
159            ///             1pixel      =   1/9525
160            /// </summary>
161            public int RowOff
162            {
163                get
164                {
165                    return GetXmlNodeInt(rowOffPath);
166                }
167                set
168                {
169                    SetXmlNodeString(rowOffPath, value.ToString());
170                }
171            }
172        }
173        protected ExcelDrawings _drawings;
174        protected XmlNode _topNode;
175        string _nameXPath;
176        protected internal int _id;
177        const float STANDARD_DPI = 96;
178        public const int EMU_PER_PIXEL = 9525;
179
180        internal ExcelDrawing(ExcelDrawings drawings, XmlNode node, string nameXPath) :
181            base(drawings.NameSpaceManager, node)
182        {
183            _drawings = drawings;
184            _topNode = node;
185            _id = drawings.Worksheet.Workbook._nextDrawingID++;
186            XmlNode posNode = node.SelectSingleNode("xdr:from", drawings.NameSpaceManager);
187            if (node != null)
188            {
189                From = new ExcelPosition(drawings.NameSpaceManager, posNode);
190            }
191            posNode = node.SelectSingleNode("xdr:to", drawings.NameSpaceManager);
192            if (node != null)
193            {
194                To = new ExcelPosition(drawings.NameSpaceManager, posNode);
195            }
196            else
197            {
198                To = null;
199            }
200            _nameXPath = nameXPath;
201            SchemaNodeOrder = new string[] { "from", "to", "graphicFrame", "sp", "clientData"  };
202        }
203        /// <summary>
204        /// The name of the drawing object
205        /// </summary>
206        public string Name
207        {
208            get
209            {
210                try
211                {
212                    if (_nameXPath == "") return "";
213                    return GetXmlNodeString(_nameXPath);
214                }
215                catch
216                {
217                    return "";
218                }
219            }
220            set
221            {
222                try
223                {
224                    if (_nameXPath == "") throw new NotImplementedException();
225                    SetXmlNodeString(_nameXPath, value);
226                }
227                catch
228                {
229                    throw new NotImplementedException();
230                }
231            }
232        }
233        /// <summary>
234        /// How Excel resize drawings when the column width is changed within Excel.
235        /// The width of drawings are currently NOT resized in EPPLus when the column width changes
236        /// </summary>
237        public eEditAs EditAs
238        {
239            get
240            {
241                try
242                {
243                    string s = GetXmlNodeString("@editAs");
244                    if (s == "")
245                    {
246                        return eEditAs.TwoCell;
247                    }
248                    else
249                    {
250                        return (eEditAs)Enum.Parse(typeof(eEditAs), s,true);
251                    }
252                }
253                catch
254                {
255                    return eEditAs.TwoCell;
256                }
257            }
258            set
259            {
260                string s=value.ToString();
261                SetXmlNodeString("@editAs", s.Substring(0,1).ToLower(CultureInfo.InvariantCulture)+s.Substring(1,s.Length-1));
262            }
263        }
264        const string lockedPath="xdr:clientData/@fLocksWithSheet";
265        /// <summary>
266        /// Lock drawing
267        /// </summary>
268        public bool Locked
269        {
270            get
271            {
272                return GetXmlNodeBool(lockedPath, true);
273            }
274            set
275            {
276                SetXmlNodeBool(lockedPath, value);
277            }
278        }
279        const string printPath = "xdr:clientData/@fPrintsWithSheet";
280        /// <summary>
281        /// Print drawing with sheet
282        /// </summary>
283        public bool Print
284        {
285            get
286            {
287                return GetXmlNodeBool(printPath, true);
288            }
289            set
290            {
291                SetXmlNodeBool(printPath, value);
292            }
293        }        /// <summary>
294        /// Top Left position
295        /// </summary>
296        public ExcelPosition From { get; set; }
297        /// <summary>
298        /// Bottom right position
299        /// </summary>
300        public ExcelPosition To
301        {
302            get;
303            set;
304        }
305        /// <summary>
306        /// Add new Drawing types here
307        /// </summary>
308        /// <param name="drawings">The drawing collection</param>
309        /// <param name="node">Xml top node</param>
310        /// <returns>The Drawing object</returns>
311        internal static ExcelDrawing GetDrawing(ExcelDrawings drawings, XmlNode node)
312        {
313            if (node.SelectSingleNode("xdr:sp", drawings.NameSpaceManager) != null)
314            {
315                return new ExcelShape(drawings, node);
316            }
317            else if (node.SelectSingleNode("xdr:pic", drawings.NameSpaceManager) != null)
318            {
319                return new ExcelPicture(drawings, node);
320            }
321            else if (node.SelectSingleNode("xdr:graphicFrame", drawings.NameSpaceManager) != null)
322            {
323                return ExcelChart.GetChart(drawings, node);
324            }
325            else
326            {
327                return new ExcelDrawing(drawings, node, "");
328            }
329        }
330        internal string Id
331        {
332            get { return _id.ToString(); }
333        }
334        internal static string GetTextAchoringText(eTextAnchoringType value)
335        {
336            switch (value)
337            {
338                case eTextAnchoringType.Bottom:
339                    return "b";
340                case eTextAnchoringType.Center:
341                    return "ctr";
342                case eTextAnchoringType.Distributed:
343                    return "dist";
344                case eTextAnchoringType.Justify:
345                    return "just";
346                default:
347                    return "t";
348            }
349        }
350        internal static eTextAnchoringType GetTextAchoringEnum(string text)
351        {
352            switch (text)
353            {
354                case "b":
355                    return eTextAnchoringType.Bottom;
356                case "ctr":
357                    return eTextAnchoringType.Center;
358                case "dist":
359                    return eTextAnchoringType.Distributed;
360                case "just":
361                    return eTextAnchoringType.Justify;
362                default:
363                    return eTextAnchoringType.Top;
364            }
365        }
366        internal static string GetTextVerticalText(eTextVerticalType value)
367        {
368            switch (value)
369            {
370                case eTextVerticalType.EastAsianVertical:
371                    return "eaVert";
372                case eTextVerticalType.MongolianVertical:
373                    return "mongolianVert";
374                case eTextVerticalType.Vertical:
375                    return "vert";
376                case eTextVerticalType.Vertical270:
377                    return "vert270";
378                case eTextVerticalType.WordArtVertical:
379                    return "wordArtVert";
380                case eTextVerticalType.WordArtVerticalRightToLeft:
381                    return "wordArtVertRtl";
382                default:
383                    return "horz";
384            }
385        }
386        internal static eTextVerticalType GetTextVerticalEnum(string text)
387        {
388            switch (text)
389            {
390                case "eaVert":
391                    return eTextVerticalType.EastAsianVertical;
392                case "mongolianVert":
393                    return eTextVerticalType.MongolianVertical;
394                case "vert":
395                    return eTextVerticalType.Vertical;
396                case "vert270":
397                    return eTextVerticalType.Vertical270;
398                case "wordArtVert":
399                    return eTextVerticalType.WordArtVertical;
400                case "wordArtVertRtl":
401                    return eTextVerticalType.WordArtVerticalRightToLeft;
402                default:
403                    return eTextVerticalType.Horizontal;
404            }
405        }
406        #region "Internal sizing functions"
407        internal int GetPixelLeft()
408        {
409            ExcelWorksheet ws = _drawings.Worksheet;
410            decimal mdw = ws.Workbook.MaxFontWidth;
411
412            int pix = 0;
413            for (int col = 0; col < From.Column; col++)
414            {
415                pix += (int)decimal.Truncate(((256 * GetColumnWidth(col + 1) + decimal.Truncate(128 / (decimal)mdw)) / 256) * mdw);
416            }
417            pix += From.ColumnOff / EMU_PER_PIXEL;
418            return pix;
419        }
420        internal int GetPixelTop()
421        {
422            ExcelWorksheet ws = _drawings.Worksheet;
423            int pix = 0;
424            for (int row = 0; row < From.Row; row++)
425            {
426                pix += (int)(GetRowWidth(row + 1) / 0.75);
427            }
428            pix += From.RowOff / EMU_PER_PIXEL;
429            return pix;
430        }
431        internal int GetPixelWidth()
432        {
433            ExcelWorksheet ws = _drawings.Worksheet;
434            decimal mdw = ws.Workbook.MaxFontWidth;
435
436            int pix = -From.ColumnOff / EMU_PER_PIXEL;
437            for (int col = From.Column + 1; col <= To.Column; col++)
438            {
439                pix += (int)decimal.Truncate(((256 * GetColumnWidth(col) + decimal.Truncate(128 / (decimal)mdw)) / 256) * mdw);
440            }
441            pix += To.ColumnOff / EMU_PER_PIXEL;
442            return pix;
443        }
444        internal int GetPixelHeight()
445        {
446            ExcelWorksheet ws = _drawings.Worksheet;
447
448            int pix = -(From.RowOff / EMU_PER_PIXEL);
449            for (int row = From.Row + 1; row <= To.Row; row++)
450            {
451                pix += (int)(GetRowWidth(row) / 0.75);
452            }
453            pix += To.RowOff / EMU_PER_PIXEL;
454            return pix;
455        }
456
457        private decimal GetColumnWidth(int col)
458        {
459            ExcelWorksheet ws = _drawings.Worksheet;
460            var column = ws._values.GetValue(0, col) as ExcelColumn;
461            if (column == null)   //Check that the column exists
462            {
463                return (decimal)ws.DefaultColWidth;
464            }
465            else
466            {
467                return (decimal)ws.Column(col).VisualWidth;
468            }
469        }
470        private double GetRowWidth(int row)
471        {
472            ExcelWorksheet ws = _drawings.Worksheet;
473            object o = null;
474            if (ws._values.Exists(row, 0, ref o) && o != null)   //Check that the row exists
475            {
476                var internalRow = (RowInternal)o;
477                if (internalRow.Height >= 0)
478                {
479                    return internalRow.Height;
480                }
481            }
482            return (double)ws.DefaultRowHeight;
483        }
484        internal void SetPixelTop(int pixels)
485        {
486            ExcelWorksheet ws = _drawings.Worksheet;
487            decimal mdw = ws.Workbook.MaxFontWidth;
488            int prevPix = 0;
489            int pix = (int)(GetRowWidth(1) / 0.75);
490            int row = 2;
491
492            while (pix < pixels)
493            {
494                prevPix = pix;
495                pix += (int)(GetRowWidth(row++) / 0.75);
496            }
497
498            if (pix == pixels)
499            {
500                From.Row = row - 1;
501                From.RowOff = 0;
502            }
503            else
504            {
505                From.Row = row - 2;
506                From.RowOff = (pixels - prevPix) * EMU_PER_PIXEL;
507            }
508        }
509        internal void SetPixelLeft(int pixels)
510        {
511            ExcelWorksheet ws = _drawings.Worksheet;
512            decimal mdw = ws.Workbook.MaxFontWidth;
513            int prevPix = 0;
514            int pix = (int)decimal.Truncate(((256 * GetColumnWidth(1) + decimal.Truncate(128 / (decimal)mdw)) / 256) * mdw);
515            int col = 2;
516
517            while (pix < pixels)
518            {
519                prevPix = pix;
520                pix += (int)decimal.Truncate(((256 * GetColumnWidth(col++) + decimal.Truncate(128 / (decimal)mdw)) / 256) * mdw);
521            }
522            if (pix == pixels)
523            {
524                From.Column = col - 1;
525                From.ColumnOff = 0;
526            }
527            else
528            {
529                From.Column = col - 2;
530                From.ColumnOff = (pixels - prevPix) * EMU_PER_PIXEL;
531            }
532        }
533        internal void SetPixelHeight(int pixels)
534        {
535            SetPixelHeight(pixels, STANDARD_DPI);
536        }
537        internal void SetPixelHeight(int pixels, float dpi)
538        {
539            ExcelWorksheet ws = _drawings.Worksheet;
540            //decimal mdw = ws.Workbook.MaxFontWidth;
541            pixels = (int)(pixels / (dpi / STANDARD_DPI) + .5);
542            int pixOff = pixels - ((int)(ws.Row(From.Row + 1).Height / 0.75) - (int)(From.RowOff / EMU_PER_PIXEL));
543            int prevPixOff = pixels;
544            int row = From.Row + 1;
545
546            while (pixOff >= 0)
547            {
548                prevPixOff = pixOff;
549                pixOff -= (int)(GetRowWidth(++row) / 0.75);
550            }
551            To.Row = row - 1;
552            if (From.Row == To.Row)
553            {
554                To.RowOff = From.RowOff + (pixels) * EMU_PER_PIXEL;
555            }
556            else
557            {
558                To.RowOff = prevPixOff * EMU_PER_PIXEL;
559            }
560        }
561        internal void SetPixelWidth(int pixels)
562        {
563            SetPixelWidth(pixels, STANDARD_DPI);
564        }
565        internal void SetPixelWidth(int pixels, float dpi)
566        {
567            ExcelWorksheet ws = _drawings.Worksheet;
568            decimal mdw = ws.Workbook.MaxFontWidth;
569
570            pixels = (int)(pixels / (dpi / STANDARD_DPI) + .5);
571            int pixOff = (int)pixels - ((int)decimal.Truncate(((256 * GetColumnWidth(From.Column + 1) + decimal.Truncate(128 / (decimal)mdw)) / 256) * mdw) - From.ColumnOff / EMU_PER_PIXEL);
572            int prevPixOff = From.ColumnOff / EMU_PER_PIXEL + (int)pixels;
573            int col = From.Column + 2;
574
575            while (pixOff >= 0)
576            {
577                prevPixOff = pixOff;
578                pixOff -= (int)decimal.Truncate(((256 * GetColumnWidth(col++) + decimal.Truncate(128 / (decimal)mdw)) / 256) * mdw);
579            }
580
581            To.Column = col - 2;
582            To.ColumnOff = prevPixOff * EMU_PER_PIXEL;
583        }
584        #endregion
585        #region "Public sizing functions"
586        /// <summary>
587        /// Set the top left corner of a drawing.
588        /// Note that resizing columns / rows after using this function will effect the position of the drawing
589        /// </summary>
590        /// <param name="PixelTop">Top pixel</param>
591        /// <param name="PixelLeft">Left pixel</param>
592        public void SetPosition(int PixelTop, int PixelLeft)
593        {
594            int width = GetPixelWidth();
595            int height = GetPixelHeight();
596
597            SetPixelTop(PixelTop);
598            SetPixelLeft(PixelLeft);
599
600            SetPixelWidth(width);
601            SetPixelHeight(height);
602        }
603        /// <summary>
604        /// Set the top left corner of a drawing.
605        /// Note that resizing columns / rows after using this function will effect the position of the drawing
606        /// </summary>
607        /// <param name="Row">Start row</param>
608        /// <param name="RowOffsetPixels">Offset in pixels</param>
609        /// <param name="Column">Start Column</param>
610        /// <param name="ColumnOffsetPixels">Offset in pixels</param>
611        public void SetPosition(int Row, int RowOffsetPixels, int Column, int ColumnOffsetPixels)
612        {
613            int width = GetPixelWidth();
614            int height = GetPixelHeight();
615
616            From.Row = Row;
617            From.RowOff = RowOffsetPixels * EMU_PER_PIXEL;
618            From.Column = Column;
619            From.ColumnOff = ColumnOffsetPixels * EMU_PER_PIXEL;
620
621            SetPixelWidth(width);
622            SetPixelHeight(height);
623        }
624        /// <summary>
625        /// Set size in Percent
626        /// Note that resizing columns / rows after using this function will effect the size of the drawing
627        /// </summary>
628        /// <param name="Percent"></param>
629        public virtual void SetSize(int Percent)
630        {
631            int width = GetPixelWidth();
632            int height = GetPixelHeight();
633
634            width = (int)(width * ((decimal)Percent / 100));
635            height = (int)(height * ((decimal)Percent / 100));
636
637            SetPixelWidth(width, 96);
638            SetPixelHeight(height, 96);
639        }
640        /// <summary>
641        /// Set size in pixels
642        /// Note that resizing columns / rows after using this function will effect the size of the drawing
643        /// </summary>
644        /// <param name="PixelWidth">Width in pixels</param>
645        /// <param name="PixelHeight">Height in pixels</param>
646        public void SetSize(int PixelWidth, int PixelHeight)
647        {
648            SetPixelWidth(PixelWidth);
649            SetPixelHeight(PixelHeight);
650        }
651        #endregion
652        internal virtual void DeleteMe()
653        {
654            TopNode.ParentNode.RemoveChild(TopNode);
655        }
656
657        public virtual void Dispose()
658        {
659            _topNode = null;
660        }
661    }
662}
Note: See TracBrowser for help on using the repository browser.