使用 Python 在演示文稿中自定义图表坐标轴

概览

本文介绍如何使用 Aspose.Slides for Python via Java 自定义图表坐标轴。它涵盖了计算坐标轴数值、切换图表的行列、坐标轴可见性、类别标签和刻度间隔、日期类别及其格式、标题旋转、坐标轴位置以及显示单位。

获取图表垂直坐标轴的最大值

创建一个演示文稿并添加一个带有默认数据的面积图。在读取计算后的坐标轴值之前调用validateChartLayout,以确保图表布局是最新的。

读取getActualMaxValue和getActualMinValue以获取坐标轴限制,读取getActualMajorUnit和getActualMinorUnit以获取刻度间隔。getActualMajorUnitScale和getActualMinorUnitScale提供时间单位比例,这与日期坐标轴相关。示例将这些值存储在局部变量中并保存图表。

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import Presentation, ChartType, SaveFormat

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)

    chart = slide.getShapes().addChart(ChartType.Area, 100, 100, 500, 350)
    chart.validateChartLayout()

    max_value = chart.getAxes().getVerticalAxis().getActualMaxValue()
    min_value = chart.getAxes().getVerticalAxis().getActualMinValue()

    major_unit = chart.getAxes().getVerticalAxis().getActualMajorUnit()
    minor_unit = chart.getAxes().getVerticalAxis().getActualMinorUnit()

    major_unit_scale = chart.getAxes().getVerticalAxis().getActualMajorUnitScale()
    minor_unit_scale = chart.getAxes().getVerticalAxis().getActualMinorUnitScale()

    presentation.save("AxisValues_out.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

交换坐标轴之间的数据

使用switchRowColumn来交换图表数据中系列和类别的角色。原来的每个类别变为系列,原来的每个系列变为类别。这会改变数据的分组方式;但不会交换水平和垂直坐标轴。示例在切换行列之前使用setRange将默认数据绑定到 Sheet1!A1:D5,包括标题行和类别列。它保存了一个包含四个系列和三个类别的图表。

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpake.startJVM()

from asposeslides.api import Presentation, ChartType, SaveFormat

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)

    chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 100, 100, 400, 300)
    chart.getChartData().setRange("Sheet1!A1:D5")
    chart.getChartData().switchRowColumn()

    presentation.save("SwitchChartRowColumns_out.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

禁用折线图的垂直坐标轴

在垂直坐标轴上调用setVisible并传入 False 以隐藏它。示例创建一个带默认数据的折线图并保存其垂直坐标轴已隐藏的版本。

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import Presentation, ChartType, SaveFormat

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)

    chart = slide.getShapes().addChart(ChartType.Line, 100, 100, 400, 300)
    chart.getAxes().getVerticalAxis().setVisible(False)

    presentation.save("HiddenVerticalAxis.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

禁用折线图的水平坐标轴

在水平坐标轴上调用setVisible并传入 False 以隐藏它。示例创建一个带默认数据的折线图并保存其水平坐标轴已隐藏的版本。

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import Presentation, ChartType, SaveFormat

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)

    chart = slide.getShapes().addChart(ChartType.Line, 100, 100, 400, 300)
    chart.getAxes().getHorizontalAxis().setVisible(False)

    presentation.save("HiddenHorizontalAxis.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

更改类别坐标轴

使用setCategoryAxisType来选择日期或文本类别坐标轴。此示例需要 ExistingChart.pptx,其中图表是第一张幻灯片的第一个形状,类别单元格包含数值型 Excel 日期。它将水平坐标轴更改为日期坐标轴。调用setAutomaticMajorUnit并传入 False、setMajorUnit传入 1,以及setMajorUnitScale传入TimeUnitType.Months将在每月间隔放置主刻度线。

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import Presentation, SaveFormat, CategoryAxisType, TimeUnitType

presentation = Presentation("ExistingChart.pptx")
try:
    slide = presentation.getSlides().get_Item(0)

    chart = slide.getShapes().get_Item(0)
    chart.getAxes().getHorizontalAxis().setCategoryAxisType(CategoryAxisType.Date)
    chart.getAxes().getHorizontalAxis().setAutomaticMajorUnit(False)
    chart.getAxes().getHorizontalAxis().setMajorUnit(1)
    chart.getAxes().getHorizontalAxis().setMajorUnitScale(TimeUnitType.Months)

    presentation.save("ChangeChartCategoryAxis_out.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

控制类别坐标轴标签间隔

当图表拥有许多类别时,可以在不删除类别或数据点的情况下减少可见轴标签的数量。调用setAutomaticTickLabelSpacing并传入 False,随后将所需的类别间隔传给setTickLabelSpacing。对于按正常顺序排列的文本类别,计数从第一个类别开始:

间隔 示例中显示的标签
1 类别 1, 类别 2, 类别 3, … 类别 24
2 类别 1, 类别 3, 类别 5, … 类别 23
3 类别 1, 类别 4, 类别 7, … 类别 22

间隔为 3 时每隔三个标签显示一次,中间的两个标签被隐藏。它不会删除相应的列。自动间距会基于可用空间选择间隔;并不一定显示每个标签。

刻度线有单独的控制。调用setAutomaticTickMarksSpacing并传入 False,并使用setTickMarksSpacing设置其间隔。例如,1 会在每个类别间隔保留刻度线,而标签仅每隔第三个类别出现一次。使用setMajorTickMark并设置为可见样式,以便看到效果。再次将任一自动间距设置器设为 True,图表会重新选择该间距。

以下自包含示例创建 24 个类别和一个系列,然后在 CategoryAxisIntervals.pptx 中保存三张幻灯片:自动间距、带独立刻度线的手动标签间距以及恢复的自动间距。两份副本保留原始图表数据。无需输入演示文稿。水平标签文本使密度差异易于观察。

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import Presentation, ChartType, SaveFormat, CategoryAxisType, TickMarkType

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)

    chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 30, 40, 660, 320)

    chart.setLegend(False)
    chart.getChartData().getCategories().clear()
    chart.getChartData().getSeries().clear()

    workbook = chart.getChartData().getChartDataWorkbook()
    workbook.clear(0)

    series = chart.getChartData().getSeries().add(ChartType.ClusteredColumn)
    for i in range(24):
        category_cell = workbook.getCell(0, i + 1, 0, f"Category {i + 1}")
        chart.getChartData().getCategories().add(category_cell)
        value_cell = workbook.getCell(0, i + 1, 1, float(10 + i % 6 * 5))
        series.getDataPoints().addDataPointForBarSeries(value_cell)

    axis = chart.getAxes().getHorizontalAxis()
    axis.setCategoryAxisType(CategoryAxisType.Text)
    axis.getTextFormat().getTextBlockFormat().setRotationAngle(0)
    axis.getTextFormat().getPortionFormat().setFontHeight(12)
    axis.setMajorTickMark(TickMarkType.Outside)
    axis.setAutomaticTickLabelSpacing(True)
    axis.setAutomaticTickMarksSpacing(True)

    # 第 2 幻灯片: 显示每三个标签,但为每个类别保留刻度线。
    manual_slide = presentation.getSlides().addClone(slide)
    manual_chart = manual_slide.getShapes().get_Item(0)
    manual_axis = manual_chart.getAxes().getHorizontalAxis()
    manual_axis.setAutomaticTickLabelSpacing(False)
    manual_axis.setTickLabelSpacing(3)
    manual_axis.setAutomaticTickMarksSpacing(False)
    manual_axis.setTickMarksSpacing(1)

    # 第 3 幻灯片: 让图表再次自行选择两个间隔。
    restored_slide = presentation.getSlides().addClone(manual_slide)
    restored_chart = restored_slide.getShapes().get_Item(0)
    restored_chart.getAxes().getHorizontalAxis().setAutomaticTickLabelSpacing(True)
    restored_chart.getAxes().getHorizontalAxis().setAutomaticTickMarksSpacing(True)

    presentation.save("CategoryAxisIntervals.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

自动间距(第 1 幻灯片): 在此渲染中,每第二个类别标签被显示并换行到两行。自动结果可能因图表大小、字体和渲染器而异。

自动类别标签间距(所有 24 列可见)

手动间距(第 2 幻灯片): 每第三个标签显示在一行上,而刻度仍保持在每个类别间隔。所有 24 列,包括没有标签的列,仍然可见且值相同。第 3 幻灯片恢复了上面显示的自动外观。

手动类别标签间隔为三,所有 24 列可见

选择正确的坐标轴和间隔

对文本类别坐标轴使用此类别计数间隔,例如柱形图、折线图、面积图或条形图的类别坐标轴。在柱形图中,它是水平坐标轴。 在水平条形图中,类别坐标轴是垂直的,因此将这些设置应用于由getVerticalAxis返回的坐标轴。刻度间隔同样适用于具有系列坐标轴的图表。

不要使用类别标签间隔来设置数值坐标轴的数值刻度。在数值坐标轴上,setMajorUnit指定值的差异:例如,主单位为 10 时,在轴起点为零的情况下会在 0、10、20 等处生成刻度线。类别标签间隔为 3 时则是按类别位置计数,独立于其数据值。散点图和气泡图使用数值坐标轴而非文本类别坐标轴。对日期坐标轴,请使用更改类别坐标轴中描述的基于时间的主单位和比例。

设置类别坐标轴值的日期格式

示例用四个年度值替换默认图表数据。日期以 OLE Automation 序列号存储在第一个工作表(索引 0)中,计算方式为自 1899 年 12 月 30 日起的天数。使用setCategoryAxisType并传入CategoryAxisType.Date,调用setNumberFormatLinkedToSource并传入 False,随后将 yyyy 传给setNumberFormat,使类别标签独立于单元格格式显示四位数年份。

from datetime import date

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import Presentation, ChartType, SaveFormat, CategoryAxisType

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)

    chart = slide.getShapes().addChart(ChartType.Line, 50, 50, 450, 300)

    chart.getChartData().getCategories().clear()
    chart.getChartData().getSeries().clear()

    workbook = chart.getChartData().getChartDataWorkbook()
    workbook.clear(0)

    base_date = date(1899, 12, 30)

    series = chart.getChartData().getSeries().add(ChartType.Line)
    for i in range(4):
        category_date = date(2015 + i, 1, 1)
        category_value = float((category_date - base_date).days)
        category_cell = workbook.getCell(0, i + 1, 0, category_value)
        chart.getChartData().getCategories().add(category_cell)

        value_cell = workbook.getCell(0, i + 1, 1, float(i + 1))
        series.getDataPoints().addDataPointForLineSeries(value_cell)

    chart.getAxes().getHorizontalAxis().setCategoryAxisType(CategoryAxisType.Date)
    chart.getAxes().getHorizontalAxis().setNumberFormatLinkedToSource(False)
    chart.getAxes().getHorizontalAxis().setNumberFormat("yyyy")

    presentation.save("DateAxisFormat.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

设置图表坐标轴标题的旋转角度

在垂直坐标轴上调用setTitle并传入 True,提供标题文本,然后在标题的文本块格式中设置旋转角度。角度以度为单位;此示例保存了一个列形图,其值轴标题旋转了 90 度。

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import Presentation, ChartType, SaveFormat

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)

    chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 50, 50, 450, 300)
    chart.getAxes().getVerticalAxis().setTitle(True)
    chart.getAxes().getVerticalAxis().getTitle().addTextFrameForOverriding("Value")
    chart.getAxes().getVerticalAxis().getTitle().getTextFormat().getTextBlockFormat().setRotationAngle(90)

    presentation.save("RotatedAxisTitle.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

设置类别或数值坐标轴的位置

使用setAxisBetweenCategories来控制数值坐标轴是在类别之间还是在类别刻度线处与类别坐标轴相交。此设置适用于类别坐标轴。示例在列形图的水平类别坐标轴上将其设为 True 并保存结果。

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import Presentation, ChartType, SaveFormat

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)

    chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 50, 50, 450, 300)
    chart.getAxes().getHorizontalAxis().setAxisBetweenCategories(True)

    presentation.save("AxisBetweenCategories.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

设置图表数值坐标轴的显示单位

使用setDisplayUnit可在不更改底层数据的情况下缩放数值坐标轴的标签。将DisplayUnitType设为 Millions 时,60000000 将显示为 60。示例创建一个列形图并将其垂直坐标轴的显示单位设置为百万。

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import Presentation, ChartType, SaveFormat, DisplayUnitType

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)

    chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 50, 50, 450, 300)
    chart.getAxes().getVerticalAxis().setDisplayUnit(DisplayUnitType.Millions)

    presentation.save("Result.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

常见问题

如何设置一个坐标轴交叉另一坐标轴的数值(坐标轴交叉)?

使用setCrossType选择交叉行为。若要指定数值交叉点,请使用setCrossAt。这些设置允许您将坐标轴交叉移动到合适的基准线。

如何相对于坐标轴定位刻度标签?

调用setTickLabelPosition,并使用TickLabelPositionType:Low、High、NextTo 或 None。若要控制刻度线本身,请使用setMajorTickMark或setMinorTickMark;这些与标签定位是分开的。