ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 73082|回复: 125

[原创] 玩转VBA窗体图表——MSChart控件详细教程

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2019-1-22 15:35 | 显示全部楼层 |阅读模式
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖已被收录到知识树中,索引项:控件
本帖最后由 ivccav 于 2019-1-23 18:11 编辑

之前写过在工作表中用VBA画图表,http://club.excelhome.net/thread-1417686-1-1.html
现在说说怎么在窗体上画图表,使用的控件是MSChart,感觉比在工作表中画图更容易些。

MSChart是微软一款免费的图表控件,也可能是微软最好用的一款图表控件,其特点是在数组中构建好数据,赋值给控件,控件生成图表。这对于一些不喜欢在EXCEL中处理数据的朋友来说,是很好的选择,特别是有些特殊图表,需要添加很多辅助列,会破坏原有数据的布局。因为MSChart接受数组作为数据源,因此,可以方便的使用EXCEL、数据库,甚至是自己虚拟出来的数据创建图表。本帖主要涉及:


1.图表对象模型
    1.1 控件属性
    1.2 Plot对象
    1.3 Axis对象
        1.3.1 AxisGrid对象
        1.3.2 AxisScale对象
        1.3.3 AxisTitle对象
        1.3.4 CategoryScale对象
        1.3.5 ValueScale 对象
        1.3.6 DataGrid 对象
        1.3.7 Intersection 对象
        1.3.8 Label 对象
        1.3.9 Tick对象
        1.4 SeriesCollection集合
        1.4.1 DataPoint 对象
        1.4.2 DataPointLabel 对象
        1.4.3 StatLine 对象
        1.4.4 Backdrop 对象
    1.5 总结

2. 图表实践
    2.1 堆叠图表
    2.2切片图表
    2.3 组合图表
    2.4 动态散点图
    2.5 图表缩放
    2.6 图表保存和打印
        2.6.1 保存图表
        2.6.2 打印图表


附件: 电子文档、源代码及所用控件.zip (1.37 MB, 下载次数: 6977)


在我们的常规印象中,图表应该是这样的:

组合图-2.png

其实图表是可以动的:

切片-3.gif

动态散点图.gif

甚至,连教学文档也是可以很直观的:

动态1.gif

动态2.gif

动态3.gif





补充内容 (2019-5-14 19:56):
VBA MSChart控件中文手册(帮助文件)下载:http://club.excelhome.net/thread-1477219-1-1.html

评分

30

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-1-22 15:36 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
先抢个沙发,呵呵

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-1-22 15:41 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
MSChart对象模型图.png
MSChart控件对象模型

1.图表对象模型

1.1 控件属性

MSChart控件包括:Plot、Backdrop、Footnote、Title和Legend对象,Plot是图表绘图区,是最重要的对象,Backdrop描述在图表或图表元素后面的阴影、图案或图片,Footnote是注脚,Title是标题,Legend是图例。Backdrop和Footnote用得很少,Title和Legend使用简单,就标题和图例,设置起来没有难度,唯一需要重点关注的是Plot对象。
MSChart的重要属性:ChartType和ChartData,ChartType属性返回或设置用于显示图表的图表类型,支持的图表类型如表1:
控件属性-表1.png

经过多次试验,发现组合图不能组合散点图,想组合一些特殊的图表变得不可行。

ChartData是一个数组,用于保存图表的数据和行、列标签。ChartData数组的索引基于0,第0行数据用于保存列标签(等效于图例),第0列用于保存行标签。ChartData数组具有一定判断能力,如果你定义的arr数组的第一列不是字符串,控件会自动添加R1、R2……行标签,如果arr数组的第一行不是字符串,控件会自动添加C1、C2……列标签(系列名称,和图例Legend是一个意思),如图1所示。把单元格区域A1:B10赋值给数组arr,然后把arr赋值给控件的属性ChartData,再输出到单元格G1:I11,数据多了一行和一列。

控件属性-图1.png
图1

输出的代码为:
Private Sub UserForm_Initialize()
    Dim arr()
    arr = Range("a1").CurrentRegion
    With MSChart1
        .ChartData = arr
        Range("g1").Resize(UBound(.ChartData) - LBound(.ChartData) + 1, _
            UBound(.ChartData, 2) - LBound(.ChartData, 2) + 1) = .ChartData
    End With
End Sub

细心的朋友应该会发现,arr定义为arr(),一个变体型数组,不能是VBA中常用的Dim arr,把arr定义成变体型变量,否则提示类型错误。当然,也不能定义为单精度数组Dim arr!()或双精度数组Dim arr#(),因为VBA也不接受把单元格区域赋值给非变体型数组。ChartData是基于0的数组,所以要用上标减去下标,并加1.

用ChartData也可以方便的把图表数据输出,和普通数组的用法一样,不再赘叙。
如果不使用数组赋值,而是自己虚构一个,可以使用如下代码:
With MSChart1
   .ColumnCount = 8
   .RowCount = 8
   For c = 1 To 8
      For r = 1 To 8
         .Column = c
         .Row = r
         .Data = Rnd()
      Next
   Next
End With

