找回密码
 立即注册

QQ登录

只需一步,快速开始

Richard.Ma 讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2024-1-22 11:47  /   查看:530  /  回复:0
本帖最后由 Richard.Ma 于 2024-1-22 12:10 编辑

在通过GCExcel代码自动化构建可视化图表的过程中,一些用户需要复制图表系列的配置,包括样式。以及系列中包含的元素及样式,如:数据标签,趋势线,误差线 等等。

本教程提供了代码复制同一个Chart的一个系列的样式及元素到另一个系列,以提供相同的展示效果。同时,大家通过代码可以更好的理解系列中的样式和元素的结构。

首先,需要明确以下的前提条件

1.不是所有的内容都是可以复制的,不同系列一些属性肯定是不同的,否则图表会出错或者不同系列本身也就没有意义了。例如:系列名称,系列的引用数据区域等等

2.不是所有的Chart类型都有多个系列的,例如饼图,散点图,股票图,瀑布图等图表类型,都是用来展示单个系列的。

3.一个图表内的多个系列如果是不同的Chart类型,例如一个是柱形图,一个是点线图。那么相关的样式选项是不同的。因此复制时,应该先同步系列的类型。

4.对于填充,边框等等的样式,除了给series本身设置外,还需要注意给系列中的每个数据点设置。


具体的代码可以参考文末,提供了一个CloneSeries的静态方法。可以复制系列
需要调用的时候,可以通过这句代码
  1. ChartHelper.CloneSeries(chart.SeriesCollection[1], chart.SeriesCollection[0]);
复制代码

具体效果:

复制配置前
image.png388712462.png

复制配置后
image.png221849364.png


以下代码为C#代码,适用于GCExcel.NET组件,GCExcel Java版本和.NET版本的接口命名规则很类似。如有需要可以参考编写对应代码。

