本节介绍Excel提供的基本图形元素的创建,包括点、直线段、矩形、椭圆、多义线、多边形、贝塞尔曲线、标签、文本框、标注、自选图形、图表、艺术字等。
Excel对象模型中,用Shape对象表示图形,Shapes对象作为集合对所有图形进行保存和管理。通过编程创建图形的过程,就是创建Shape对象并利用它本身及与之相关的一系列对象的属性和方法进行编程的过程。[大谦Excel,dqexcel点com]
点
Shapes对象没有提供专门用于绘制点的方法,但是它提供的自选图形里面有若干特殊的图形类型可以用来表示点,比如星形、矩形、圆形、菱形等,这些自选图形可以用Shapes对象的AddShape方法创建。该方法的语法格式为:
sht.api.Shapes.AddShape(Type, Left, Top, Width, Height)
采用的是xlwings包的API调用方式。sht表示一个工作表对象。该方法返回一个Shape对象,各参数的意义如表4-1所示。
表4-1 AddShape方法的参数说明
| 名 称 | 必需/可选 | 数据类型 | 说 明 |
|---|---|---|---|
| Type | 必需 | MsoAutoShapeType | 指定要创建的自选图形的类型 |
| Left | 必需 | Single | 自选图形边框左上角相对于文档左上角的位置 (以磅为单位) |
| Top | 必需 | Single | 自选图形边框左上角相对于文档顶部的位置 (以磅为单位) |
| Width | 必需 | Single | 自选图形边框的宽度(以磅为单位) |
| Height | 必需 | Single | 自选图形边框的高度(以磅为单位) |
其中,Type参数的值为msoAutoShapeType枚举类型,可以有很多的选择。表4-2中列出了一些星形点对应的常数和值。
表4-2 AddShape方法Type参数中星形点的取值
| 名 称 | 值 | 说 明 |
|---|---|---|
| msoShape10pointStar | 149 | 十角星 |
| msoShape12pointStar | 150 | 十二角星 |
| msoShape16pointStar | 94 | 十六角星 |
| msoShape24pointStar | 95 | 二十四角星 |
| msoShape32pointStar | 96 | 三十二角星 |
| msoShape4pointStar | 91 | 四角星 |
| msoShape5pointStar | 92 | 五角星 |
| msoShape6pointStar | 147 | 六角星 |
下面创建一个五角星、一个十二角星和一个三十二角星表示的点。
>>> import xlwings as xw #导入xlwings
>>> bk=xw.Book() #新建工作簿
>>> sht=bk.sheets(1) #获取第1个工作表
>>> sht.api.Shapes.AddShape(92,180,80,10,10) #在指定位置添加点
>>> sht.api.Shapes.AddShape(150,150,40,15,15)
>>> sht.api.Shapes.AddShape(96,80,80,3,3)
效果如图4-1所示。
图4-1 星形点
也可以用矩形和圆表示点,在4.1.3小节进行介绍。
直线段
用Shapes对象的AddLine方法创建直线段。该方法的语法格式为:
sht.api.Shapes.AddLine(BeginX, BeginY, EndX, EndY)
其中,sht表示一个工作表对象。参数BeginX, BeginY表示起点的横坐标和纵坐标,EndX, EndY表示终点的横坐标和纵坐标。该方法返回一个表示直线段的Shape对象。
下面在工作表sht中添加一个起点为(10,10),终点为(250, 250)的直线段。并设置该直线段的线型为圆点线,颜色为红色,线宽为5。关于直线段的属性编辑,在4.2.2小节有比较详细的介绍。
>>> shp=sht.api.Shapes.AddLine(10,10,250,250) #创建直线段Shape对象
>>> ln=shp.Line #获取线形对象
>>> ln.DashStyle=3 #设置线形对象的属性:线型、颜色和线宽
>>> ln.ForeColor.RGB=xw.utils.rgb_to_int((255, 0, 0))
>>> ln.Weight=5
生成图4-2所示的直线段。
图4-2 创建直线段
矩形、圆角矩形、椭圆和圆
用Shapes对象的AddShape方法创建矩形、圆角矩形、椭圆和圆。该方法在4.1.1小节进行了介绍,实际上是通过创建自选图形的方法来创建。该方法跟以上几种图形有关的Type参数取值如表4-3所示。其中,圆是特殊的椭圆,即横轴和纵轴相等的椭圆。
表4-3 AddShape方法相关的Type参数取值
| 名 称 | 值 | 说 明 |
|---|---|---|
| msoShapeRectangle | 1 | 矩形 |
| msoShapeRoundedRectangle | 5 | 圆角矩形 |
| msoShapeOval | 9 | 椭圆形 |
默认时生成的矩形和圆都是实心的,是矩形面和圆形面。设置它们的Fill属性返回对象的Visible属性的值为False,可以生成线形的矩形和圆。
本例向工作表sht中添加矩形、圆角矩形、椭圆和圆,皆为实心的面。
>>> sht.api.Shapes.AddShape(1, 50, 50, 100, 200) #矩形区域
>>> sht.api.Shapes.AddShape(5, 100, 100, 100, 200) #圆角矩形区域
>>> sht.api.Shapes.AddShape(9, 150, 150, 100, 200) #椭圆区域
>>> sht.api.Shapes.AddShape(9, 200, 200, 100, 100) #圆区域
生成图4-3。
下面生成没有填充的线形的矩形、圆角矩形、椭圆和圆。
>>> shp1=sht.api.Shapes.AddShape(1, 50, 50, 100, 200) #矩形
>>> shp1.Fill.Visible = False
>>> shp2=sht.api.Shapes.AddShape(5, 100, 100, 100, 200) #圆角矩形
>>> shp2.Fill.Visible = False
>>> shp3=sht.api.Shapes.AddShape(9, 150, 150, 100, 200) #椭圆
>>> shp3.Fill.Visible = False
>>> shp4=sht.api.Shapes.AddShape(9, 200, 200, 100, 100) #圆
>>> shp4.Fill.Visible = False
生成图4-4。
图4-3 矩形、圆角矩形、椭圆和圆形面 图4-4 矩形、圆角矩形、椭圆和圆形线
多义线和多边形
使用Shapes对象的AddPolyline方法创建多义线和多边形。该方法的语法格式为:
sht.api.Shapes.AddPolyline(SafeArrayOfPoints)
其中,sht表示一个工作表对象。参数SafeArrayOfPoints指定多义线或多边形的顶点坐标。该方法返回一个表示多义线或多边形的Shape对象。
各顶点用其横坐标和纵坐标对表示,全部顶点用一个二维列表表示,例如:
pts=[[10,10],[20,30],[30,50],[50,80],[10,10]]
本例用xlwings向工作表中添加一个四边形。 由于起点和终点的坐标相同,因此,该四边形既是闭合的又是填充的。
>>> pts=[[10,10],[20,30],[30,50],[50,80],[10,10]]
>>> sht.api.Shapes.AddPolyline(pts)
结果返回下面的出错信息:
pywintypes.com_error: (-2147352567, '发生意外。', (0, None, '指定参数的数据类型不正确。', None, 0, -2146827284), None)
可见,使用xlwings绘制多义线和多边形,以及下一节介绍的曲线存在问题。我们使用另一个Python包comtypes来实现。该包跟win32com和xlwings类似,都是基于COM机制。
首先,在DOS命令窗口,用pip命令安装comtypes库:
pip install comtypes
然后在Python IDLE窗口输入:
>>> #从comtypes包导入CreateObject函数
>>> from comtypes.client import CreateObject
>>> app2=CreateObject("Excel.Application") #创建Excel应用
>>> app2.Visible=True #应用窗口可见
>>> bk2=app2.Workbooks.Add() #添加工作簿
>>> sht2=bk2.Sheets(1) #获取第1个工作表
>>> pts=[[10,10], [50,150],[90,80], [70,30], [10,10]] #多边形顶点
>>> sht2.Shapes.AddPolyline(pts) #添加多边形区域
生成图4-5所示的多边形区域。
如果只生成多边形线条,设置表示多边形区域的Shape对象的Fill属性返回对象的Visible属性的值为False。
>>> pts=[[10,10], [50,150],[90,80], [70,30], [10,10]]
>>> shp=sht2.Shapes.AddPolyline(pts)
>>> shp.Fill.Visible=False #多边形
生成图4-6。
图4-5 多边形区域 图4-6 多边形
曲线
用Shapes对象的AddCurve方法创建曲线。该方法的语法格式为:
sht.api.Shapes.AddCurve(SafeArrayOfPoints)
其中,sht表示一个工作表对象。参数SafeArrayOfPoints指定贝塞尔曲线顶点和控制点的坐标。指定的点数始终为3n + 1,其中n为曲线的线段条数。该方法返回一个表示贝塞尔曲线的Shape对象。
各顶点用其横坐标和纵坐标对表示,全部顶点用一个二维列表表示,例如:
pts=[[0,0],[72,72],[100,40],[20,50],[90,120],[60,30],[150,90]]
下面的示例向工作表sht中添加贝塞尔曲线。基于与4.1.5小节示例相同的原因,使用COMTypes包进行绘制。
>>> from comtypes.client import CreateObject
>>> app2=CreateObject("Excel.Application")
>>> app2.Visible=True
>>> bk2=app2.Workbooks.Add()
>>> sht2=bk2.Sheets(1)
>>> pts=[[0,0],[72,72],[100,40],[20,50],[90,120],[60,30],[150,90]] #顶点
>>> sht2.Shapes.AddCurve(pts) #添加贝塞尔曲线
生成图4-7所示的贝塞尔曲线。
图4-7 贝塞尔曲线
标签
使用Shapes对象的AddLabel方法创建标签。该方法的语法格式为:
sht.api.Shapes.AddLabel(Orientation,Left,Top,Width,Height)
其中,sht表示一个工作表对象。各参数的说明如表4-4所示。该方法返回一个表示标签的Shape对象。
表4-4 AddLabel方法各参数的说明
| 名 称 | 必需/可选 | 数据类型 | 说 明 |
|---|---|---|---|
| Orientation | 必需 | msoTextOrientation | 标签中文本的方向 |
| Left | 必需 | Single | 标签左上角相对于文档左上角的位置 (以磅为单位) |
| Top | 必需 | Single | 标签左上角相对于文档顶部的位置 (以磅为单位) |
| Width | 必需 | Single | 标签的宽度(以磅为单位) |
| Height | 必需 | Single | 标签的高度(以磅为单位) |
Orientation参数表示标签中文本的方向,其取值如表4-5所示。
表4-5 Orientation参数的取值
| 名 称 | 值 | 说 明 |
|---|---|---|
| msoTextOrientationDownward | 3 | 朝下 |
| msoTextOrientationHorizontal | 1 | 水平 |
| msoTextOrientationHorizontalRotatedFarEast | 6 | 亚洲语言支持所需的水平和旋转 |
| msoTextOrientationMixed | -2 | 不支持 |
| msoTextOrientationUpward | 2 | 朝上 |
| msoTextOrientationVertical | 5 | 垂直 |
| msoTextOrientationVerticalFarEast | 4 | 亚洲语言支持所需的垂直 |
本示例向工作表sht中添加包含文本的垂直标签。
>>> shp=sht.api.Shapes.AddLabel(1,100,20,60,150) #添加标签
>>> shp.TextFrame.Characters.Text="Test Python Label" #标签文本,bug
生成图4-8所示的标签。可见,只生成了标签本身,文字的内容并没有生成。笔者测试了ComTypes和Win32COM等其他包,也存在这个问题。Characters属性生成对象的所有成员都不能正常工作。如果您找到解决办法,请告诉我。
可以在标签中手工输入文本,如图4-9所示。
图4-8 生成标签 图4-9 手工输入标签文本
文本框
用Shapes对象的AddTextbox方法生成文本框。该方法的调用格式和各参数的意义跟AddLabel方法的相同。
本示例向工作表sht中添加包含文本的文本框。
>>> shp=sht.api.Shapes.AddTextbox(1,10,10,100,100)
>>> shp.TextFrame.Characters.Text="Test Box"
>>> //改为:shp.TextFrame2.TextRange.Characters.Text="Test Box"
生成图4-10所示的文本框。文字内容没有显示。可以手工输入文字,如图4-11所示。
图4-10 文本框 图4-11 手工输入文字
标注
用Shapes对象的AddCallout方法添加标注。该方法的语法格式为:
sht.api.Shapes.AddCallout(Type,Left,Top,Width,Height)
其中,sht表示一个工作表对象。各参数的说明如表4-6所示。该方法返回一个表示标注的Shape对象。
表4-6 AddCallout方法的参数设置
| 名称 | 必需/可选 | 数据类型 | 说 明 |
|---|---|---|---|
| Type | 必需 | MsoCalloutType | 标注线的类型 |
| Left | 必需 | Single | 标注边界框左上角相对于文档左上角的位置 (以磅为单位) |
| Top | 必需 | Single | 标注边界框左上角相对于文档顶部的位置 (以磅为单位) |
| Width | 必需 | Single | 标注边框的宽度(以磅为单位) |
| Height | 必需 | Single | 标注边框的高度(以磅为单位) |
Type参数的取值为MsoCalloutType枚举类型的值,如表4-7中所示,指定标注线的类型。
表4-7 AddCallout方法Type参数的取值
| 名 称 | 值 | 说 明 |
|---|---|---|
| msoCalloutFour | 4 | 由两条线段组成的标注线。 标注线附加在文本边界框的右侧 |
| msoCalloutMixed | -2 | 只返回值,表示其他状态的组合 |
| msoCalloutOne | 1 | 单线段水平标注线 |
| msoCalloutThree | 3 | 由两条线段组成的标注线。 标注线连接在文本边界框的左侧 |
| msoCalloutTwo | 2 | 单线段倾斜标注线 |
本示例向工作表sht中添加包含文本的标注。
>>> shp=sht.api.Shapes. AddCallout(2, 10, 10, 200, 50)
>>> shp.TextFrame.Characters.Text="Test Box"
>>> //改为:shp.TextFrame2.TextRange.Characters.Text="Test Box"
生成图4-12所示的标注框。文字内容没有显示。可以手工输入文字,如图4-13所示。
图4-12 标注 图4-13 手工输入标注内容
设置shp对象的Callout属性:
>>> shp.Callout.Accent=True
>>> shp.Callout.Border=True
>>> shp.Callout.Angle=2
其中,Accent属性设置引线左侧的竖线,Border属性设置标注区域的外框,Angle属性设置引线的角度,这里设置为30度。生成图4-14。
图4-14 设置标注对象的属性
自选图形
所谓自选图形,是Excel预定义好的很多图形对象。使用Shapes对象的AddShape方法创建自选图形。前面我们用该方法创建了点、矩形、椭圆等图形。实际上,还有很多其他的图形类型,如表4-8中所示。
表4-8 部分自选图形
| 名 称 | 值 | 说 明 |
|---|---|---|
| msoShapeOval | 9 | 椭圆形 |
| msoShapeOvalCallout | 107 | 椭圆形标注 |
| msoShapeParallelogram | 12 | 斜平行四边形 |
| msoShapePie | 142 | 圆形 ("饼图"), 缺少部分 |
| msoShapeQuadArrow | 39 | 指向向上、向下、向左和向右的箭头 |
| msoShapeQuadArrowCallout | 59 | 带向上、向下、向左和向右的箭头的标注 |
| msoShapeRectangle | 1 | 矩形 |
| msoShapeRectangularCallout | 105 | 矩形标注 |
| msoShapeRightArrow | 33 | 右箭头 |
| msoShapeRightArrowCallout | 53 | 带右箭头的标注 |
| msoShapeRightBrace | 32 | 右大括号 |
| msoShapeRightBracket | 30 | 右小括号 |
| msoShapeRightTriangle | utf-8 | 直角三角形 |
| msoShapeRound1Rectangle | 151 | 有一个圆角的矩形 |
| msoShapeRound2DiagRectangle | 157 | 有两个圆角的矩形, 对角相对 |
| msoShapeRound2SameRectangle | 152 | 具有两个圆角的矩形, 共一侧 |
| msoShapeRoundedRectangle | 5 | 圆角矩形 |
| msoShapeRoundedRectangularCallout | 106 | 圆角矩形-形状标注 |
| …… |
下面的例子向工作表sht中添加矩形、平行四边形和一个笑脸图形。
>>> sht.api.Shapes. AddShape(1, 50, 50, 100, 200)
>>> sht.api.Shapes. AddShape(12, 250, 50, 100, 100)
>>> sht.api.Shapes. AddShape(17, 450, 50, 100, 100)
生成图4-15。
图4-15 生成自选图形
图表
用Shapes对象的AddChart2方法创建图表。该方法的语法格式为:
sht.api.Shapes.AddChart2(Style, XlChartType, Left, Top, Width, Height, NewLayout)
其中,sht为当前工作表。一共有7个参数,均可选。
• Style:图表样式,值为-1时表示各图形类型的默认样式。
• xlChartType:图表类型,值为XlChartType枚举类型,表4-9中列出了一部分。
• Left:图表左侧位置,省略时水平居中。
• Top:图表顶端位置,省略时垂直居中。
• Width:图表的宽度,省略时取默认值354。
• Height:图表的高度,省略时取默认值210。
• NewLayout:表示图表布局,如果值为True,则只有复合图形才会显示图例。
该方法返回一个表示图表的Shape对象。
表4-9 部分图表类型
| 名 称 | 值 | 说 明 |
|---|---|---|
| xlArea | 1 | 面积图 |
| xlLine | 4 | 线形图 |
| xlPie | 5 | 饼图 |
| xlBarClustered | 57 | 复合条形图 |
| xlBarStacked | 58 | 堆栈条形图 |
| xlXYScatter | -4169 | 散点图 |
| xlBubble | 个 | 泡泡图 |
| xlSurface | 83 | 三维曲面图 |
| …… |
下面利用图4-16所示工作表中的数据绘制复合条形图。首先选择数据区域,然后用Shapes对象的AddChart2方法绘制。
>>> sht.api.Range("A1").CurrentRegion.Select()
>>> sht.api.Shapes.AddChart2(-1,xw.constants.ChartType.xlColumnClustered,30,150,300,200,True)
生成图4-16所示工作表下方的图形。
图4-16 利用给定数据绘复合条形图
艺术字
用Shapes对象的AddTextEffect方法创建艺术字。该方法的语法格式为:
sht.api.Shapes.AddTextEffect(PresetTextEffect,Text,FontName,FontSize,FontBold,FontItalic, Left, Top)
其中,sht为当前工作表,各参数的意义如表4-10中所示。
表4-10 AddTextEffect方法的参数
| 名 称 | 必需/可选 | 数据类型 | 说 明 |
|---|---|---|---|
| PresetTextEffect | 必需 | MsoPresetTextEffect | 预置文字效果 |
| Text | 必需 | String | 艺术字中的文字 |
| FontName | 必需 | String | 艺术字中所用字体的名称 |
| FontSize | 必需 | Single | 在艺术字中使用的字体的大小 (以磅为单位) |
| FontBold | 必需 | MsoTriState | 在艺术字中要加粗的字体 |
| FontItalic | 必需 | MsoTriState | 在艺术字中要倾斜的字体 |
| Left | 必需 | Single | 左上角点的横坐标 |
| Top | 必需 | Single | 左上角点的纵坐标 |
PresetTextEffect参数表示艺术字的效果。Excel预置了约50种效果,表4-11中列出了少部分。设置时给PresetTextEffect参数赋对应的值即可。
表4-11 PresetTextEffect参数的取值
| 名 称 | 值 | 说 明 |
|---|---|---|
| msoTextEffect1 | 0 | 第一个文本效果 |
| msoTextEffect2 | 1 | 第二个文本效果 |
| msoTextEffect3 | 2 | 第三个文本效果 |
| …… |
下面创建两种不同效果的艺术字。
>>> sht.api.Shapes.AddTextEffect(9,"学习Python","Arial Black",36,False,False,10,10)
>>> sht.api.Shapes.AddTextEffect(29,"春眠不觉晓","黑体",40,False,False,30,50)
如图4-17所示。[大谦Excel,dqexcel点com]
图4-17 艺术字