上边的代码构建了一个8行8列的图表,其效果和使用数组是一样的。另外使用ColumnCount属性可以动态的添加新系列,如:.ColumnCount= .ColumnCount+1就给图表新增了一个系列,可以通过赋值,绘制图表。这时只需要循环列8就行了(不能使用ChartData对单个数据点赋值,否则EXCEL应用程序会立即崩溃!):
With MSChart1
   .ColumnCount = 9
    For r = 1 To 8
       .Row = r
       .Data = Rnd()
    Next
End With

1.2 Plot对象

Plot对象表示图表显示的区域,是MSChart最重要的对象。其下包括Axis、Backdrop、SeriesCollection、Light、LocationRect、View3D、Wall和Plotbase对象。Axis 对象代表图表的 x 、 y 和 z 轴(3D类型时可见),BackDrop 对象代表坐标轴后面的区域,Light 对象代表图表的环境光和边缘光,LocationRect 对象代表图表的位置,SeriesCollection 对象代表系列的集合,View3D 对象代表立体图像的正视图和旋转图,Wall 对象代表三维图表中 y 坐标轴所在的平面区域,Plotbase对象代表图表中正下方区域的外观(基座)。重要的对象是:Axis和SeriesCollection,后面会单独讲到,其他对象用得不多。
Plot对象的UniformAxis属性指定图表的所有值坐标轴的单位刻度是否一致,一般要设置为FALSE,即每个坐标轴的单位刻度不一致。


TA的精华主题

TA的得分主题

 楼主| 发表于 2019-1-22 15:49 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助

1.3 Axis对象

Axis对象表示图表上的所有坐标轴。其下包括AxisGrid、AxisScale、AxisTitle、CategoryScale、Intersection、Labels、Pen、Tick和ValueScale 对象。如图2所示:
Axis对象-图1.png

引用坐标轴的方式如:
MSChart1.Plot.Axis(VtChAxisIdX)
其中VtChAxisIdX为X坐标轴ID,坐标轴ID共有4个常数:
Axis对象-表1.png

1.3.1 AxisGrid对象

AxisGrid对象代表坐标轴的网格线,所有与网格线相关的属性都在这里设置。网格线分主网格线和次网格线。MajorPen描述主坐标轴网格线的外观,MinorPen描述次坐标轴网格线的外观,其实这两个属性都是对Pen对象的引用。图表上所有的线段或边框的颜色及线型由Pen对象(画笔)绘制,而另一个对象Brush(画刷)决定图表元素的填充类型和颜色。
Pen对象的风格可为:
AxisGrid对象-表1.png

可以用MSChart1.Plot.Axis(VtChAxisIdX).AxisGrid.MajorPen.style = VtPenStyleNull取消显示X轴的主网格线,不显示次网格线用MinorPen,其他坐标轴的设置改变坐标轴ID即可。Pen对象的VtColor属性决定画笔的颜色,而其Width属性决定画笔的宽度,单位磅。

Brush 对象设置比较复杂,不同风格的画刷,设置不同。画刷风格为:
AxisGrid对象-表2.png

Solid风格的画刷(为了区别Pen对象(画笔),Brush对象改叫画刷)只需要设置Brush 对象的FillColor属性,用于指定填充颜色。Null画刷为透明色,设置什么也看不到,别白费表情了。如果指定画刷为Pattern和Hatched,还需要选择画刷的图案,两种风格画刷的图案是不同的,Pattern的可选图案为:
AxisGrid对象-表3.png

Hatched的可选图案为:
AxisGrid对象-表4.png

画刷图案用Brush对象的Index属性指定,绘制图案的颜色由PatternColor属性指定。当然,网格线AxisGrid是不能设置Brush的,在这里提出,是为了区别Pen和Brush。

1.3.2 AxisScale对象

AxisScale对象控制如何在坐标轴上绘制图表数值。有4个属性:Hide、LogBase、PercentBasis和Type 属性。Hide决定是否隐藏图表的坐标轴,如隐藏X坐标轴:
MSChart1.Plot.Axis(VtChAxisIdX).AxisScale.Hide = TRUE
坐标轴(包括刻度标签、刻度标记、轴标题)会被隐藏起来。
LogBase和PercentBasis由Type 属性确定。Type 属性决定坐标轴的类型,可选值:
AxisScale对象-表1.png
Type的默认类型为Linear,即使用线性刻度绘制图表值。

如果坐标轴类型为Logarithmic,LogBase属性设置在对数坐标轴上绘制图表数值时使用的对数底数,缺省的底数为 10,有效的取值范围从 2 到 100。
如果坐标轴类型为Percent,PercentBasis属性设置在百分比坐标轴上用来绘制图表数值的百分比类型:

AxisScale对象-表2.png


TA的精华主题

TA的得分主题

 楼主| 发表于 2019-1-22 15:53 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助


1.3.3 AxisTitle对象

AxisTitle对象设置图表的坐标轴标题,包括文本、字体、颜色和对齐方式,等等,设置并不复杂,不会深入讲解。附件中的示例文件,对AxisTitle对象的所有属性都有设置演示。

