| @@ -0,0 +1,102 @@ | |||
| using System; | |||
| using System.Xml.Linq; | |||
| namespace Novacode | |||
| { | |||
| /// <summary> | |||
| /// This element contains the 2-D bar or column series on this chart. | |||
| /// 21.2.2.16 barChart (Bar Charts) | |||
| /// </summary> | |||
| public class BarChart : Chart | |||
| { | |||
| /// <summary> | |||
| /// Specifies the possible directions for a bar chart. | |||
| /// </summary> | |||
| public BarDirection BarDirection | |||
| { | |||
| get | |||
| { | |||
| return XElementHelpers.GetValueToEnum<BarDirection>( | |||
| ChartXml.Element(XName.Get("barDir", DocX.c.NamespaceName))); | |||
| } | |||
| set | |||
| { | |||
| XElementHelpers.SetValueFromEnum<BarDirection>( | |||
| ChartXml.Element(XName.Get("barDir", DocX.c.NamespaceName)), value); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Specifies the possible groupings for a bar chart. | |||
| /// </summary> | |||
| public BarGrouping BarGrouping | |||
| { | |||
| get | |||
| { | |||
| return XElementHelpers.GetValueToEnum<BarGrouping>( | |||
| ChartXml.Element(XName.Get("grouping", DocX.c.NamespaceName))); | |||
| } | |||
| set | |||
| { | |||
| XElementHelpers.SetValueFromEnum<BarGrouping>( | |||
| ChartXml.Element(XName.Get("grouping", DocX.c.NamespaceName)), value); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Specifies that its contents contain a percentage between 0% and 500%. | |||
| /// </summary> | |||
| public Int32 GapWidth | |||
| { | |||
| get | |||
| { | |||
| return Convert.ToInt32( | |||
| ChartXml.Element(XName.Get("gapWidth", DocX.c.NamespaceName)).Attribute(XName.Get("val")).Value); | |||
| } | |||
| set | |||
| { | |||
| if ((value < 1) || (value > 500)) | |||
| throw new ArgumentException("GapWidth lay between 0% and 500%!"); | |||
| ChartXml.Element(XName.Get("gapWidth", DocX.c.NamespaceName)).Attribute(XName.Get("val")).Value = value.ToString(); | |||
| } | |||
| } | |||
| protected override XElement CreateChartXml() | |||
| { | |||
| return XElement.Parse( | |||
| @"<c:barChart xmlns:c=""http://schemas.openxmlformats.org/drawingml/2006/chart""> | |||
| <c:barDir val=""col""/> | |||
| <c:grouping val=""clustered""/> | |||
| <c:gapWidth val=""150""/> | |||
| </c:barChart>"); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Specifies the possible directions for a bar chart. | |||
| /// 21.2.3.3 ST_BarDir (Bar Direction) | |||
| /// </summary> | |||
| public enum BarDirection | |||
| { | |||
| [XmlName("col")] | |||
| Column, | |||
| [XmlName("bar")] | |||
| Bar | |||
| } | |||
| /// <summary> | |||
| /// Specifies the possible groupings for a bar chart. | |||
| /// 21.2.3.4 ST_BarGrouping (Bar Grouping) | |||
| /// </summary> | |||
| public enum BarGrouping | |||
| { | |||
| [XmlName("clustered")] | |||
| Clustered, | |||
| [XmlName("percentStacked")] | |||
| PercentStacked, | |||
| [XmlName("stacked")] | |||
| Stacked, | |||
| [XmlName("standard")] | |||
| Standard | |||
| } | |||
| } | |||
| @@ -7,16 +7,17 @@ using System.IO; | |||
| using System.IO.Packaging; | |||
| using System.Collections; | |||
| using System.Drawing; | |||
| using System.Reflection; | |||
| namespace Novacode | |||
| { | |||
| /// <summary> | |||
| /// Represents a Chart in this document. | |||
| /// Represents every Chart in this document. | |||
| /// </summary> | |||
| public class Chart | |||
| public abstract class Chart | |||
| { | |||
| private XElement ChartXml; | |||
| private XElement ChartRootXml; | |||
| protected XElement ChartXml { get; private set; } | |||
| protected XElement ChartRootXml { get; private set; } | |||
| public XDocument Xml { get; private set; } | |||
| @@ -33,9 +34,47 @@ namespace Novacode | |||
| } | |||
| } | |||
| public virtual void AddSeries(Series series) | |||
| { | |||
| ChartXml.Add(series.Xml); | |||
| } | |||
| private ChartLegend legend; | |||
| public ChartLegend Legend { get { return legend; } } | |||
| /// <summary> | |||
| /// Specifies how blank cells shall be plotted on a chart | |||
| /// </summary> | |||
| public DisplayBlanksAs DisplayBlanksAs | |||
| { | |||
| get | |||
| { | |||
| String value = ChartRootXml.Element(XName.Get("dispBlanksAs", DocX.c.NamespaceName)).Attribute(XName.Get("val")).Value; | |||
| switch (value) | |||
| { | |||
| case "gap": return DisplayBlanksAs.Gap; | |||
| case "span": return DisplayBlanksAs.Span; | |||
| case "zero": return DisplayBlanksAs.Zero; | |||
| default: throw new NotImplementedException("This DisplayBlanksAsType was not implement!"); | |||
| } | |||
| } | |||
| set | |||
| { | |||
| String newValue; | |||
| switch (value) | |||
| { | |||
| case DisplayBlanksAs.Gap: newValue = "gap"; | |||
| break; | |||
| case DisplayBlanksAs.Span: newValue = "span"; | |||
| break; | |||
| case DisplayBlanksAs.Zero: newValue = "zero"; | |||
| break; | |||
| default: throw new NotImplementedException("This DisplayBlanksAsType was not implement!"); | |||
| } | |||
| ChartRootXml.Element(XName.Get("dispBlanksAs", DocX.c.NamespaceName)).Attribute(XName.Get("val")).Value = newValue; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Create an Chart for this document | |||
| /// </summary> | |||
| @@ -68,16 +107,15 @@ namespace Novacode | |||
| <c:showPercent val=""0""/> | |||
| <c:showBubbleSize val=""0""/> | |||
| </c:dLbls>"); | |||
| XElement axIDcat = XElement.Parse( | |||
| @"<c:axId val=""154227840"" xmlns:c=""http://schemas.openxmlformats.org/drawingml/2006/chart""/>"); | |||
| XElement axIDval = XElement.Parse( | |||
| @"<c:axId val=""148921728"" xmlns:c=""http://schemas.openxmlformats.org/drawingml/2006/chart""/>"); | |||
| ChartXml = XElement.Parse( | |||
| @"<c:barChart xmlns:c=""http://schemas.openxmlformats.org/drawingml/2006/chart""> | |||
| <c:barDir val=""col""/> | |||
| <c:grouping val=""clustered""/> | |||
| <c:gapWidth val=""150""/> | |||
| <c:axId val=""148921728""/> | |||
| <c:axId val=""154227840""/> | |||
| </c:barChart>"); | |||
| ChartXml.Add(dLbls); | |||
| ChartXml = CreateChartXml(); | |||
| ChartXml.Add(dLbls); | |||
| ChartXml.Add(axIDval); | |||
| ChartXml.Add(axIDcat); | |||
| XElement catAx = XElement.Parse( | |||
| @"<c:catAx xmlns:c=""http://schemas.openxmlformats.org/drawingml/2006/chart""> | |||
| @@ -122,10 +160,8 @@ namespace Novacode | |||
| ChartXml, catAx, valAx); | |||
| } | |||
| public void AddSeries(Series series) | |||
| { | |||
| ChartXml.Add(series.Xml); | |||
| } | |||
| protected abstract XElement CreateChartXml(); | |||
| public void AddLegend() | |||
| { | |||
| @@ -147,6 +183,8 @@ namespace Novacode | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Represents a chart series | |||
| /// </summary> | |||
| @@ -339,7 +377,8 @@ namespace Novacode | |||
| } | |||
| /// <summary> | |||
| /// Specifies the possible positions for a legend | |||
| /// Specifies the possible positions for a legend. | |||
| /// 21.2.3.24 ST_LegendPos (Legend Position) | |||
| /// </summary> | |||
| public enum ChartLegendPosition | |||
| { | |||
| @@ -349,4 +388,15 @@ namespace Novacode | |||
| Right, | |||
| TopRight | |||
| } | |||
| /// <summary> | |||
| /// Specifies the possible ways to display blanks. | |||
| /// 21.2.3.10 ST_DispBlanksAs (Display Blanks As) | |||
| /// </summary> | |||
| public enum DisplayBlanksAs | |||
| { | |||
| Gap, | |||
| Span, | |||
| Zero | |||
| } | |||
| } | |||
| @@ -0,0 +1,54 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Xml.Linq; | |||
| namespace Novacode | |||
| { | |||
| /// <summary> | |||
| /// This element contains the 2-D line chart series. | |||
| /// 21.2.2.97 lineChart (Line Charts) | |||
| /// </summary> | |||
| public class LineChart: Chart | |||
| { | |||
| /// <summary> | |||
| /// Specifies the kind of grouping for a column, line, or area chart. | |||
| /// </summary> | |||
| public Grouping Grouping | |||
| { | |||
| get | |||
| { | |||
| return XElementHelpers.GetValueToEnum<Grouping>( | |||
| ChartXml.Element(XName.Get("grouping", DocX.c.NamespaceName))); | |||
| } | |||
| set | |||
| { | |||
| XElementHelpers.SetValueFromEnum<Grouping>( | |||
| ChartXml.Element(XName.Get("grouping", DocX.c.NamespaceName)), value); | |||
| } | |||
| } | |||
| protected override XElement CreateChartXml() | |||
| { | |||
| return XElement.Parse( | |||
| @"<c:lineChart xmlns:c=""http://schemas.openxmlformats.org/drawingml/2006/chart""> | |||
| <c:grouping val=""standard""/> | |||
| </c:lineChart>"); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Specifies the kind of grouping for a column, line, or area chart. | |||
| /// 21.2.2.76 grouping (Grouping) | |||
| /// </summary> | |||
| public enum Grouping | |||
| { | |||
| [XmlName("percentStacked")] | |||
| PercentStacked, | |||
| [XmlName("stacked")] | |||
| Stacked, | |||
| [XmlName("standard")] | |||
| Standard | |||
| } | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Xml.Linq; | |||
| namespace Novacode | |||
| { | |||
| /// <summary> | |||
| /// This element contains the 2-D pie series for this chart. | |||
| /// 21.2.2.141 pieChart (Pie Charts) | |||
| /// </summary> | |||
| public class PieChart : Chart | |||
| { | |||
| protected override XElement CreateChartXml() | |||
| { | |||
| return XElement.Parse( | |||
| @"<c:pieChart xmlns:c=""http://schemas.openxmlformats.org/drawingml/2006/chart""> | |||
| </c:pieChart>"); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| using System; | |||
| using System.Linq; | |||
| using System.Reflection; | |||
| using System.Xml.Linq; | |||
| namespace Novacode | |||
| { | |||
| internal static class XElementHelpers | |||
| { | |||
| /// <summary> | |||
| /// Get value from XElement and convert it to enum | |||
| /// </summary> | |||
| /// <typeparam name="T">Enum type</typeparam> | |||
| internal static T GetValueToEnum<T>(XElement element) | |||
| { | |||
| if (element == null) | |||
| throw new ArgumentNullException("element"); | |||
| String value = element.Attribute(XName.Get("val")).Value; | |||
| foreach (T e in Enum.GetValues(typeof(T))) | |||
| { | |||
| FieldInfo fi = typeof(T).GetField(e.ToString()); | |||
| if (fi.GetCustomAttributes(typeof(XmlNameAttribute), false).Count() == 0) | |||
| throw new Exception(String.Format("Attribute 'XmlNameAttribute' is not assigned to {0} fields!", typeof(T).Name)); | |||
| XmlNameAttribute a = (XmlNameAttribute)fi.GetCustomAttributes(typeof(XmlNameAttribute), false).First(); | |||
| if (a.XmlName == value) | |||
| return e; | |||
| } | |||
| throw new ArgumentException("Invalid element value!"); | |||
| } | |||
| /// <summary> | |||
| /// Convert value to xml string and set it into XElement | |||
| /// </summary> | |||
| /// <typeparam name="T">Enum type</typeparam> | |||
| internal static void SetValueFromEnum<T>(XElement element, T value) | |||
| { | |||
| if (element == null) | |||
| throw new ArgumentNullException("element"); | |||
| if (value == null) | |||
| throw new ArgumentNullException("value"); | |||
| FieldInfo fi = typeof(T).GetField(value.ToString()); | |||
| if (fi.GetCustomAttributes(typeof(XmlNameAttribute), false).Count() == 0) | |||
| throw new Exception(String.Format("Attribute 'XmlNameAttribute' is not assigned to {0} fields!", typeof(T).Name)); | |||
| XmlNameAttribute a = (XmlNameAttribute)fi.GetCustomAttributes(typeof(XmlNameAttribute), false).First(); | |||
| element.Attribute(XName.Get("val")).Value = a.XmlName; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// This attribute applied to enum's fields for definition their's real xml names in DocX file. | |||
| /// </summary> | |||
| /// <example> | |||
| /// public enum MyEnum | |||
| /// { | |||
| /// [XmlName("one")] // This means, that xml element has 'val="one"' | |||
| /// ValueOne, | |||
| /// [XmlName("two")] // This means, that xml element has 'val="two"' | |||
| /// ValueTwo | |||
| /// } | |||
| /// </example> | |||
| [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] | |||
| internal sealed class XmlNameAttribute : Attribute | |||
| { | |||
| /// <summary> | |||
| /// Real xml name | |||
| /// </summary> | |||
| public String XmlName { get; private set; } | |||
| public XmlNameAttribute(String xmlName) | |||
| { | |||
| XmlName = xmlName; | |||
| } | |||
| } | |||
| } | |||
| @@ -87,7 +87,11 @@ | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Compile Include="Border.cs" /> | |||
| <Compile Include="Chart.cs" /> | |||
| <Compile Include="Charts\BarChart.cs" /> | |||
| <Compile Include="Charts\Chart.cs" /> | |||
| <Compile Include="Charts\LineChart.cs" /> | |||
| <Compile Include="Charts\PieChart.cs" /> | |||
| <Compile Include="Charts\XElementHelpers.cs" /> | |||
| <Compile Include="Container.cs" /> | |||
| <Compile Include="Footers.cs" /> | |||
| <Compile Include="Footer.cs" /> | |||
| @@ -54,9 +54,18 @@ namespace Examples | |||
| using (DocX document = DocX.Create(@"docs\Chart.docx")) | |||
| { | |||
| // Create chart. | |||
| Chart c = new Chart(); | |||
| BarChart c = new BarChart(); | |||
| c.BarDirection = BarDirection.Column; | |||
| c.BarGrouping = BarGrouping.Standard; | |||
| c.GapWidth = 400; | |||
| c.AddLegend(ChartLegendPosition.Bottom, false); | |||
| PieChart cc = new PieChart(); | |||
| cc.AddLegend(ChartLegendPosition.Bottom, false); | |||
| LineChart ccc = new LineChart(); | |||
| ccc.AddLegend(ChartLegendPosition.Bottom, false); | |||
| // Create data. | |||
| List<ChartData> company1 = new List<ChartData>(); | |||
| company1.Add(new ChartData() { Mounth = "January", Money = 100 }); | |||
| @@ -72,14 +81,19 @@ namespace Examples | |||
| s1.Color = Color.GreenYellow; | |||
| s1.Bind(company1, "Mounth", "Money"); | |||
| c.AddSeries(s1); | |||
| ccc.AddSeries(s1); | |||
| Series s2 = new Series("Apple"); | |||
| s2.Bind(company2, "Mounth", "Money"); | |||
| c.AddSeries(s2); | |||
| c.AddSeries(s2); | |||
| cc.AddSeries(s2); | |||
| ccc.AddSeries(s2); | |||
| // Insert chart into document | |||
| document.InsertParagraph("Diagram").FontSize(20); | |||
| document.InsertParagraph("BeforeText"); | |||
| document.InsertChartInTheDevelopment(c); | |||
| document.InsertChartInTheDevelopment(cc); | |||
| document.InsertChartInTheDevelopment(ccc); | |||
| document.InsertParagraph("AfterText"); | |||
| document.Save(); | |||
| } | |||