dotnet OpenXML 解析 PPT 图表 面积图入门
本文告诉大家如何使用 OpenXML 解析 PPT 的图表,以面积图为入门例子告诉大家 OpenXML 的存储
在 PPT 里面,有强大的图表功能,可以联动 Excel 展示数据。在 PPT 里面的图表和 Excel 的图表稍微有一些差别,本文只聊 PPT 的图表
如下图是本文将作为例子的图表
对应的数据如图
如上图可以看到在 PPT 里面的图表是可以使用 Excel 的数据,将 Excel 文件内嵌到 PPT 里面。但这不代表要解析图表的数据就一定需要先了解 Excel 的内容,本文将绕过对 Excel 的任何读取,通过 PPT 里面的内容拿到图表的数据
图表的组成
开始之前,还请先让我告诉大家一个图表元素包含的基础组件部分,也就是图表元素由哪些部分组成
横坐标轴 类别坐标轴数据
对于面积图来说,默认的面积图的横坐标就是类别的坐标轴数据,对应的 Excel 表格的第一列的内容,也就是 A B C D E 这些数据
在 OpenXML SDK 里面,采用 DocumentFormat.OpenXml.Drawing.Charts.CategoryAxisData
存放
本文以下将会告诉大家获取方法,这里只是写上类型,方便大家了解
纵坐标轴
对于默认面积图来说,纵坐标属于一个运行时属性,不会存放在 OpenXML 文档里面,需要根据每个系列的数值的最大值和最小值以及配置,计算出来纵坐标的内容,本文不会涉及具体的坐标轴计算方法
数据系列
在图表里面有数据系列的概念,每个系列的数据组成一个个的数据系列。对于大部分图表来说,数据层都是由一个个数据系列组成的
每个数据系列可以有自己的系列名称
系列名称大部分时候都放在图例里面,也就是图例里面的内容就是由系列名称提供的
在 OpenXML SDK 里面,采用 DocumentFormat.OpenXml.Drawing.Charts.SeriesText
存放
在图表里面,核心就是对数据的处理,系列的数据内容就是核心的
如图,面积图有两个数据系列,通过上面的 Excel 内容可以了解到两个系列的数据分别如下
系列 1:32,32,28,12,15
系列 2:12,12,12,21,28
本文将重点告诉大家如何解析图表的数据
效果
以下是本文的解析效果,可以解析出来图表的类别坐标轴数据,和各个系列的系列名称和系列数据
下面将告诉大家如何根据 OpenXML SDK 提供的方法读取到图表的内容
读取图表
在开始之前,还请大家先了解 OpenXml 读取 PPT 的基础。本文将在 C# dotnet 使用 OpenXml 解析 PPT 文件 的基础上进行开发
先读取 PPT 文档
var file = new FileInfo("Test.pptx");
using var presentationDocument = PresentationDocument.Open(file.FullName, false);
本文的测试文件和所有代码都可以在本文最后获取
在这份 Test.pptx 的图表是放在第一个页面,先获取页面,通过页面的元素获取到图表
var slide = presentationDocument.PresentationPart!.SlideParts.First().Slide;
在 OpenXML 里面的页面存放的图表的代码如下
<p:cSld>
<p:spTree>
<p:graphicFrame>
...
</p:graphicFrame>
</p:spTree>
</p:cSld>
图表也是一个元素,放在 SharpTree (p:spTree) 里面,作为 GraphicFrame (p:graphicFrame) 存放。但不能说 GraphicFrame 就是图表元素,在 OpenXML 的 GraphicFrame 是一个很通用的元素,如 OLE 元素或公式都会用到此元素
读取 GraphicFrame 的内容,如果能读取到 ChartReference (c:chart) 那就证明这个元素是图表元素
// 获取图表元素,在这份课件里,有一个面积图。以下使用 First 忽略细节,获取图表
var graphicFrame = slide.Descendants<GraphicFrame>().First();
// 获取到对应的图表信息,图表是引用的,内容不是放在 Slide 页面里面,而是放在独立的图表 xml 文件里
var graphic = graphicFrame.Graphic;
var graphicData = graphic?.GraphicData;
var chartReference = graphicData?.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.ChartReference>();
在 OpenXML 里,图表是引用的,内容不是放在 Slide 页面里面,而是放在独立的图表 xml 文件里。页面的代码如下
<p:graphicFrame>
<a:graphic>
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/chart">
<c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="rId2" />
</a:graphicData>
</a:graphic>
</p:graphicFrame>
根据 dotnet OpenXML 为什么资源使用 Relationship 引用 可以了解到,这里的图表引用,需要到 rels 文件里面获取关联的内容。在 OpenXml SDK 里,封装好了获取方法,获取时需要有两个参数,一个是 id 另一个是去哪里获取的 Part 内容。获取 id 的方法如下
// 获取到 id 也就是 `r:id="rId2"` 根据 Relationship 的描述,可以知道去 rels 文件里面获取关联的内容。在 OpenXml SDK 里,封装好了获取方法,获取时需要有两个参数,一个是 id 另一个是去哪里获取的 Part 内容
var id = chartReference?.Id?.Value;
在这份课件是图表元素放在页面上,可以通过页面去获取到图表元素的存储。在实际项目里,需要判断图表元素所在的是页面还是页面模版等,不能和以下代码写固定从页面获取
// 如果是放在模版里面,记得要用模版的 Part 去获取
var currentPart = slide.SlidePart!;
if (!currentPart.TryGetPartById(id!, out var openXmlPart))
{
// 在这份课件里,一定不会进入此分支
// 一定能从页面找到对应的资源内容也就是图表
return;
}
这里拿到的 openXmlPart
是 ChartPart 对象,这里面就存放了图表的信息
if (openXmlPart is not ChartPart chartPart)
{
// 这里拿到的一定是 ChartPart 对象,一定不会进入此分支。但是在实际项目的代码,还是要做这个判断
return;
}
这里的 ChartPart 对应的就是 charts\chartN.xml 文件。这里的 chartN.xml 表示的是 chart1.xml 或 chart2.xml 等文件
这个文件的存储内容大概如下
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<c:chartSpace>
<c:chart>
...
<c:plotArea>
...
</c:plotArea>
</c:chart>
</c:chartSpace>
读取图表首先需要获取 ChartSpace 对象,再获取到 Chart 对象。在 OpenXML SDK 里面,定义了很多个 Chart 类型,放在不同的命名空间,在获取时,推荐写全命名空间
using Chart = DocumentFormat.OpenXml.Drawing.Charts.Chart;
// 这里的 ChartPart 对应的就是 charts\chartN.xml 文件。这里的 chartN.xml 表示的是 chart1.xml 或 chart2.xml 等文件
var chartSpace = chartPart.ChartSpace;
// 这里的 Chart 是 DocumentFormat.OpenXml.Drawing.Charts.Chart 类型,在 OpenXmlSDK 里面,有多个同名的 Chart 类型,还请看具体的命名空间
/*
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<c:chartSpace>
<c:chart>
...
<c:plotArea>
...
</c:plotArea>
</c:chart>
</c:chartSpace>
*/
var chart = chartSpace.GetFirstChild<Chart>();
接着获取 PlotArea 对象,这里面就存放了图表的内容
using PlotArea = DocumentFormat.OpenXml.Drawing.Charts.PlotArea;
var chart = chartSpace.GetFirstChild<Chart>();
var plotArea = chart?.GetFirstChild<PlotArea>();
如本文的面积图就放在 PlotArea 元素里
<c:plotArea>
<c:areaChart>
...
</c:areaChart>
</c:plotArea>
在 Chart 里,有不同的图表类型,例如 BarChart Bar3DChart LineChart PieChart Pie3DChart OfPieChart 不水字数了,就是很多不同的图表。本文这里只获取面积图
var areaChart = plotArea?.GetFirstChild<AreaChart>();
if (areaChart == null)
{
// 在这份课件里,一定存在面积图,一定不会进入此分支
return;
}
获取到面积图,接下来就是读取面积图的数据系列
数据系列的存储代码如下
<c:plotArea>
<c:areaChart>
<c:ser>
...
</c:ser>
<c:ser>
...
</c:ser>
</c:areaChart>
</c:plotArea>
每个 DocumentFormat.OpenXml.Drawing.Charts.AreaChartSeries (c:ser) 就是一个系列的内容。一个图表里面可以有多个系列,每个系列包含下面数据
- 系列名
- 系列数据
- 类别轴上的数据
- 样式信息
样式信息里面包含了填充的画刷,如纯色填充。类别轴上的数据是面积图横坐标轴显示内容,每个系列都有,这是重复的数据,在 PPT 里,只取第一个系列的数据
数据系列里的横坐标轴的类别坐标轴数据,在 OpenXML 里面,是 DocumentFormat.OpenXml.Drawing.Charts.CategoryAxisData
类型,对应 c:cat
的内容
读取类别轴上的数据方法如下
foreach (var areaChartChildElement in areaChart.ChildElements)
{
// 获取系列
/*
<c:plotArea>
<c:areaChart>
<c:ser>
...
</c:ser>
<c:ser>
...
</c:ser>
</c:areaChart>
</c:plotArea>
*/
if (areaChartChildElement is DocumentFormat.OpenXml.Drawing.Charts.AreaChartSeries areaChartSeries)
{
// 类别轴上的数据 横坐标轴上的数据
var categoryAxisData = areaChartSeries.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.CategoryAxisData>()!;
}
}
在 OpenXML SDK 的存储如下
<c:plotArea>
<c:areaChart>
<c:ser>
<c:cat>
</c:cat>
</c:ser>
</c:areaChart>
</c:plotArea>
在类别轴上的数据存放的是数据引用,数据引用在 OpenXML 里面有多个不同的存储类型。例如 NumberReference 类型表示的是数值引用,例如 StringReference 表示字符串引用类型,在这份课件里面存放的是 StringReference 类型,以下代码只演示采用 StringReference 类型的读取方式,还请在具体项目,自行判断
var categoryAxisData = areaChartSeries.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.CategoryAxisData>()!;
var categoryAxisDataStringReference = categoryAxisData.GetFirstChild<StringReference>();
在 StringReference 里面,大部分都有两个部分,一个是公式,表示如何引用 Excel 的数据。通过公式读取 Excel 可以获取到正确的数据,但缺点是比较复杂。可以通过第二部分,也就是缓存数据部分读取,虽然读取缓存也许不对,不过优点在于简单
存储的代码如下
<c:cat>
<c:strRef>
<c:f>Sheet1!$A$2:$A$6</c:f>
<c:strCache>
<c:ptCount val="5" />
<c:pt idx="0">
<c:v>A</c:v>
</c:pt>
<c:pt idx="1">
<c:v>B</c:v>
</c:pt>
<c:pt idx="2">
<c:v>C</c:v>
</c:pt>
<c:pt idx="3">
<c:v>D</c:v>
</c:pt>
<c:pt idx="4">
<c:v>E</c:v>
</c:pt>
</c:strCache>
</c:strRef>
</c:cat>
获取公式的代码如下
var categoryAxisDataStringReference = categoryAxisData.GetFirstChild<StringReference>();
if (categoryAxisDataStringReference != null)
{
// 这个公式表示是从 Excel 哪个数据获取的,获取的方式比较复杂。这里还是先从缓存获取
var categoryAxisDataFormula = categoryAxisDataStringReference.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.Formula>();
}
读取缓存的方法如下
// 读取缓存
var categoryAxisDataStringCache = categoryAxisDataStringReference.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.StringCache>()!;
读取类别轴上的数据
var list = new List<string>();
foreach (var stringPoint in categoryAxisDataStringCache.Elements<DocumentFormat.OpenXml.Drawing.Charts.StringPoint>())
{
// 以下的 类别轴上的数据 横坐标轴上的数据,各个列项的名称
// 对于面积图来说,多个系列的列项都是相同的。尽管在 OpenXml 存储里面存放了两份,但以第零个系列的为准
var text = stringPoint.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.NumericValue>()!.Text;
list.Add(text);
}
上面代码的 list 就存放了读取类别轴上的数据,也就是 A B C D E 字符串
继续读取第二部分内容,系列的系列名称,也就是系列标题
系列标题在 OpenXML 里,使用 DocumentFormat.OpenXml.Drawing.Charts.SeriesText
表示,对应 c:tx
类型。在图表里面的数据大部分都采用引用的方式,引用里面基本都有两个部分,如 类别轴上的数据 有引用 Excel 的公式,和缓存
这里读取系列标题也是通过缓存读取,不会去解析 Excel 内容
// 获取系列标题,放心,可以不读取 Excel 的内容,通过缓存内容即可。但是缓存内容也许和 Excel 内容不对应
/*
<c:plotArea>
<c:areaChart>
<c:ser>
<c:tx>
<c:strRef>
<c:f>Sheet1!$B$1</c:f>
<c:strCache>
<c:ptCount val="1" />
<c:pt idx="0">
<c:v>系列 1</c:v>
</c:pt>
</c:strCache>
</c:strRef>
</c:tx>
...
</c:ser>
</c:areaChart>
</c:plotArea>
*/
var seriesText = areaChartSeries.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.SeriesText>()!;
var seriesTextStringReference = seriesText.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.StringReference>()!;
// 这个公式表示是从 Excel 哪个数据获取的,获取的方式比较复杂。这里还是先从缓存获取
var seriesTextFormula = seriesTextStringReference.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.Formula>();
使用缓存获取系列名称
// 有缓存的话,从缓存获取就可以,缓存内容也许和 Excel 内容不对应
/*
<c:strCache>
<c:ptCount val="1" />
<c:pt idx="0">
<c:v>系列 1</c:v>
</c:pt>
</c:strCache>
*/
var seriesTextStringCache = seriesTextStringReference.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.StringCache>();
if (seriesTextStringCache != null)
{
var seriesTextStringPoint = seriesTextStringCache.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.StringPoint>();
var numericValue = seriesTextStringPoint!.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.NumericValue>();
// 系列1 标题
var title = numericValue!.Text;
}
上面的 title
就是系列的标题,如上面图表,拿到的就是 系列1
或 系列2
字符串
完成获取系列的标题获取,下面开始获取系列的样式。系列的样式如系列的填充画刷,画刷是一个比较大的话题,本文使用的例子只用到纯色画刷
图表的系列样式存储采用的是 DocumentFormat.OpenXml.Drawing.Charts.ChartShapeProperties
类型,图表的形状属性的内容和 形状属性 的内容是差不多的
<c:plotArea>
<c:areaChart>
<c:ser>
<c:tx>
...
</c:tx>
<c:spPr>
<a:solidFill>
<a:srgbClr val="FF0000" />
</a:solidFill>
</c:spPr>
</c:ser>
</c:areaChart>
</c:plotArea>
获取系列的填充颜色
// 图表的形状属性的内容和 形状属性 的内容是差不多的
/*
<c:plotArea>
<c:areaChart>
<c:ser>
<c:tx>
...
</c:tx>
<c:spPr>
<a:solidFill>
<a:srgbClr val="FF0000" />
</a:solidFill>
</c:spPr>
</c:ser>
</c:areaChart>
</c:plotArea>
*/
var chartShapeProperties = areaChartSeries.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.ChartShapeProperties>()!;
// 获取画刷,画刷有好多不同的类型,这个课件只用了纯色
var solidFill = chartShapeProperties.GetFirstChild<SolidFill>()!;
// 画刷纯色颜色有很多个颜色表示方法,这个课件只用了 RGB 的纯色
var rgbColorModelHex = solidFill.GetFirstChild<DocumentFormat.OpenXml.Drawing.RgbColorModelHex>()!;
// 这就是这个系列的颜色
var colorValue = rgbColorModelHex.Val!.Value;
以上的 colorValue
就是这个系列的填充。不同的系列可以有不同的填充
接下来获取图表最核心的内容,系列的数据
在 PPT 里面,是允许数据为空的,如果是空,行为就是不绘制系列内容。本文使用的例子是存在数据,就没有判断数据为空
// 获取系列的值
/*
<c:plotArea>
<c:areaChart>
<c:ser>
<c:tx>
...
</c:tx>
<c:cat>
...
</c:cat>
<c:val>
<c:numRef>
<c:f>Sheet1!$B$2:$B$6</c:f>
<c:numCache>
<c:formatCode>General</c:formatCode>
<c:ptCount val="5" />
<c:pt idx="0">
<c:v>32</c:v>
</c:pt>
<c:pt idx="1">
<c:v>32</c:v>
</c:pt>
<c:pt idx="2">
<c:v>28</c:v>
</c:pt>
<c:pt idx="3">
<c:v>12</c:v>
</c:pt>
<c:pt idx="4">
<c:v>15</c:v>
</c:pt>
</c:numCache>
</c:numRef>
</c:val>
</c:ser>
<c:ser>
...
</c:ser>
</c:areaChart>
</c:plotArea>
*/
// 这就是系列里面最重要的数据。然而在 PPT 里面,是允许为空的,如果是空,行为就是不绘制系列内容
var valueList = new List<string>();
var values = areaChartSeries.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.Values>();
在面积图,数据理论上是数值类型。对应的是 NumberReference 引用,同样可以使用公式引用 Excel 数据,也可以采用缓存获取
var valuesNumberReference = values?.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.NumberReference>();
if (valuesNumberReference != null)
{
/*
<c:val>
<c:numRef>
<c:f>Sheet1!$B$2:$B$6</c:f>
<c:numCache>
<c:formatCode>General</c:formatCode>
<c:ptCount val="5" />
<c:pt idx="0">
<c:v>32</c:v>
</c:pt>
<c:pt idx="1">
<c:v>32</c:v>
</c:pt>
<c:pt idx="2">
<c:v>28</c:v>
</c:pt>
<c:pt idx="3">
<c:v>12</c:v>
</c:pt>
<c:pt idx="4">
<c:v>15</c:v>
</c:pt>
</c:numCache>
</c:numRef>
</c:val>
*/
// 这份课件一定存在 values 内容
// 和其他的一样,存在引用 Excel 的内容。这里同样也是采用缓存
var valuesFormula = valuesNumberReference.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.Formula>();
本文只采用读取缓存的方式。在缓存也有一个数据,表示数据如何格式化显示,例如通过格式化字符串告诉 PPT 如何格式化日期内容等。本文使用的例子写的是 General 表示不需要格式化
var valuesNumberingCache = valuesNumberReference.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.NumberingCache>()!;
// 通过 FormatCode 决定界面效果。这份课件是 General 表示不用格式化
var formatCode = valuesNumberingCache.FormatCode;
Debug.Assert(formatCode?.Text == "General");
接下来继续获取数据
var valueList = new List<string>();
foreach (var numericPoint in valuesNumberingCache.Elements<DocumentFormat.OpenXml.Drawing.Charts.NumericPoint>())
{
var numericValue = numericPoint.GetFirstChild<DocumentFormat.OpenXml.Drawing.Charts.NumericValue>()!;
var numericValueText = numericValue.Text;
valueList.Add(numericValueText);
}
通过上面例子,无论数据引用是数值引用还是字符串引用,具体的内容都是 DocumentFormat.OpenXml.Drawing.Charts.NumericValue
类型。如果不需要准确判断内容,可以采用获取此类型,简化逻辑
上面代码的 valueList
存放了系列数据内容
这就完成了读取图表的大部分数据内容
数据存储
本文期望大家了解 OpenXML 里对图表的存储方式。在 OpenXML 里面,图表是放在页面的一个元素,但是数据不放在页面上,页面上放的是引用。通过引用获取到图表的内容,对应的数据存储如下
<c:plotArea>
<c:areaChart>
<c:ser>
<!-- 系列的数据 -->
</c:ser>
<c:ser>
<c:tx>
<!-- 系列标题 -->
</c:tx>
<c:spPr>
<!-- 系列样式 -->
</c:spPr>
<c:cat>
<!-- 类别轴上的数据 -->
</c:cat>
<c:val>
<!-- 系列数据 -->
</c:val>
</c:ser>
</c:areaChart>
</c:plotArea>
以上是面积图的存储,面积图里面由多个系列组成。对于图表来说,最重要的数据就是每个系列的内容。系列里面包含了系列标题,系列样式,和类别轴上的数据和系列数据。其中类别轴上的数据只有第零个系列的有用,但是在 OpenXML 里每个系列都重复存放一份
在图表里存放的数据使用的是引用,可以用公式读取 Excel 的数据,也可以使用缓存。如果想要数据正确,是需要通过公式读取 Excel 的数据,如果想要读取 Excel 的数据,前置的是读取 PPT 里面内嵌的 Excel 内容,请看 dotnet OpenXML 读取 PPT 内嵌 xlsx 格式 Excel 表格的信息
图表还有其他的内容,如图表标题和样式等。以及图表的数据格式化展示逻辑,日期计算方法等,这些都没有放在本文告诉大家。将在后续博客告诉大家这些内容和行为,请看 Office 使用 OpenXML SDK 解析文档博客目录
代码
本文以上的测试文件和代码放在github 和 gitee 欢迎访问
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 2f266d20916f784662d84a98d60b7e1bd097d11d
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
获取代码之后,进入 MainWindow.xaml.cs 文件,在这个文件里就是本文的例子代码
更多
更多请看 Office 使用 OpenXML SDK 解析文档博客目录
dotnet OpenXML 解析 PPT 图表 面积图入门的更多相关文章
- dotnet OpenXML 读取 PPT 内嵌 ole 格式 Excel 表格的信息
在 Office 中,可以在 PPT 里面插入表格,插入表格有好多不同的方法,对应 OpenXML 文档存储的更多不同的方式.本文来介绍如何读取 PPT 内嵌 ole 格式的 xls+ 表格的方法 在 ...
- 使用 WPF 做个 PowerPoint 系列 基于 OpenXML 解析实现 PPT 文本描边效果
本文是使用 WPF 做个 PowerPoint 系列的博客,本文来告诉大家如何解析 PPT 里面的文本描边效果,在 WPF 应用中绘制出来,实现像素级相同 背景知识 在开始之前,期望你了解了 PPT ...
- dotnet OpenXML 转换 PathFillModeValues 为颜色特效
在 OpenXml 预设形状,有一些形状设置了 PathFillModeValues 枚举,此枚举提供了亮暗的蒙层特效.具体的特效是让形状选择一个画刷,在画刷上加上特效.如立体几何 Cube 形状,在 ...
- Python交互图表可视化Bokeh:4. 折线图| 面积图
折线图与面积图 ① 单线图.多线图② 面积图.堆叠面积图 1. 折线图--单线图 import numpy as np import pandas as pd import matplotlib.py ...
- 【Dotnet 工具箱】跨平台图表库 LiveCharts2
你好,这里是 Dotnet 工具箱,定期分享 Dotnet 有趣,实用的工具和组件,希望对您有用! LiveCharts2 LiveCharts2 是一个简单.灵活.交互式以及功能强大的跨平台图表库. ...
- javascript曲线图和面积图Line & Area chart控件功能及下载
Line & Area chart 控件是一款新型的.可用性极强的曲线图和面积图产品.一个您网站的访问者可以放大他感兴趣的一段区域,打开和关闭数值气球,并可显示和隐藏图表.您能创建简单.堆积. ...
- 06. Matplotlib 2 |折线图| 柱状图| 堆叠图| 面积图| 填图| 饼图| 直方图| 散点图| 极坐标| 图箱型图
1.基本图表绘制 plt.plot() 图表类别:线形图.柱状图.密度图,以横纵坐标两个维度为主同时可延展出多种其他图表样式 plt.plot(kind='line', ax=None, figsiz ...
- Java编辑PPT的折线图,与内嵌Excel联动
/** * 折线图的数据写入方法 * @param slide ppt图表 * @param index 折线图的下标 * @param data 需要填充的数据 * @param titles 内嵌 ...
- 初探ggplot2 geom__制作面积图
大家大概都对如下信息图并不陌生,该图用100%堆积面积图的方式来表现不同时期不同国家人数所占的比例.这是一种很有意思的表达方式,而面积图也是很常用的数据图表,现在让我们一起来看看如何在R里用g ...
- React中用EChart写面积图
UED出的设计图如下: 实际展示效果如下: 调取的数据如下: "staffCountList":[ { "time":"2019-12-24 17: ...
随机推荐
- 【LeetCode刷题】744. 寻找比目标字母大的最小字母
744. 寻找比目标字母大的最小字母(点击跳转LeetCode) 给你一个排序后的字符列表 letters ,列表中只包含小写英文字母.另给出一个目标字母 target,请你寻找在这一有序列表里比目标 ...
- MYSQL 同步到ES 如何设计架构保持一致性
简单使用某个组件很容易,但是一旦要搬到生产上就要考虑各种各样的异常,保证你方案的可靠性,可恢复性就是我们需要思考的问题.今天来聊聊我们部门在 MYSQL 同步到ES的方案设计. 在面对复杂条件查询时, ...
- FreeRTOS教程10 低功耗
1.准备材料 正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) Keil µVision5 IDE(MDK-Arm) 野火DAP仿真器 XCO ...
- vscode中vue代码提示插件
由来 基于(Vue 3 Snippets,Vue VSCode Snippets)插件集成而来,因为这俩插件目前没有集成最新vue代码片段,且集成内容相对较少,于是这个插件就诞生了 插件提示跟vue写 ...
- Games101--作业2
说明 该作业主要想实现两个三角形的绘制 绘制结果走样 按照课上所讲的方法,对包围盒里面的所有像素进行判断是否在三角形内,然后着色,这样的结果由于采样频率的问题将导致边缘走样现象的发生 if(!insi ...
- apue 文章集锦
与 apue 相关的一系列文章比较庞杂,按原书目录整理了一下,形成目录,方便系统性阅读. 另外这些文章是在我快读完的时候开始写的,之前的一些章节还多有遗漏,后面慢慢补上. chapter 1: UNI ...
- arch xfce启用自动挂载usb设备,自动访问usb设备,自动连接usb设备
1.安装gvfs sudo pacman -S gvfs GVFS(Gnome Virtual File System)是一个用于 GNOME 桌面环境的虚拟文件系统,它提供了一种统一的方式来访问和管 ...
- MySQL字符集和语言
字符集和校对顺序 数据库表被用来存储和检索数据.不同的语言和字符集需要以不同的方式存储和检索.因此,MySQL需要适应不同的字符集(不同的字母和字符),适应不同的排序和检索数据的方法. 在讨论多种 ...
- 【AI】『Suno』哎呦不错呦,AI界的周董,快来创作你的歌曲吧!
前言 缘由 Suno AI的旋风终于还是吹到了音乐圈 事情起因: 朋友说他练习时长两天半,用Suno发布了首张AI音乐专辑.震惊之余,第一反应是音乐圈门槛也这么低了,什么妖魔鬼怪都可以进军了嘛! 好奇 ...
- #矩阵乘法,线段树#CF575A Fibonotci
题目 分析 \(K\)那么大肯定是矩阵乘法, 带修改可以用线段树单点修改, 转移矩阵类似于斐波那契数列, 这题思维难度不大,细节很多,需要很长时间QWQ 时间复杂度\(O(mlog_2K)\),具体注 ...