显示或隐藏坐标轴标题:
MSChart1.Plot.Axis(VtChAxisIdX).AxisTitle.Visible = TRUE

设置坐标轴标题字体:
MSChart1.Plot.Axis(VtChAxisIdX).AxisTitle.VtFont.Name = “宋体”
MSChart1.Plot.Axis(VtChAxisIdX).AxisTitle .VtFont.Size = 16
MSChart1.Plot.Axis(VtChAxisIdX).AxisTitle.VtFont.VtColor.Set 255,0,0

设置坐标轴标题文字布局由TextLayout对象完成:
MSChart1.Plot.Axis(VtChAxisIdX).AxisTitle.TextLayout.WordWrap=TRUE
MSChart1.Plot.Axis(VtChAxisIdX).AxisTitle.TextLayout.HorzAlignment
MSChart1.Plot.Axis(VtChAxisIdX).AxisTitle.TextLayout. VertAlignment
MSChart1.Plot.Axis(VtChAxisIdX).AxisTitle.TextLayout. Orientation

AxisTitle对象-B1.png

VtOrientation 常数提供了以下放置文本的选项。

AxisTitle对象-B2.png

1.3.4 CategoryScale对象

CategoryScale对象决定分类坐标轴的刻度。CategoryScale对象和ValueScale 对象容易混淆,ValueScale 对象决定坐标轴显示数值时所用的刻度。一条坐标轴既可以是分类坐标轴,也可以是值坐标轴,除了XY散点图,X轴一般都是作为分类坐标轴,Y轴作为值坐标轴,分类坐标轴的刻度是等分的,XY散点图中,X轴也是值坐标轴,刻度就是实际的数值。CategoryScale对象和ValueScale 对象非常重要,虽然它们都只有4-5个属性,要重点理解。
CategoryScale对象有4个属性:Auto、DivisionsPerLabel、DivisionsPerTick 和LabelTick属性。Auto 属性指示是否自动为坐标轴决定刻度,如果不希望控件自动决定,把该值设置为FALSE。DivisionsPerLabel 属性设置刻度标签之间跳过的部分数,DivisionsPerTick 属性设置主刻度之间跳过的部分数,两者经常设置为相同的值。LabelTick 属性指示分类坐标轴标签是否位于坐标轴刻度标记的中心。下面的示例设置分类坐标轴的比例属性:

With MSChart1.Plot.Axis(VtChAxisIdX)
   .CategoryScale.Auto = False '设置为人工缩放。
   .CategoryScale.DivisionsPerLabel = 2 '每两个单位显示标签。
   .CategoryScale.DivisionsPerTick = 2 '每两个单位显示刻度。
   .CategoryScale.LabelTick = True '在刻度标记顶端显示标签。
End With

1.3.5 ValueScale 对象

        ValueScale 对象决定坐标轴显示数值时所用的刻度。ValueScale 对象有5个属性:Auto、MajorDivision 、Maximum 、Minimum和MinorDivision 属性。
        Auto 属性决定是否使用自动调整刻度的特性来显示坐标轴的数值。MajorDivision 属性设置在坐标轴上显示的主刻度的数目,MSChart控件会根据Maximum 和Minimum属性设置的值等分坐标轴主刻度数量为MajorDivision指定的数字。MinorDivision 属性设置在坐标轴上每一格主刻度显示的次要刻度线的数目。每格主刻度显示的次刻度数量设置为0,则是不显示,设置为1是和主刻度重合,设置为2以上才有效果。Maximum 属性设置图表坐标轴的最大值或终止值。Minimum 属性设置图表坐标轴的最小值或起始值。下面示例设置XY散点图各坐标轴的ValueScale属性,因为XY散点图的X轴和Y轴都是值坐标轴,数据见附件源代码:

Private Sub UserForm_Initialize()
Dim arr()
arr = Range("a1:b200")
With MSChart1
    .TitleText = "变化趋势图"
    .Title.VtFont.VtColor.Blue = 255
    .Plot.Axis(VtChAxisIdX).AxisTitle.Text = "时间(单位:秒)"
    .Plot.SeriesCollection(1).Pen.Width = 20
    .Plot.SeriesCollection(1).Pen.Style = VtPenStyleSolid
    With .Plot.Axis(VtChAxisIdX).ValueScale
        .Auto = False
        .Maximum = 10
        .Minimum = 0
        .MajorDivision = 6
        .MinorDivision = 0
    End With
    .Plot.Axis(VtChAxisIdX).AxisGrid.MajorPen.Style = VtPenStyleDotted
    With .Plot.Axis(VtChAxisIdY).ValueScale
        .Auto = False
        .Maximum = 400
        .Minimum = -800
        .MajorDivision = 12
        .MinorDivision = 0
    End With
    .Plot.Axis(VtChAxisIdY).AxisGrid.MajorPen.Style = VtPenStyleDotted
    .Plot.UniformAxis = False
    .ChartType = VtChChartType2dXY
    .ChartData = arr
End With
End Sub


TA的精华主题

TA的得分主题

 楼主| 发表于 2019-1-22 15:56 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助


1.3.6 DataGrid 对象