CloneSeries方法↓↓↓↓↓
  1. public static class ChartHelper
  2. {
  3.     public static void CloneSeries(ISeries newSer, ISeries oldSer)
  4.     {
  5.         newSer.ChartType = oldSer.ChartType;

  6.         //判断图表类型,当前仅测试了柱状图,折线图,面积图,条形图
  7.         if (newSer.ChartType != ChartType.ColumnClustered &&
  8.             newSer.ChartType != ChartType.Line &&
  9.             newSer.ChartType != ChartType.LineMarkers &&
  10.             newSer.ChartType != ChartType.Area &&
  11.             newSer.ChartType != ChartType.BarClustered
  12.             )
  13.         {
  14.             Exception ex = new Exception("Clone Series operation is not supported for this chart type");
  15.             throw ex;
  16.         }
  17.       

  18.         newSer.AxisGroup = oldSer.AxisGroup;
  19.         newSer.PictureType = oldSer.PictureType;
  20.         newSer.Smooth = oldSer.Smooth;


  21.         //Format
  22.         CloneFill(newSer.Format.Fill, oldSer.Format.Fill);
  23.         CloneLine(newSer.Format.Line, oldSer.Format.Line);
  24.         Clone3D(newSer.Format.ThreeD, oldSer.Format.ThreeD);//阴影/发光/柔化/3D等可以自己再设置
  25.         newSer.InvertIfNegative = oldSer.InvertIfNegative;
  26.         if (newSer.InvertIfNegative)
  27.         {
  28.             CloneColor(newSer.InvertColor, oldSer.InvertColor);
  29.         }
  30.             

  31.         //Points Format
  32.         for (int i = 0; i < Math.Min(newSer.Points.Count, oldSer.Points.Count); i++)
  33.         {
  34.             CloneFill(newSer.Points[i].Format.Fill, oldSer.Points[i].Format.Fill);
  35.             CloneLine(newSer.Points[i].Format.Line, oldSer.Points[i].Format.Line);
  36.         }

  37.         //MarkerFormat for LineMarkers
  38.         if (newSer.ChartType == ChartType.LineMarkers)
  39.         {
  40.             newSer.ShowMeanMarkers = oldSer.ShowMeanMarkers;
  41.             newSer.MarkerSize = oldSer.MarkerSize;
  42.             newSer.MarkerStyle = oldSer.MarkerStyle;
  43.             CloneFill(newSer.MarkerFormat.Fill, oldSer.MarkerFormat.Fill);
  44.             CloneLine(newSer.MarkerFormat.Line, oldSer.MarkerFormat.Line);
  45.             for (int i = 0; i < Math.Min(newSer.Points.Count, oldSer.Points.Count); i++)
  46.             {
  47.                 CloneFill(newSer.Points[i].MarkerFormat.Fill, oldSer.Points[i].MarkerFormat.Fill);
  48.                 CloneLine(newSer.Points[i].MarkerFormat.Line, oldSer.Points[i].MarkerFormat.Line);
  49.             }
  50.         }


  51.         //Series DataLabels
  52.         newSer.HasDataLabels = oldSer.HasDataLabels;
  53.         if (newSer.HasDataLabels)
  54.         {
  55.             CloneFill(newSer.DataLabels.Format.Fill, oldSer.DataLabels.Format.Fill);
  56.             CloneLine(newSer.DataLabels.Format.Line, oldSer.DataLabels.Format.Line);
  57.             CloneFont(newSer.DataLabels.Font, oldSer.DataLabels.Font);
  58.             CloneLabelOptions(newSer.DataLabels, oldSer.DataLabels, newSer.ChartType);

  59.             //Point DataLabels
  60.             for (int i = 0; i < Math.Min(newSer.DataLabels.Count, oldSer.DataLabels.Count); i++)
  61.             {
  62.                 CloneFill(newSer.DataLabels[i].Format.Fill, oldSer.DataLabels[i].Format.Fill);
  63.                 CloneLine(newSer.DataLabels[i].Format.Line, oldSer.DataLabels[i].Format.Line);
  64.                 CloneFont(newSer.DataLabels[i].Font, oldSer.DataLabels[i].Font);
  65.             }
  66.         }
  67.         //Trendlines
  68.         newSer.Trendlines.All((tl) => { tl.Delete(); return true; });
  69.         oldSer.Trendlines.All((tl) => { newSer.Trendlines.Add(); return true; });
  70.         for (int i = 0; i < Math.Min(newSer.Trendlines.Count, oldSer.Trendlines.Count); i++)
  71.         {
  72.             CloneLine(newSer.Trendlines[i].Format.Line, oldSer.Trendlines[i].Format.Line);
  73.             newSer.Trendlines[i].Type = oldSer.Trendlines[i].Type;
  74.             if (newSer.Trendlines[i].Type == TrendlineType.MovingAvg)
  75.                 newSer.Trendlines[i].Period = oldSer.Trendlines[i].Period;
  76.             if (newSer.Trendlines[i].Type == TrendlineType.Polynomial)
  77.                 newSer.Trendlines[i].Order = oldSer.Trendlines[i].Order;
  78.             newSer.Trendlines[i].Backward = oldSer.Trendlines[i].Backward;
  79.             newSer.Trendlines[i].Forward = oldSer.Trendlines[i].Forward;
  80.             newSer.Trendlines[i].Intercept = oldSer.Trendlines[i].Intercept;
  81.             newSer.Trendlines[i].DisplayEquation = oldSer.Trendlines[i].DisplayEquation;
  82.             newSer.Trendlines[i].DisplayRSquared = oldSer.Trendlines[i].DisplayRSquared;
  83.         }

  84.         //ErrorBar
  85.         if (oldSer.HasErrorBars)
  86.         {
  87.             newSer.HasErrorBars = oldSer.HasErrorBars;
  88.             CloneErrorBar(newSer.YErrorBar, oldSer.YErrorBar);
  89.         }
  90.     }

  91.     private static void CloneFill(IFillFormat newFill, IFillFormat oldFill)
  92.     {

  93.         switch (oldFill.Type)
  94.         {
  95.             case FillType.Solid:

  96.                 newFill.Color.ColorType = oldFill.Color.ColorType;
  97.                 switch (newFill.Color.ColorType)
  98.                 {
  99.                     case SolidColorType.RGB:
  100.                         newFill.Color.RGB = oldFill.Color.RGB;
  101.                         break;
  102.                     case SolidColorType.Theme:
  103.                         newFill.Color.ObjectThemeColor = oldFill.Color.ObjectThemeColor;
  104.                         newFill.Color.TintAndShade = oldFill.Color.TintAndShade;
  105.                         break;
  106.                 }
  107.                 newFill.Color.Brightness = oldFill.Color.Brightness;
  108.                 newFill.Transparency = oldFill.Transparency;
  109.                 newFill.Solid();
  110.                 break;
  111.             case FillType.Gradient:
  112.                 newFill.PresetGradient(oldFill.GradientStyle, oldFill.GradientVariant, oldFill.PresetGradientType);
  113.                 foreach (IGradientStop item in oldFill.GradientStops)
  114.                 {
  115.                     newFill.GradientStops.Insert(item.Color.RGB.ToArgb(), item.Position, item.Transparency);
  116.                 }
  117.                 newFill.GradientPathType = oldFill.GradientPathType;
  118.                 newFill.GradientAngle = oldFill.GradientAngle;
  119.                 break;
  120.             case FillType.Picture:
  121.                 //newFill.UserPicture("");   //不提供获取接口

  122.                 newFill.PatternColor.RGB = oldFill.PatternColor.RGB;
  123.                 newFill.PatternColor.ObjectThemeColor = oldFill.PatternColor.ObjectThemeColor;
  124.                 newFill.PatternColor.ColorType = oldFill.PatternColor.ColorType;
  125.                 newFill.PatternColor.TintAndShade = oldFill.PatternColor.TintAndShade;
  126.                 newFill.PatternColor.Brightness = oldFill.PatternColor.Brightness;
  127.                 newFill.Transparency = oldFill.Transparency;
  128.                 break;
  129.             case FillType.Textured:
  130.                 newFill.PresetTextured(oldFill.PresetTexture);
  131.                 newFill.TextureAlignment = oldFill.TextureAlignment;
  132.                 newFill.TextureOffsetX = oldFill.TextureOffsetX;
  133.                 newFill.TextureOffsetY = oldFill.TextureOffsetY;
  134.                 break;
  135.             case FillType.Patterned:
  136.                 newFill.Patterned(oldFill.Pattern);
  137.                 newFill.PatternColor.ColorType = oldFill.PatternColor.ColorType;
  138.                 switch (newFill.PatternColor.ColorType)
  139.                 {
  140.                     case SolidColorType.RGB:
  141.                         newFill.Color.RGB = oldFill.Color.RGB;
  142.                         newFill.PatternColor.RGB = oldFill.PatternColor.RGB;
  143.                         break;
  144.                     case SolidColorType.Theme:
  145.                         newFill.Color.ObjectThemeColor = oldFill.Color.ObjectThemeColor;
  146.                         newFill.Color.TintAndShade = oldFill.Color.TintAndShade;
  147.                         newFill.PatternColor.ObjectThemeColor = oldFill.PatternColor.ObjectThemeColor;
  148.                         newFill.PatternColor.TintAndShade = oldFill.PatternColor.TintAndShade;
  149.                         break;
  150.                 }
  151.                 newFill.PatternColor.Brightness = oldFill.PatternColor.Brightness;
  152.                 newFill.Transparency = oldFill.Transparency;
  153.                 break;
  154.         }
  155.         newFill.Visible = oldFill.Visible;
  156.     }
  157.     private static void CloneLine(ILineFormat newLine, ILineFormat oldLine)
  158.     {
  159.         newLine.Style = oldLine.Style;
  160.         newLine.Weight = oldLine.Weight;
  161.         newLine.DashStyle = oldLine.DashStyle;
  162.         newLine.Transparency = oldLine.Transparency;
  163.         switch (oldLine.Type)
  164.         {
  165.             case FillType.Solid:
  166.                 newLine.Solid();
  167.                 CloneColor(newLine.Color, oldLine.Color);
  168.                 break;
  169.             case FillType.Gradient:


  170.                 newLine.PresetGradient(oldLine.GradientStyle, oldLine.GradientVariant, PresetGradientType.Ocean);
  171.                 foreach (IGradientStop item in oldLine.GradientStops)
  172.                     newLine.GradientStops.Insert(item.Color.RGB.ToArgb(), item.Position, item.Transparency);
  173.                 newLine.GradientAngle = oldLine.GradientAngle;
  174.                 break;


  175.         }
  176.         newLine.Visible = oldLine.Visible;
  177.     }
  178.     private static void CloneColor(IColorFormat newColor, IColorFormat oldColor)
  179.     {
  180.         newColor.ColorType = oldColor.ColorType;
  181.         switch (newColor.ColorType)
  182.         {
  183.             case SolidColorType.RGB:
  184.                 newColor.RGB = oldColor.RGB;
  185.                 break;
  186.             case SolidColorType.Theme:
  187.                 newColor.ObjectThemeColor = oldColor.ObjectThemeColor;
  188.                 newColor.TintAndShade = oldColor.TintAndShade;
  189.                 break;
  190.         }
  191.         newColor.Brightness = oldColor.Brightness;
  192.     }
  193.     private static void CloneFont(IFontFormat newFont, IFontFormat oldFont)
  194.     {
  195.         newFont.Color.ColorType = oldFont.Color.ColorType;
  196.         switch (newFont.Color.ColorType)
  197.         {
  198.             case SolidColorType.RGB:
  199.                 newFont.Color.RGB = oldFont.Color.RGB;
  200.                 break;
  201.             case SolidColorType.Theme:
  202.                 newFont.Color.ObjectThemeColor = oldFont.Color.ObjectThemeColor;
  203.                 newFont.Color.TintAndShade = oldFont.Color.TintAndShade;
  204.                 break;
  205.         }
  206.         newFont.Bold = oldFont.Bold;
  207.         newFont.Italic = oldFont.Italic;
  208.         newFont.Color.Brightness = oldFont.Color.Brightness;
  209.         newFont.Size = oldFont.Size;
  210.         newFont.Name = oldFont.Name;
  211.         newFont.Underline = oldFont.Underline;
  212.         newFont.Strikethrough = oldFont.Strikethrough;
  213.         newFont.Superscript = oldFont.Superscript;
  214.         newFont.Subscript = oldFont.Subscript;
  215.         newFont.Italic = oldFont.Italic;

  216.     }
  217.     private static void CloneLabelOptions(IDataLabels newLabels, IDataLabels oldLabels, ChartType chartType)
  218.     {
  219.         newLabels.ShowValue = oldLabels.ShowValue;
  220.         newLabels.ShowCategoryName = oldLabels.ShowCategoryName;
  221.         newLabels.ShowSeriesName = oldLabels.ShowSeriesName;
  222.         newLabels.ShowLegendKey = oldLabels.ShowLegendKey;
  223.         newLabels.ShowLeaderLines = oldLabels.ShowLeaderLines;
  224.         newLabels.Separator = oldLabels.Separator;
  225.         newLabels.Position = oldLabels.Position;
  226.         newLabels.NumberFormat = oldLabels.NumberFormat;
  227.         if (chartType == ChartType.Pie || chartType == ChartType.Doughnut)
  228.             newLabels.ShowPercentage = oldLabels.ShowPercentage;
  229.         if (chartType == ChartType.Bubble)
  230.             newLabels.ShowBubbleSize = oldLabels.ShowBubbleSize;

  231.         for (int i = 0; i < Math.Min(newLabels.Count, oldLabels.Count); i++)
  232.         {
  233.             newLabels[i].Position = oldLabels[i].Position;
  234.             newLabels[i].ShowValue = oldLabels[i].ShowValue;
  235.             newLabels[i].ShowCategoryName = oldLabels[i].ShowCategoryName;
  236.             newLabels[i].ShowSeriesName = oldLabels[i].ShowSeriesName;
  237.             newLabels[i].ShowLegendKey = oldLabels[i].ShowLegendKey;
  238.             newLabels[i].Separator = oldLabels[i].Separator;
  239.             newLabels[i].Position = oldLabels[i].Position;
  240.             newLabels[i].Text = oldLabels[i].Text;
  241.             newLabels[i].NumberFormat = oldLabels[i].NumberFormat;
  242.             if (chartType == ChartType.Pie || chartType == ChartType.Doughnut)
  243.                 newLabels[i].ShowPercentage = oldLabels[i].ShowPercentage;
  244.             if (chartType == ChartType.Bubble)
  245.                 newLabels[i].ShowBubbleSize = oldLabels[i].ShowBubbleSize;
  246.         }
  247.     }
  248.     private static void CloneErrorBar(IErrorBar newErr, IErrorBar oldErr)
  249.     {
  250.         newErr.Type = oldErr.Type;
  251.         newErr.Amount = oldErr.Amount;
  252.         newErr.EndStyle = oldErr.EndStyle;
  253.         newErr.ValueType = oldErr.ValueType;
  254.         switch (newErr.ValueType)
  255.         {
  256.             case ErrorBarType.Custom:
  257.                 newErr.Minus = oldErr.Minus;
  258.                 newErr.Plus = oldErr.Plus;
  259.                 break;
  260.         }
  261.         CloneLine(newErr.Format.Line, oldErr.Format.Line);
  262.     }
  263.     private static void Clone3D(IThreeDFormat newo3d, IThreeDFormat old3d)
  264.     {

  265.     }

  266. }
复制代码





0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部