You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

.NET Core中使用NPOI修改散点图样式的方法(移除连线、调整标记形状/颜色等)

.NET Core中使用NPOI修改散点图样式的方法(移除连线、调整标记形状/颜色等)

我之前用NPOI做散点图的时候也踩过这个坑!默认的散点之间会自动连上线条,密集的点直接糊成一团,完全失去了散点图的意义。下面就给你说解决方法,包括移除连线,还有一些常用的样式调整,都是我实际试过能用的:

首先,先解决移除散点间连线的问题。NPOI的高层图表API没有直接封装这个选项,我们需要直接操作底层的OpenXML对象(就是那些以CT_开头的类)。在你的代码里,创建完series并设置标题后,添加下面这段代码:

// 移除散点之间的连线
using NPOI.OpenXmlFormats.Drawing.Spreadsheet;

// 获取底层的散点series对象
var ctScatterSer = series.GetCTScatterSer();

// 初始化形状属性(如果不存在的话)
if (ctScatterSer.spPr == null)
{
    ctScatterSer.spPr = new CT_ShapeProperties();
}
if (ctScatterSer.spPr.ln == null)
{
    ctScatterSer.spPr.ln = new CT_LineProperties();
}

// 设置线条为无填充(也就是隐藏连线)
ctScatterSer.spPr.ln.noFill = new CT_NoFillProperties();

这样就能把那些烦人的连线去掉了,只剩下独立的散点。

接下来是散点标记的样式调整,比如改形状、颜色、大小,同样是操作CT对象:

// 调整散点标记的形状(可选:circle、square、diamond、triangle等)
if (ctScatterSer.marker == null)
{
    ctScatterSer.marker = new CT_Marker();
}
ctScatterSer.marker.symbol = CT_MarkerStyleVal.circle;

// 设置标记的填充颜色(这里用的是十六进制FF5733,也就是橙色)
if (ctScatterSer.marker.solidFill == null)
{
    ctScatterSer.marker.solidFill = new CT_SolidColorFillProperties();
}
ctScatterSer.marker.solidFill.srgbClr = new CT_SRgbColor();
ctScatterSer.marker.solidFill.srgbClr.val = System.Text.Encoding.ASCII.GetBytes("FF5733");

// 设置标记的大小(单位是pt的1/100,比如800就是8pt)
ctScatterSer.marker.size = new CT_MarkerSize();
ctScatterSer.marker.size.val = 800;

如果想要修改图表标题的样式(比如加粗、改字号),也可以用类似的方式操作图表的底层对象:

// 调整标题的字体大小和加粗
var ctTitle = chart.GetCTChart().title;
if (ctTitle.tx.rich.p == null)
{
    ctTitle.tx.rich.p = new CT_TextParagraph[] { new CT_TextParagraph() };
}
var titleTextPr = ctTitle.tx.rich.p[0].rPr = new CT_TextCharacterProperties();
titleTextPr.sz = new CT_PositiveSize2D();
titleTextPr.sz.val = 1400; // 14pt
titleTextPr.b = new CT_Boolean();
titleTextPr.b.val = true; // 加粗

把这些代码整合到你的AddTempErrChart方法里,最终的代码大概是这样:

public static void AddTempErrChart(XSSFWorkbook wb, XSSFSheet sh, int r0, int c0, int nRows, int xOffset, int yOffset) 
{ 
    var draw = sh.CreateDrawingPatriarch() as XSSFDrawing; 
    var anchor = draw.CreateAnchor(0, 0, 0, 0, c0, r0 + nRows + 2, c0 + 6, r0 + nRows + 17); 
    var chart = draw.CreateChart(anchor) as XSSFChart; 
    chart.SetTitle("Temp vs FitPresErr"); 

    var bottom = chart.ChartAxisFactory.CreateValueAxis(AxisPosition.Bottom); 
    var left = chart.ChartAxisFactory.CreateValueAxis(AxisPosition.Left); 

    var data = chart.ChartDataFactory.CreateScatterChartData<double, double>(); 

    // data ranges 
    var xRange = new CellRangeAddress(r0 + 1, r0 + nRows, c0 + xOffset, c0 + xOffset); 
    var yRange = new CellRangeAddress(r0 + 1, r0 + nRows, c0 + yOffset, c0 + yOffset); 
    var xs = DataSources.FromNumericCellRange(sh, xRange); 
    var ys = DataSources.FromNumericCellRange(sh, yRange); 

    var series = data.AddSeries(xs, ys); 
    series.SetTitle("run"); 

    // ------------------ 样式修改部分开始 ------------------
    using NPOI.OpenXmlFormats.Drawing.Spreadsheet;

    // 移除散点间的连线
    var ctScatterSer = series.GetCTScatterSer();
    if (ctScatterSer.spPr == null)
    {
        ctScatterSer.spPr = new CT_ShapeProperties();
    }
    if (ctScatterSer.spPr.ln == null)
    {
        ctScatterSer.spPr.ln = new CT_LineProperties();
    }
    ctScatterSer.spPr.ln.noFill = new CT_NoFillProperties();

    // 调整散点标记:圆形、橙色、8pt大小
    if (ctScatterSer.marker == null)
    {
        ctScatterSer.marker = new CT_Marker();
    }
    ctScatterSer.marker.symbol = CT_MarkerStyleVal.circle;
    if (ctScatterSer.marker.solidFill == null)
    {
        ctScatterSer.marker.solidFill = new CT_SolidColorFillProperties();
    }
    ctScatterSer.marker.solidFill.srgbClr = new CT_SRgbColor();
    ctScatterSer.marker.solidFill.srgbClr.val = System.Text.Encoding.ASCII.GetBytes("FF5733");
    ctScatterSer.marker.size = new CT_MarkerSize();
    ctScatterSer.marker.size.val = 800;

    // 调整标题样式:14pt加粗
    var ctTitle = chart.GetCTChart().title;
    if (ctTitle.tx.rich.p == null)
    {
        ctTitle.tx.rich.p = new CT_TextParagraph[] { new CT_TextParagraph() };
    }
    var titleTextPr = ctTitle.tx.rich.p[0].rPr = new CT_TextCharacterProperties();
    titleTextPr.sz = new CT_PositiveSize2D();
    titleTextPr.sz.val = 1400;
    titleTextPr.b = new CT_Boolean();
    titleTextPr.b.val = true;
    // ------------------ 样式修改部分结束 ------------------

    chart.Plot(data, bottom, left); 
}

最后补充一句:因为NPOI的图表高层API封装得比较基础,很多精细的样式调整都需要直接操作底层的CT_*类,这些类对应的是Office Open XML的规范,如果你需要更复杂的样式(比如坐标轴网格线、背景色),可以去查ECMA-376的图表部分,或者直接看NPOI源码里的这些CT类的定义,找对应的属性调整就行。

内容来源于stack exchange

火山引擎 最新活动