DataGrid对象表示一个虚拟矩阵,它包含该 MSChart 控件的标签和数据点,言外之意,所有的图表标签和数据值都可以通过它进行修改,主要用于设置二级标签的文本,一般并不会修改数据,因为图表是用来发现规律的,修改数据的方式并不可取。DataGrid 对象由行和列组成,可以在该矩阵中添加和删除行、列以及标签以改变该图表的外观。下面的示例设置一个三维条形图表的图表参数,用随机数据填充图表并为数据网格列分配标签。

Private Sub Command1_Click()
   Dim rowLabelCount, columnLabelCount, rowCount As Integer
   Dim columnCount, labelIndex, Column, Row As Integer
   MSChart1.ChartType = VtChChartType3dBar
   With MSChart1.DataGrid
   '使用方法设置图表参数。
      rowLabelCount = 2’ 第二级行标签
      columnLabelCount = 2’ 第二级列标签
      rowCount = 6’行数
      columnCount = 6’列数
      .SetSize RowLabelCount, columnLabelCount, RowCount, ColumnCount
      .RandomDataFill’随机填充数据。
      labelIndex = 2
      column = 1’然后为第二级分配标签。
      .ColumnLabel(column, labelIndex) = "Product 1"
      column = 4
      .ColumnLabel(column, labelIndex) = "Product 2"
      row = 1
      .RowLabel(row, labelIndex) = "1994"
      row = 4
      .RowLabel(row, labelIndex) = "1995"
   End With
End Sub

ColumnCount 属性:返回或设置与图表关联的当前数据网格中的列数。

ColumnLabel 属性:返回或设置与图表关联的网格中数据列的标签。其语法为:
object.ColumnLabel( column, labelIndex ) [= text ],参数说明如下:
column标识特定的数据列,列编号时从 1 开始,由左向右依次编号,任何包含标签的列不作为数据列计数。
labelIndex标识特定的标签,如果对该列有多个列标签级别,则必须标识其中之一,列标签从 1 开始,从左向右依次编号。
Text指示列标签文本。

ColumnLabelCount属性:返回或设置与图表关联的数据网格中的列的标签级别数。设置此属性可以添加或删除数据网格列上的标签级别。从1开始、自下而上编号列标签级别,从顶部添加或减少级别。

RowCount 属性 :返回或设置与图表关联的数据网格每一列的行数。

RowLabel 属性:返回或设置与图表关联的当前数据网格中的特定行标签。其语法为:
object.RowLabel ( row, labelIndex ) [ = text ],参数说明如下:
row指定行。行从 1 开始、由顶端向底端依次编号。
labelIndex指定特定的行标签级别。行标签从 1 开始、由顶端向底端依次编号。
Text 指定行标签的文本。

RowLabelCount 属性:返回或设置与图表关联的数据网格行标签的级别数。通过设置该属性来添加或减少数据网格的行标签级别。行标签的级别从 1 开始,从右往左进行编号。标签的添加或减少均在左边进行。

DeleteColumnLabels 方法:从与图表关联的数据网格中删除数据列的标签级。其语法:
object.DeleteColumnLabels (labelIndex, count) ,参数说明如下:
labelIndex标识要删除的第一级标签编号。列标签从 1 开始,由底端向顶端依次编号。
count指定要删除的标签级别数。要删除的列从 labelIndex 标识的列开始向上计算。


DeleteColumns 方法:在与图表关联的数据网格中删除数据列以及与它们关联的标签。其语法:
object.DeleteColumns (column, count) ,参数说明如下:
column标识特定的数据列。列从 1 开始、由左向右依次编号。
count指定要删除的列数。

DeleteRowLabels 方法:从与图表关联的数据网格的数据行中删除标签级。其语法:
object.DeleteRowLabels (labelIndex, count) ,参数说明如下:
labelIndex指定要删除的第一级标签编号。行标签从 1 开始,由左向右依次编号。
count指定要删除的标签级别编号。要删除的行标签从 labelIndex 标识的行开始向左计算。

DeleteRows 方法:从与图表关联的数据网格中删除数据行及与它们关联的标签。其语法:
object.DeleteRows (row, count) ,参数说明如下:
row标识特定的数据行。行从 1 开始、由顶端向底端依次编号。
count指定要删除的行数。

GetData 方法:在与图表关联的数据网格中返回特定数据点中的当前存储数值。其语法:
object.GetData (row, column, dataPoint, nullFlag) ,参数说明如下:
row标识包含数据点数值的行。
column标识包含数据点数值的列。
dataPoint数据点的数值。
nullFlag指示数据点数值是否为空值。

InsertColumnLabels 方法:在与图表关联的数据网格的数据列中插入标签级。其语法:
object.InsertColumnLabels (labelIndex, count) ,参数说明如下:
labelIndex标识要插入的第一级标签编号。列标签级从 1 开始、由底端向顶端依次编号。
count指定要插入的标签级数。要插入的列数从由 labelIndex 标识的列开始向上计算。

