| /******************************************************************************* |
| * You may amend and distribute as you like, but don't remove this header! |
| * |
| * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets. |
| * See http://www.codeplex.com/EPPlus for details. |
| * |
| * Copyright (C) 2011 Jan Källman |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| * See the GNU Lesser General Public License for more details. |
| * |
| * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php |
| * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html |
| * |
| * All code and executables are provided "as is" with no warranty either express or implied. |
| * The author accepts no liability for any damage or loss of business that this product may cause. |
| * |
| * Code change notes: |
| * |
| * Author Change Date |
| * ****************************************************************************** |
| * Jan Källman Initial Release 2009-10-01 |
| * Jan Källman License changed GPL-->LGPL 2011-12-16 |
| *******************************************************************************/ |
| using System; |
| using System.Collections.Generic; |
| using System.Globalization; |
| using System.Text; |
| using System.Xml; |
| using OfficeOpenXml.Style.XmlAccess; |
| using OfficeOpenXml.Drawing; |
| using OfficeOpenXml.Style; |
| /// <summary> |
| /// Shape style |
| /// </summary> |
| public enum eShapeStyle |
| { |
| AccentBorderCallout1, |
| AccentBorderCallout2, |
| AccentBorderCallout3, |
| AccentCallout1, |
| AccentCallout2, |
| AccentCallout3, |
| ActionButtonBackPrevious, |
| ActionButtonBeginning, |
| ActionButtonBlank, |
| ActionButtonDocument, |
| ActionButtonEnd, |
| ActionButtonForwardNext, |
| ActionButtonHelp, |
| ActionButtonHome, |
| ActionButtonInformation, |
| ActionButtonMovie, |
| ActionButtonReturn, |
| ActionButtonSound, |
| Arc, |
| BentArrow, |
| BentConnector2, |
| BentConnector3, |
| BentConnector4, |
| BentConnector5, |
| BentUpArrow, |
| Bevel, |
| BlockArc, |
| BorderCallout1, |
| BorderCallout2, |
| BorderCallout3, |
| BracePair, |
| BracketPair, |
| Callout1, |
| Callout2, |
| Callout3, |
| Can, |
| ChartPlus, |
| ChartStar, |
| ChartX, |
| Chevron, |
| Chord, |
| CircularArrow, |
| Cloud, |
| CloudCallout, |
| Corner, |
| CornerTabs, |
| Cube, |
| CurvedConnector2, |
| CurvedConnector3, |
| CurvedConnector4, |
| CurvedConnector5, |
| CurvedDownArrow, |
| CurvedLeftArrow, |
| CurvedRightArrow, |
| CurvedUpArrow, |
| Decagon, |
| DiagStripe, |
| Diamond, |
| Dodecagon, |
| Donut, |
| DoubleWave, |
| DownArrow, |
| DownArrowCallout, |
| Ellipse, |
| EllipseRibbon, |
| EllipseRibbon2, |
| FlowChartAlternateProcess, |
| FlowChartCollate, |
| FlowChartConnector, |
| FlowChartDecision, |
| FlowChartDelay, |
| FlowChartDisplay, |
| FlowChartDocument, |
| FlowChartExtract, |
| FlowChartInputOutput, |
| FlowChartInternalStorage, |
| FlowChartMagneticDisk, |
| FlowChartMagneticDrum, |
| FlowChartMagneticTape, |
| FlowChartManualInput, |
| FlowChartManualOperation, |
| FlowChartMerge, |
| FlowChartMultidocument, |
| FlowChartOfflineStorage, |
| FlowChartOffpageConnector, |
| FlowChartOnlineStorage, |
| FlowChartOr, |
| FlowChartPredefinedProcess, |
| FlowChartPreparation, |
| FlowChartProcess, |
| FlowChartPunchedCard, |
| FlowChartPunchedTape, |
| FlowChartSort, |
| FlowChartSummingJunction, |
| FlowChartTerminator, |
| FoldedCorner, |
| Frame, |
| Funnel, |
| Gear6, |
| Gear9, |
| HalfFrame, |
| Heart, |
| Heptagon, |
| Hexagon, |
| HomePlate, |
| HorizontalScroll, |
| IrregularSeal1, |
| IrregularSeal2, |
| LeftArrow, |
| LeftArrowCallout, |
| LeftBrace, |
| LeftBracket, |
| LeftCircularArrow, |
| LeftRightArrow, |
| LeftRightArrowCallout, |
| LeftRightCircularArrow, |
| LeftRightRibbon, |
| LeftRightUpArrow, |
| LeftUpArrow, |
| LightningBolt, |
| Line, |
| LineInv, |
| MathDivide, |
| MathEqual, |
| MathMinus, |
| MathMultiply, |
| MathNotEqual, |
| MathPlus, |
| Moon, |
| NonIsoscelesTrapezoid, |
| NoSmoking, |
| NotchedRightArrow, |
| Octagon, |
| Parallelogram, |
| Pentagon, |
| Pie, |
| PieWedge, |
| Plaque, |
| PlaqueTabs, |
| Plus, |
| QuadArrow, |
| QuadArrowCallout, |
| Rect, |
| Ribbon, |
| Ribbon2, |
| RightArrow, |
| RightArrowCallout, |
| RightBrace, |
| RightBracket, |
| Round1Rect, |
| Round2DiagRect, |
| Round2SameRect, |
| RoundRect, |
| RtTriangle, |
| SmileyFace, |
| Snip1Rect, |
| Snip2DiagRect, |
| Snip2SameRect, |
| SnipRoundRect, |
| SquareTabs, |
| Star10, |
| Star12, |
| Star16, |
| Star24, |
| Star32, |
| Star4, |
| Star5, |
| Star6, |
| Star7, |
| Star8, |
| StraightConnector1, |
| StripedRightArrow, |
| Sun, |
| SwooshArrow, |
| Teardrop, |
| Trapezoid, |
| Triangle, |
| UpArrow, |
| UpArrowCallout, |
| UpDownArrow, |
| UpDownArrowCallout, |
| UturnArrow, |
| Wave, |
| WedgeEllipseCallout, |
| WedgeRectCallout, |
| WedgeRoundRectCallout, |
| VerticalScroll |
| } |
| /// <summary> |
| /// Text alignment |
| /// </summary> |
| public enum eTextAlignment |
| { |
| Left, |
| Center, |
| Right, |
| Distributed, |
| Justified, |
| JustifiedLow, |
| ThaiDistributed |
| } |
| /// <summary> |
| /// Fillstyle. |
| /// </summary> |
| public enum eFillStyle |
| { |
| NoFill, |
| SolidFill, |
| GradientFill, |
| PatternFill, |
| BlipFill, |
| GroupFill |
| } |
| namespace OfficeOpenXml.Drawing |
| { |
| /// <summary> |
| /// An Excel shape. |
| /// </summary> |
| public sealed class ExcelShape : ExcelDrawing |
| { |
| internal ExcelShape(ExcelDrawings drawings, XmlNode node) : |
| base(drawings, node, "xdr:sp/xdr:nvSpPr/xdr:cNvPr/@name") |
| { |
| init(); |
| } |
| internal ExcelShape(ExcelDrawings drawings, XmlNode node, eShapeStyle style) : |
| base(drawings, node, "xdr:sp/xdr:nvSpPr/xdr:cNvPr/@name") |
| { |
| init(); |
| XmlElement shapeNode = node.OwnerDocument.CreateElement("xdr", "sp", ExcelPackage.schemaSheetDrawings); |
| shapeNode.SetAttribute("macro", ""); |
| shapeNode.SetAttribute("textlink", ""); |
| node.AppendChild(shapeNode); |
| |
| shapeNode.InnerXml = ShapeStartXml(); |
| node.AppendChild(shapeNode.OwnerDocument.CreateElement("xdr", "clientData", ExcelPackage.schemaSheetDrawings)); |
| } |
| private void init() |
| { |
| SchemaNodeOrder = new string[] { "prstGeom", "ln", "pPr", "defRPr", "solidFill", "uFill", "latin", "cs", "r", "rPr", "t" }; |
| } |
| #region "public methods" |
| const string ShapeStylePath = "xdr:sp/xdr:spPr/a:prstGeom/@prst"; |
| /// <summary> |
| /// Shape style |
| /// </summary> |
| public eShapeStyle Style |
| { |
| get |
| { |
| string v = GetXmlNodeString(ShapeStylePath); |
| try |
| { |
| return (eShapeStyle)Enum.Parse(typeof(eShapeStyle), v, true); |
| } |
| catch |
| { |
| throw (new Exception(string.Format("Invalid shapetype {0}", v))); |
| } |
| } |
| set |
| { |
| string v = value.ToString(); |
| v = v.Substring(0, 1).ToLower(CultureInfo.InvariantCulture) + v.Substring(1, v.Length - 1); |
| SetXmlNodeString(ShapeStylePath, v); |
| } |
| } |
| ExcelDrawingFill _fill = null; |
| /// <summary> |
| /// Fill |
| /// </summary> |
| public ExcelDrawingFill Fill |
| { |
| get |
| { |
| if (_fill == null) |
| { |
| _fill = new ExcelDrawingFill(NameSpaceManager, TopNode, "xdr:sp/xdr:spPr"); |
| } |
| return _fill; |
| } |
| } |
| ExcelDrawingBorder _border = null; |
| /// <summary> |
| /// Border |
| /// </summary> |
| public ExcelDrawingBorder Border |
| { |
| get |
| { |
| if (_border == null) |
| { |
| _border = new ExcelDrawingBorder(NameSpaceManager, TopNode, "xdr:sp/xdr:spPr/a:ln"); |
| } |
| return _border; |
| } |
| } |
| string[] paragraphNodeOrder = new string[] { "pPr", "defRPr", "solidFill", "uFill", "latin", "cs", "r", "rPr", "t" }; |
| const string PARAGRAPH_PATH = "xdr:sp/xdr:txBody/a:p"; |
| ExcelTextFont _font=null; |
| public ExcelTextFont Font |
| { |
| get |
| { |
| if (_font == null) |
| { |
| XmlNode node = TopNode.SelectSingleNode(PARAGRAPH_PATH, NameSpaceManager); |
| if(node==null) |
| { |
| Text=""; //Creates the node p element |
| node = TopNode.SelectSingleNode(PARAGRAPH_PATH, NameSpaceManager); |
| } |
| _font = new ExcelTextFont(NameSpaceManager, TopNode, "xdr:sp/xdr:txBody/a:p/a:pPr/a:defRPr", paragraphNodeOrder); |
| } |
| return _font; |
| } |
| } |
| const string TextPath = "xdr:sp/xdr:txBody/a:p/a:r/a:t"; |
| /// <summary> |
| /// Text inside the shape |
| /// </summary> |
| public string Text |
| { |
| get |
| { |
| return GetXmlNodeString(TextPath); |
| } |
| set |
| { |
| SetXmlNodeString(TextPath, value); |
| } |
| |
| } |
| string lockTextPath = "xdr:sp/@fLocksText"; |
| /// <summary> |
| /// Lock drawing |
| /// </summary> |
| public bool LockText |
| { |
| get |
| { |
| return GetXmlNodeBool(lockTextPath, true); |
| } |
| set |
| { |
| SetXmlNodeBool(lockTextPath, value); |
| } |
| } |
| ExcelParagraphCollection _richText = null; |
| /// <summary> |
| /// Richtext collection. Used to format specific parts of the text |
| /// </summary> |
| public ExcelParagraphCollection RichText |
| { |
| get |
| { |
| if (_richText == null) |
| { |
| //XmlNode node=TopNode.SelectSingleNode(PARAGRAPH_PATH, NameSpaceManager); |
| //if (node == null) |
| //{ |
| // CreateNode(PARAGRAPH_PATH); |
| //} |
| _richText = new ExcelParagraphCollection(NameSpaceManager, TopNode, PARAGRAPH_PATH, paragraphNodeOrder); |
| } |
| return _richText; |
| } |
| } |
| const string TextAnchoringPath = "xdr:sp/xdr:txBody/a:bodyPr/@anchor"; |
| /// <summary> |
| /// Text Anchoring |
| /// </summary> |
| public eTextAnchoringType TextAnchoring |
| { |
| get |
| { |
| return GetTextAchoringEnum(GetXmlNodeString(TextAnchoringPath)); |
| } |
| set |
| { |
| SetXmlNodeString(TextAnchoringPath, GetTextAchoringText(value)); |
| } |
| } |
| const string TextAnchoringCtlPath = "xdr:sp/xdr:txBody/a:bodyPr/@anchorCtr"; |
| /// <summary> |
| /// Specifies the centering of the text box. |
| /// </summary> |
| public bool TextAnchoringControl |
| { |
| get |
| { |
| return GetXmlNodeBool(TextAnchoringCtlPath); |
| } |
| set |
| { |
| if (value) |
| { |
| SetXmlNodeString(TextAnchoringCtlPath, "1"); |
| } |
| else |
| { |
| SetXmlNodeString(TextAnchoringCtlPath, "0"); |
| } |
| } |
| } |
| const string TEXT_ALIGN_PATH = "xdr:sp/xdr:txBody/a:p/a:pPr/@algn"; |
| /// <summary> |
| /// How the text is aligned |
| /// </summary> |
| public eTextAlignment TextAlignment |
| { |
| get |
| { |
| switch(GetXmlNodeString(TEXT_ALIGN_PATH)) |
| { |
| case "ctr": |
| return eTextAlignment.Center; |
| case "r": |
| return eTextAlignment.Right; |
| case "dist": |
| return eTextAlignment.Distributed; |
| case "just": |
| return eTextAlignment.Justified; |
| case "justLow": |
| return eTextAlignment.JustifiedLow; |
| case "thaiDist": |
| return eTextAlignment.ThaiDistributed; |
| default: |
| return eTextAlignment.Left; |
| } |
| } |
| set |
| { |
| switch (value) |
| { |
| case eTextAlignment.Right: |
| SetXmlNodeString(TEXT_ALIGN_PATH, "r"); |
| break; |
| case eTextAlignment.Center: |
| SetXmlNodeString(TEXT_ALIGN_PATH, "ctr"); |
| break; |
| case eTextAlignment.Distributed: |
| SetXmlNodeString(TEXT_ALIGN_PATH, "dist"); |
| break; |
| case eTextAlignment.Justified: |
| SetXmlNodeString(TEXT_ALIGN_PATH, "just"); |
| break; |
| case eTextAlignment.JustifiedLow: |
| SetXmlNodeString(TEXT_ALIGN_PATH, "justLow"); |
| break; |
| case eTextAlignment.ThaiDistributed: |
| SetXmlNodeString(TEXT_ALIGN_PATH, "thaiDist"); |
| break; |
| default: |
| DeleteNode(TEXT_ALIGN_PATH); |
| break; |
| } |
| } |
| } |
| const string INDENT_ALIGN_PATH = "xdr:sp/xdr:txBody/a:p/a:pPr/@lvl"; |
| /// <summary> |
| /// Indentation |
| /// </summary> |
| public int Indent |
| { |
| get |
| { |
| return GetXmlNodeInt(INDENT_ALIGN_PATH); |
| } |
| set |
| { |
| if (value < 0 || value > 8) |
| { |
| throw(new ArgumentOutOfRangeException("Indent level must be between 0 and 8")); |
| } |
| SetXmlNodeString(INDENT_ALIGN_PATH, value.ToString()); |
| } |
| } |
| const string TextVerticalPath = "xdr:sp/xdr:txBody/a:bodyPr/@vert"; |
| /// <summary> |
| /// Vertical text |
| /// </summary> |
| public eTextVerticalType TextVertical |
| { |
| get |
| { |
| return GetTextVerticalEnum(GetXmlNodeString(TextVerticalPath)); |
| } |
| set |
| { |
| SetXmlNodeString(TextVerticalPath, GetTextVerticalText(value)); |
| } |
| } |
| |
| #endregion |
| #region "Private Methods" |
| private string ShapeStartXml() |
| { |
| StringBuilder xml = new StringBuilder(); |
| xml.AppendFormat("<xdr:nvSpPr><xdr:cNvPr id=\"{0}\" name=\"{1}\" /><xdr:cNvSpPr /></xdr:nvSpPr><xdr:spPr><a:prstGeom prst=\"rect\"><a:avLst /></a:prstGeom></xdr:spPr><xdr:style><a:lnRef idx=\"2\"><a:schemeClr val=\"accent1\"><a:shade val=\"50000\" /></a:schemeClr></a:lnRef><a:fillRef idx=\"1\"><a:schemeClr val=\"accent1\" /></a:fillRef><a:effectRef idx=\"0\"><a:schemeClr val=\"accent1\" /></a:effectRef><a:fontRef idx=\"minor\"><a:schemeClr val=\"lt1\" /></a:fontRef></xdr:style><xdr:txBody><a:bodyPr vertOverflow=\"clip\" rtlCol=\"0\" anchor=\"ctr\" /><a:lstStyle /><a:p></a:p></xdr:txBody>", _id, Name); |
| return xml.ToString(); |
| } |
| #endregion |
| internal new string Id |
| { |
| get { return Name + Text; } |
| } |
| } |
| } |