InsertColumns 方法:在与图表关联的数据网格中添加一个或多个数据列。其语法:
object.InsertColumns (column, count) ,参数说明如下:
column标识特定的数据列。列从 1 开始、由左向右依次编号。
Count指定要插入的列数。

InsertRowLabels 方法:在与图表关联的数据网格的数据行中插入标签级。其语法:
object.InsertRowLabels (labelIndex, count) ,参数说明如下:
labelIndex 标识要插入的第一级标签编号。行标签从 1 开始、由右向左依次编号。
Count 指定要插入的标签级数。插入的行标签由 labelIndex 标识的行起始,向左计算。

InsertRows 方法:在与图表关联的数据网格中添加一个或多个数据行。其语法:
object.InsertRows (row, count)
row  标识特定的数据行。行从 1 开始、由顶端向底端依次编号。
Count 指定要插入的行数。行中都包含空数据直到用数据行填充它们。

SetData 方法:在与图表关联的数据网格中设置数据值。其语法:
object.SetData (row, column, dataPoint, nullFlag) ,参数说明如下:
row标识包含数据点数值的行。
column标识包含数据点数值的列。
dataPoint数据点的数值。
nullFlag指示数据点数值是否为空值。

SetSize 方法:调整数据行、数据列数以及与图表关联的数据网格中的列标签级数和行标签级数。此方法可代替 RowCount、ColumnCount、RowLabelCount 和 ColumnLabelCount。其语法:object.SetSize (rowLabelCount, columnLabelCount, dataRowCount, columnLabelCount) ,参数说明如下:
rowLabelCount  返回或设置数据网格中的行标签级数。
columnLabelCount  返回或设置数据网格中的列标签级数。
dataRowCount  返回或设置数据网格上的数据行数。
columnLabelCount 返回或设置数据网格上的数据列数。

关于多级标签和数据网格的设置,附件中有详细的演示代码。

1.3.7 Intersection 对象

Intersection 对象用于设置两坐标轴相交点,有5个属性:Auto、AxisId、Index、LabelsInsidePlot 和Point 属性。

Auto属性:返回或设置一个数值,它决定 Intersection 对象是否用 Point 属性的数值来放置坐标轴。其语法:object.Auto [ = boolean],参数说明如下:
boolean 的设置值为:
True (缺省)将坐标轴放置在标准位置。
False 将相交的坐标轴放置在 Point 指定的数值处。

LabelsInsidePlot 属性:返回或设置一个数值,它决定是将坐标轴标签保留在正常位置,还是将它们与坐标轴一起移动到新的相交点。其语法:
object.LabelsInsidePlot [= boolean] ,参数说明如下:
boolean 的设置值为:
True (缺省)坐标轴标签保留在正常位置。
False 图象内部的标签移动到新的相交点处。

Point 属性:返回或设置当前坐标轴与另一坐标轴的相交点。其语法:
object.Point [ = point] ,参数说明如下:
point 指示当前坐标轴与一个轴的相交点。

举例说明,特别注意的是LabelsInsidePlot属性的影响:
Private Sub UserForm_Initialize()
    With MSChart1
        .ChartType = VtChChartType2dLine
        With .Plot.Axis(VtChAxisIdX).Pen
            .Width = 4
            .VtColor.Red = 255
        End With
        With .Plot.Axis(VtChAxisIdX).Intersection
            '设置相交属性。
            .Auto = False   '设置手工定位。
            .Point = 20      '将与Y坐标轴上的值20相交。
            .LabelsInsidePlot = True '将标签与坐标轴一起显示
        End With
    End With
End Sub

其显示结果为下图,红色的细线为X坐标轴,相较于Y轴的20:
Intersection 对象-图1.png

现在把LabelsInsidePlot设置FALSE,其结果为下图,可见标签移动了:
Intersection 对象-图2.png



TA的精华主题

TA的得分主题

 楼主| 发表于 2019-1-22 16:01 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册


1.3.8 Label 对象

Labels 集合中的项目,它描述特定的图表坐标轴标签。坐标轴标签设置文本布局很简单,和其他需要设置文本布局的对象方法一样,没什么好讲的,直接放在附件演示代码中了。不过Labels集合只能为Labels(1),代表指定轴的所有标签,不可以单独设置一个标签的格式,唯一能设置的就是其文本,可用数据网格对象的DataGrid.RowLabel和DataGrid.ColumnLabel进行设置。Label对象唯一要讲的就是Format 属性,其返回或设置用来定义显示坐标轴标签格式的字符,其格式文本跟VB函数Format使用的规则一样,如设置Y轴标签为两位小数:
MSChart1.Plot.Axis(VtChAxisIdY).Labels(1).Format = "0.00"

1.3.9 Tick对象

Tick对象代表沿图表坐标轴标识图表项的标记,该对象是指坐标轴上的刻度标记,刻度不是网格线,要注意区别。该对象只有两个属性,我也想不出有修改它们的必要性,但为了讲解得全面点,还是列举吧。

Length返回或设置坐标轴 tick 标记的长度,以点为单位。

Style用来描述坐标轴刻度标记位置,其可选值为:

Tick对象-表1.png
要设置X坐标轴刻度的长度和位置,可以用如下代码:
With MSChart1.Plot.Axis(VtChAxisIdX).Tick
   .Length = 500
   .Style = VtChAxisTickStyleOutside
End With


TA的精华主题

TA的得分主题

 楼主| 发表于 2019-1-22 16:08 | 显示全部楼层


1.4 SeriesCollection集合与Series 对象

        Series 对象(系列)是SeriesCollection 集合中的项,代表图表中的一组数据点。Series 对象和Axis对象是图表中最常使用的对象,是图表的基础,要重点掌握的。其对象模型如下图。这里先介绍其属性。

Series 对象-图1.png

DataPoints 属性:返回对 DataPoint 集合(数据点)的引用,它描述图表系列中的数据点。

GuidelinePen 属性:返回对 Pen 对象的引用,该对象描述用于显示引导线的线型及颜色。设置该属性会自动将 ShowGuideLines 属性设为 True。

下面的示例为二维 xy 图表系列设置画笔属性。其中 GuideLinePen 属性返回对 Pen 对象的引用。
Private Sub Command1_Click()
   '为二维的 XY 图表的系列 1 设置引导线。
   MSChart1.ChartType = VtChChartType2dXY
   MSChart1.Plot.SeriesCollection.Item(1) _
   .ShowGuideLine(VtChAxisIdX) = True
   With _
   MSChart1.Plot.SeriesCollection.Item(1).GuideLinePen
      '设置画笔属性。
      .VtColor.Set 255, 0, 0
      .Width = 4
      .Style = VtPenStyleDashDot
      .Join = VtPenJoinRound
      .Cap = VtPenCapRound
   End With
End Sub

LegendText 属性:返回或设置在图表的图例中标识系列的文本。

Pen 属性:返回或设置对 Pen 对象的引用,该对象描述系列线的颜色及线型。

Position 属性 :返回对 SeriesPosition 对象的引用,该对象描述与其它图表系列互相关联的系列的位置。在堆叠图表的时候,需要设置哪个系列在图层的上面,需要使用到这个属性。其下还有Hide属性可用于隐藏一个系列。

SecondaryAxis 属性:返回或设置值,这个值决定是否在次坐标轴绘制该系列。非常重要的属性。

SeriesMarker 属性:返回对 SeriesMarker 对象的引用,该对象描述标识图表系列中的所有数据点的标记。SeriesMarker 对象的Auto属性返回或设置一个值,该值决定SeriesMarker 对象是否用下一个可用标记来标记系列中的所有数据点,如果要使用自定义的标记类型,需要把Auto属性设置为FALSE,SeriesMarker 对象的Show属性返回或设置一个值,该值决定是否在图表上显示系列的标记。

SeriesType 属性:返回或设置用于显示当前系列的类型。非常重要的属性。当使用组合图时,使用该属性修改每个系列的图表类型。可选的数值为:
Series 对象-表1.png

StatLine 属性:返回对 StatLine 对象的引用,该对象描述如何在图表中显示统计线。后面会单独讲到它。

1.4.1 DataPoint 对象

DataPoint 对象是DataPoints 集合中的成员,它描述图表中单个数据点的属性。DataPoints 集合必须使用-1的索引,如:MSChart1.Plot.SeriesCollection(1).DataPoints(-1),因为不可以对单独的数据点格式进行设置,-1代表所有数据点。先说明其属性。

Brush 属性:返回对 Brush 对象的引用,它描述用于显示数据点的填充类型。Brush 对象在之前已经讲过,这里不再重复。假如要修改系列1所有数据点的填充颜色和风格,可用:
With MSChart1.Plot.SeriesCollection(1).DataPoints(-1)
   .Brush.Style = VtBrushStyleSolid
   .Brush.FillColor.Set 0, 255, 255
   .Marker.Visible = True
End With

DataPointLabel 属性:返回对 DataPointLabel 对象的引用,它描述个别图表数据点上的标签。这个在后边单独讲。

EdgePen 属性:返回 Pen 对象,此对象用于绘制图表中数据点的边界。Pen 对象已讲过了。

Marker 属性:返回对 Marker 对象的引用,该对象描述用来标识图表中的数据点的图标。可用Marker 对象的FillColor 属性对标记进行填充颜色。Marker 对象的Pen 属性用于绘制数据点标记的边框颜色及线型,标记大小由Size属性指定。数据点标记的Style(类型)为:
DataPoint 对象-表1.png

1.4.2 DataPointLabel 对象

DataPointLabel 对象代表图表中数据点的标签。其重要属性如下:

Component 属性:返回或设置用来标识数据点的标签类型。
DataPointLabel-表1.png

LineStyle 属性:
返回或设置用来连接图表中数据点和标签的线段类型。
DataPointLabel-表2.png

LocationType 属性:返回或设置显示数据点标签的位置。
DataPointLabel-表3.png

PercentFormat 属性:返回或设置一个字符串,它描述用来显示百分比标签的格式。还有一个ValueFormat属性,对值的格式设置。挺繁琐的。

数据点标签的文本布局跟其他对象一样,略……。


TA的精华主题

TA的得分主题

 楼主| 发表于 2019-1-22 16:12 | 显示全部楼层


1.4.3 StatLine 对象

StatLine 对象描述如何在图表中显示统计线。StatLine 对象只有4个属性:

Width属性指定统计线的宽度

VtColor属性指定统计线的颜色。

Flag 属性设置显示系列的是哪条统计线。
StatLine 对象-表1.png

Style 属性:返回或设置用于显示统计线的线型。其语法:
object.Style (type )[ = style],参数说明如下:
type 是用于描述统计线类型的常数,即Flag属性指定的值。
style描述统计线样式的 VtPenStyle 常数。
StatLine 对象-表2.png

下面的示例为图表的统计线设置颜色及画笔的参数:

'显示系列 2 的所有统计线。
MSChart1.ChartType = VtChChartType2dLine
With MSChart1.plot.SeriesCollection(2).StatLine
    .VtColor.Set 255, 0, 0
    .Flag = vtChStatsMinimum Or VtChStatsMaximum _
    Or VtChStatsMean Or VtChStatsStddev Or _
    VtChStatsRegression
    .Style(vtChStatsMinimum) = VtPenStyleDotted
    .Width = 4
End With

1.4.4 Backdrop 对象

Backdrop 对象表示图表元素后面的阴影或图案。本来不打算讲这个对象的,因为我不觉得它有什么用,设置它会把图表搞得眼花缭乱,我追求的是图表简洁、简单,但是很多对象都包含这个对象,我就稍微说一下吧。Backdrop 对象有3个属性:Fill、Frame和Shadow 属性。

Fill 属性:返回对 Fill 对象的引用,它描述图表对象背景的类型和外观。Fill 对象有2个属性,Brush和Style 属性,Brush就是前面说过的画刷对象, Style属性提供指定用于绘制背景的填充类型的选项,可用选项为:
Backdrop 对象-表1.png

Frame 属性:返回对 Frame 对象的引用,它描述图表元素周围框架的外观。Frame 对象有4个属性:FrameColor、SpaceColor 、Style和Width 属性。其中,FrameColor 属性返回对 VtColor 对象的引用,该对象指定环绕图表元素的单框所用的颜色。SpaceColor 属性返回对 VtColor 对象的引用,该对象指定填充环绕图表元素的双框间的空白所用的颜色。Width属性返回或设置以磅为单位的框架线宽。Style属性描述框架的类型,可选值为:
Backdrop 对象-表2.png

下面的示例在图表背景上设置蓝色的双线框架。
With MSChart1.backdrop.Frame
   .Style = VtFrameStyleDoubleLine
   .Width = 2
   .FrameColor.Set 0, 0, 255   '蓝色框架。
   .SpaceColor.Set 255, 0, 0   '红色间隔。
End With
Style 属性 (MSChart)

Shadow 属性:返回对 Shadow 对象的引用,该对象描述图表元素的阴影样式。Shadow 对象有3个属性:Brush、Offset和Style 属性。Brush 属性返回对 Brush 对象的引用,它描述用于显示图表元素的填充类型。Offset 属性返回或设置,图表元素与它的缺省位置偏移的距离。Style属性描述阴影类型,可选值为:
Backdrop 对象-表3.png

下面的示例给图表的背景设置阴影。
With MSChart1.backdrop.Shadow
    .Style = VtShadowStyleDrop
    .Offset.x = 10
    .Offset.y = 10
End With

再写一个设置backdrop对象3个属性的代码:

Private Sub UserForm_Initialize()
    With MSChart1
        .ChartType = VtChChartType2dBar
        .RandomFill = True
        With .Backdrop.Fill
            .style = VtFillStyleBrush
            .Brush.FillColor.Red = 255
            .Brush.style = VtBrushStylePattern
            .Brush.Index = VtBrushPattern50Percent
            .Brush.PatternColor.Blue = 255
        End With
        With .Backdrop.Frame
            .style = VtFrameStyleDoubleLine
            .FrameColor.Red = 255
            .SpaceColor.Blue = 255
            .Width = 2
        End With
        With .Backdrop.Shadow
            .style = VtShadowStyleDrop
            .Brush.style = VtBrushStyleSolid
        End With
    End With
End Sub


TA的精华主题

TA的得分主题

 楼主| 发表于 2019-1-22 16:13 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册


1.5 第一章总结

        MSChart控件的对象非常多,对图表元素的操控也会很细致,如果本教程对所有图表元素的操作都一一举例,教程会变得非常庞大。因此,我把对图表元素的操作全部写在代码里,大家可以在窗体上点击组合框的选项就可以看到操作结果,既可以对图表元素有个直观的认识,也可在需要的时候直接复制相关代码。为了实现在窗体上直观演示,我多写了10倍的代码量,这个方法看来不是很明智,至少对我而言是这样。这里提一下,获取系统字体的方法。论坛上的大神用如下简单的代码就获取了系统的字体:

With Application.CommandBars.FindControl(ID:=1728)
  For i = 1 To .ListCount
    Cells(i, 1) = .List(i)
  Next
End With

不过这个方法不通用,不同版本的EXCEL的ID可能不同,有些版本会什么也获取不到。于是我查阅了微软的资料,用API实现字体的获取,这样通用性应该好些,顺便把安装字体和卸载字体的代码一并提供,这样谁想设计一个小软件的时候,可以直接复制代码,也应该不错的。代码可供参考:

'获取系统字体清单
Private Declare Function EnumFontFamiliesEx Lib "gdi32" Alias "EnumFontFamiliesExA" (ByVal hDC As Long, lpLogFont As LOGFONT, ByVal lpEnumFontProc As Long, ByVal lParam As Long, ByVal dw As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hDC As Long) As Long
Private Const LF_FACESIZE = 32
Private Const LF_FULLFACESIZE = 64
Private Const ANSI_CHARSET = 0

Private Type LOGFONT
        lfHeight As Long
        lfWidth As Long
        lfEscapement As Long
        lfOrientation As Long
        lfWeight As Long
        lfItalic As Byte
        lfUnderline As Byte
        lfStrikeOut As Byte
        lfCharSet As Byte
        lfOutPrecision As Byte
        lfClipPrecision As Byte
        lfQuality As Byte
        lfPitchAndFamily As Byte
        lfFaceName(1 To LF_FACESIZE) As Byte
End Type

Private Type ENUMLOGFONTEX
    elfLogFont As LOGFONT
    elfFullName(1 To LF_FULLFACESIZE) As Byte
    elfStyle(1 To LF_FACESIZE) As Byte
    elfScript(1 To LF_FACESIZE) As Byte
End Type

Public frmname As String
Public cmbname As String
Public frm As Object
'
'参考资料:
'https://docs.microsoft.com/zh-cn/windows/desktop/api/wingdi/nf-wingdi-enumfontfamiliesexa
'ivccav 2019/1/15
Private Function EnumFontFamExProc(ByRef lpelfe As ENUMLOGFONTEX, ByVal lpntme As Long, ByVal FontType As Long, ByVal lParam As Long) As Long
    Dim fn$, pos&
    fn = StrConv(lpelfe.elfLogFont.lfFaceName, vbUnicode)
    pos = InStr(fn, Chr$(0))
    If pos Then fn = Left$(fn, pos - 1)
    With frm.Controls(cmbname)
        .AddItem fn
    End With
    EnumFontFamExProc = 1
End Function

Public Sub GetAllFonts()
    Dim lf As LOGFONT
    Dim hDC&, f As Object
    Dim bln As Boolean
    For Each f In UserForms
        If f.Name = frmname Then bln = True: Exit For
    Next
    If bln Then Set frm = f Else Exit Sub
    lf.lfCharSet = ANSI_CHARSET
    hDC = GetDC(0&)
    EnumFontFamiliesEx hDC, lf, AddressOf EnumFontFamExProc, 0&, 0&
    ReleaseDC 0&, hDC
End Sub

Private Declare Function AddFontResource Lib "gdi32" Alias "AddFontResourceA" (ByVal lpFileName As String) As Long
Private Declare Function RemoveFontResource Lib "gdi32" Alias "RemoveFontResourceA" (ByVal lpFileName As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const HWND_BROADCAST = &HFFFF&
Private Const WM_FONTCHANGE = &H1D

'参考资料:
'https://docs.microsoft.com/zh-cn/windows/desktop/api/wingdi/nf-wingdi-addfontresourcea
''ivccav 2019/1/15
Public Sub AddNewFont() '安装字体
    Dim lRet As Long, FontPath As String
    With Application.FileDialog(msoFileDialogFilePicker)
        .AllowMultiSelect = False
        .InitialFileName = "C:\Windows\Fonts\"
        .Filters.Clear
        .Filters.Add "字体文件", "*.ttf;*.ttc;*.otf"
        .Title = "请选择要安装的字体文件"
        If .Show = True Then
            FontPath = .SelectedItems.Item(1)
            lRet = AddFontResource(FontPath)
            If lRet = 0 Then
                MsgBox "添加字体失败!", vbCritical
                Exit Sub
            Else
                SendMessage HWND_BROADCAST, WM_FONTCHANGE, 0, 0
                MsgBox "添加字体成功", vbInformation
            End If
        End If
    End With
End Sub

Public Sub RemoveFont() '卸载字体
    Dim lRet As Long, FontPath As String
    With Application.FileDialog(msoFileDialogFilePicker)
        .AllowMultiSelect = False
        .InitialFileName = "C:\Windows\Fonts\"
        .Filters.Clear
        .Filters.Add "字体文件", "*.ttf;*.ttc;*.otf"
        .Title = "请选择要卸载的字体文件"
        If .Show = True Then
            FontPath = .SelectedItems.Item(1)
            lRet = RemoveFontResource(FontPath)
            If lRet = 0 Then
                MsgBox "卸载字体失败!", vbCritical
                Exit Sub
            Else
                SendMessage HWND_BROADCAST, WM_FONTCHANGE, 0, 0
                MsgBox "卸载字体成功", vbInformation
            End If
        End If
    End With
End Sub


您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-5 18:50 , Processed in 0.048598 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表