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

概述

本文说明如何使用 Aspose.Slides for C++ 自定义图表坐标轴。内容包括计算坐标轴值、切换图表行列、坐标轴可见性、类别标签与刻度间隔、日期类别及其格式、标题旋转、坐标轴位置以及显示单位。

获取图表纵向坐标轴的最大值

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

读取get_ActualMaxValue和get_ActualMinValue获取坐标轴上下限,使用get_ActualMajorUnit和get_ActualMinorUnit获取刻度间隔。get_ActualMajorUnitScale和get_ActualMinorUnitScale提供时间单位比例,适用于日期坐标轴。示例将这些值存入局部变量并保存图表。

#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IChart.h>
#include <DOM/Chart/ChartType.h>
#include <DOM/Chart/IAxesManager.h>
#include <DOM/Chart/IAxis.h>
#include <Export/SaveFormat.h>

using namespace Aspose::Slides;
using namespace Aspose::Slides::Charts;
using namespace Aspose::Slides::Export;

auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);

auto chart = slide->get_Shapes()->AddChart(ChartType::Area, 100, 100, 500, 350);
chart->ValidateChartLayout();

auto maxValue = chart->get_Axes()->get_VerticalAxis()->get_ActualMaxValue();
auto minValue = chart->get_Axes()->get_VerticalAxis()->get_ActualMinValue();

auto majorUnit = chart->get_Axes()->get_VerticalAxis()->get_ActualMajorUnit();
auto minorUnit = chart->get_Axes()->get_VerticalAxis()->get_ActualMinorUnit();

auto majorUnitScale = chart->get_Axes()->get_VerticalAxis()->get_ActualMajorUnitScale();
auto minorUnitScale = chart->get_Axes()->get_VerticalAxis()->get_ActualMinorUnitScale();

presentation->Save(u"AxisValues_out.pptx", SaveFormat::Pptx);

在坐标轴之间交换数据

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

#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IChart.h>
#include <DOM/Chart/ChartType.h>
#include <DOM/Chart/IAxesManager.h>
#include <DOM/Chart/IAxis.h>
#include <Export/SaveFormat.h>
#include <DOM/Chart/IChartData.h>

using namespace Aspose::Slides;
using namespace Aspose::Slides::Charts;
using namespace Aspose::Slides::Export;

auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);

auto chart = slide->get_Shapes()->AddChart(ChartType::ClusteredColumn, 100, 100, 400, 300);

chart->get_ChartData()->SetRange(u"Sheet1!A1:D5");
chart->get_ChartData()->SwitchRowColumn();

presentation->Save(u"SwitchChartRowColumns_out.pptx", SaveFormat::Pptx);

为折线图禁用纵向坐标轴

在纵向坐标轴上使用set_IsVisible并设为false即可隐藏坐标轴。示例创建默认数据的折线图并在隐藏纵向坐标轴的情况下保存。

#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IChart.h>
#include <DOM/Chart/ChartType.h>
#include <DOM/Chart/IAxesManager.h>
#include <DOM/Chart/IAxis.h>
#include <Export/SaveFormat.h>

using namespace Aspose::Slides;
using namespace Aspose::Slides::Charts;
using namespace Aspose::Slides::Export;

auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);

auto chart = slide->get_Shapes()->AddChart(ChartType::Line, 100, 100, 400, 300);
chart->get_Axes()->get_VerticalAxis()->set_IsVisible(false);

presentation->Save(u"HiddenVerticalAxis.pptx", SaveFormat::Pptx);

为折线图禁用水平坐标轴

在水平坐标轴上使用set_IsVisible并设为false即可隐藏坐标轴。示例创建默认数据的折线图并在隐藏水平坐标轴的情况下保存。

#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IChart.h>
#include <DOM/Chart/ChartType.h>
#include <DOM/Chart/IAxesManager.h>
#include <DOM/Chart/IAxis.h>
#include <Export/SaveFormat.h>

using namespace Aspose::Slides;
using namespace Aspose::Slides::Charts;
using namespace Aspose::Slides::Export;

auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);

auto chart = slide->get_Shapes()->AddChart(ChartType::Line, 100, 100, 400, 300);
chart->get_Axes()->get_HorizontalAxis()->set_IsVisible(false);

presentation->Save(u"HiddenHorizontalAxis.pptx", SaveFormat::Pptx);

更改类别坐标轴

使用set_CategoryAxisType可选择日期或文本类别坐标轴。此示例需要ExistingChart.pptx,其中首张幻灯片的第一张形状为图表,类别单元格包含 Excel 数字日期值。它将水平坐标轴改为日期坐标轴。调用set_IsAutomaticMajorUnit并设为false、set_MajorUnit设为1、以及set_MajorUnitScale设为月份,可使主刻度间隔为一个月。

#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IChart.h>
#include <DOM/Chart/ChartType.h>
#include <DOM/Chart/IAxesManager.h>
#include <DOM/Chart/IAxis.h>
#include <Export/SaveFormat.h>
#include <DOM/Chart/CategoryAxisType.h>
#include <DOM/Chart/TimeUnitType.h>
#include <system/object_ext.h>

using namespace Aspose::Slides;
using namespace Aspose::Slides::Charts;
using namespace Aspose::Slides::Export;

auto presentation = System::MakeObject<Presentation>(u"ExistingChart.pptx");
auto slide = presentation->get_Slide(0);

auto chart = System::ExplicitCast<IChart>(slide->get_Shape(0));
chart->get_Axes()->get_HorizontalAxis()->set_CategoryAxisType(CategoryAxisType::Date);
chart->get_Axes()->get_HorizontalAxis()->set_IsAutomaticMajorUnit(false);
chart->get_Axes()->get_HorizontalAxis()->set_MajorUnit(1);
chart->get_Axes()->get_HorizontalAxis()->set_MajorUnitScale(TimeUnitType::Months);

presentation->Save(u"ChangeChartCategoryAxis_out.pptx", SaveFormat::Pptx);

控制类别坐标轴标签间隔

当图表类别较多时,可在不删除类别或数据点的前提下减少可见坐标轴标签的数量。使用set_IsAutomaticTickLabelSpacing并设为false,随后使用set_TickLabelSpacing设置所需的类别间隔。对于按正常顺序排列的文本类别,计数从第一个类别开始:

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

间隔为3时,每三个标签显示一次,两个标签被隐藏在已显示标签之间。它不会删除对应的列。自动间隔会根据可用空间选择间隔,未必显示所有标签。

刻度线拥有独立的控制。使用set_IsAutomaticTickMarksSpacing并设为false,再使用set_TickMarksSpacing设置它们的间隔。例如,1会在每个类别间隔保留一个刻度线,而标签仅每第三个类别显示一次。使用set_MajorTickMark并设为可见样式,以便看到效果。将任一自动间隔属性重新设为true,图表会再次自行选择间隔。

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

#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IChart.h>
#include <DOM/Chart/ChartType.h>
#include <DOM/Chart/IAxesManager.h>
#include <DOM/Chart/IAxis.h>
#include <Export/SaveFormat.h>
#include <DOM/Chart/IChartData.h>
#include <DOM/Chart/CategoryAxisType.h>
#include <DOM/Chart/TickMarkType.h>
#include <DOM/Chart/IChartTextFormat.h>
#include <DOM/Chart/IChartTextBlockFormat.h>
#include <DOM/Chart/IChartPortionFormat.h>
#include <DOM/Chart/IChartDataWorkbook.h>
#include <DOM/Chart/IChartDataCell.h>
#include <DOM/Chart/IChartCategoryCollection.h>
#include <DOM/Chart/IChartSeriesCollection.h>
#include <DOM/Chart/IChartSeries.h>
#include <DOM/Chart/IChartDataPointCollection.h>
#include <system/object_ext.h>
#include <DOM/ISlideCollection.h>

using namespace Aspose::Slides;
using namespace Aspose::Slides::Charts;
using namespace Aspose::Slides::Export;

auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);

auto chart = slide->get_Shapes()->AddChart(ChartType::ClusteredColumn, 30, 40, 660, 320);

chart->set_HasLegend(false);
chart->get_ChartData()->get_Categories()->Clear();
chart->get_ChartData()->get_Series()->Clear();

auto workbook = chart->get_ChartData()->get_ChartDataWorkbook();
workbook->Clear(0);

auto series = chart->get_ChartData()->get_Series()->Add(ChartType::ClusteredColumn);
for (auto i = 0; i < 24; i++)
{
    auto categoryName = System::String::Format(u"Category {0}", i + 1);
    auto categoryCell = workbook->GetCell(0, i + 1, 0, System::ObjectExt::Box(categoryName));
    chart->get_ChartData()->get_Categories()->Add(categoryCell);
    auto valueCell = workbook->GetCell(0, i + 1, 1, System::ObjectExt::Box(10 + i % 6 * 5));
    series->get_DataPoints()->AddDataPointForBarSeries(valueCell);
}

auto axis = chart->get_Axes()->get_HorizontalAxis();
axis->set_CategoryAxisType(CategoryAxisType::Text);
axis->get_TextFormat()->get_TextBlockFormat()->set_RotationAngle(0);
axis->get_TextFormat()->get_PortionFormat()->set_FontHeight(12);
axis->set_MajorTickMark(TickMarkType::Outside);
axis->set_IsAutomaticTickLabelSpacing(true);
axis->set_IsAutomaticTickMarksSpacing(true);

// 幻灯片 2:每三个标签显示一次,但为每个类别保留刻度线。
auto manualSlide = presentation->get_Slides()->AddClone(slide);
auto manualChart = System::ExplicitCast<IChart>(manualSlide->get_Shape(0));
auto manualAxis = manualChart->get_Axes()->get_HorizontalAxis();
manualAxis->set_IsAutomaticTickLabelSpacing(false);
manualAxis->set_TickLabelSpacing(3);
manualAxis->set_IsAutomaticTickMarksSpacing(false);
manualAxis->set_TickMarksSpacing(1);

// 幻灯片 3:让图表再次自行选择两个间隔。
auto restoredSlide = presentation->get_Slides()->AddClone(manualSlide);
auto restoredChart = System::ExplicitCast<IChart>(restoredSlide->get_Shape(0));
restoredChart->get_Axes()->get_HorizontalAxis()->set_IsAutomaticTickLabelSpacing(true);
restoredChart->get_Axes()->get_HorizontalAxis()->set_IsAutomaticTickMarksSpacing(true);

presentation->Save(u"CategoryAxisIntervals.pptx", SaveFormat::Pptx);

自动间隔(幻灯片 1): 在此渲染中,每隔一个类别标签会显示一次,并换行为两行。自动结果会随图表大小、字体和渲染器而变化。

自动类别标签间隔,所有 24 列均可见

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

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

选择正确的坐标轴和间隔

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

不要使用类别标签间隔来设置数值坐标轴的数值刻度。在数值坐标轴上,set_MajorUnit指定数值差异,例如 10 的主单位会在 0、10、20 等位置产生刻度(前提是坐标轴从零开始)。而类别标签间隔 3 只计数类别位置,与其数据值无关。散点图和气泡图使用数值坐标轴,而非文本类别坐标轴。对于日期坐标轴,请参考更改类别坐标轴中描述的基于时间的主单位和比例。

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

示例用四个年度值替换默认图表数据。日期以 OLE Automation 序列号存储在第一张工作表(索引 0)中。使用set_CategoryAxisType选择日期坐标轴,使用set_IsNumberFormatLinkedToSource关闭源链接的数字格式,并使用set_NumberFormat将格式设为yyyy,从而使类别标签独立于单元格格式显示四位年份。

#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IChart.h>
#include <DOM/Chart/ChartType.h>
#include <DOM/Chart/IAxesManager.h>
#include <DOM/Chart/IAxis.h>
#include <Export/SaveFormat.h>
#include <DOM/Chart/IChartData.h>
#include <DOM/Chart/CategoryAxisType.h>
#include <DOM/Chart/IChartDataWorkbook.h>
#include <DOM/Chart/IChartDataCell.h>
#include <DOM/Chart/IChartCategoryCollection.h>
#include <DOM/Chart/IChartSeriesCollection.h>
#include <DOM/Chart/IChartSeries.h>
#include <DOM/Chart/IChartDataPointCollection.h>
#include <system/object_ext.h>
#include <system/date_time.h>

using namespace Aspose::Slides;
using namespace Aspose::Slides::Charts;
using namespace Aspose::Slides::Export;

auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);

auto chart = slide->get_Shapes()->AddChart(ChartType::Line, 50, 50, 450, 300);

chart->get_ChartData()->get_Categories()->Clear();
chart->get_ChartData()->get_Series()->Clear();

auto workbook = chart->get_ChartData()->get_ChartDataWorkbook();
workbook->Clear(0);

auto series = chart->get_ChartData()->get_Series()->Add(ChartType::Line);
for (auto i = 0; i < 4; i++)
{
    auto date = System::DateTime(2015 + i, 1, 1);
    auto categoryCell = workbook->GetCell(0, i + 1, 0, System::ObjectExt::Box(date.ToOADate()));
    chart->get_ChartData()->get_Categories()->Add(categoryCell);

    auto valueCell = workbook->GetCell(0, i + 1, 1, System::ObjectExt::Box(i + 1));
    series->get_DataPoints()->AddDataPointForLineSeries(valueCell);
}

chart->get_Axes()->get_HorizontalAxis()->set_CategoryAxisType(CategoryAxisType::Date);
chart->get_Axes()->get_HorizontalAxis()->set_IsNumberFormatLinkedToSource(false);
chart->get_Axes()->get_HorizontalAxis()->set_NumberFormat(u"yyyy");

presentation->Save(u"DateAxisFormat.pptx", SaveFormat::Pptx);

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

使用set_HasTitle启用纵向坐标轴标题,提供标题文本,并使用set_RotationAngle旋转标题。角度以度为单位;本示例将柱形图的数值轴标题旋转 90 度后保存。

#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IChart.h>
#include <DOM/Chart/ChartType.h>
#include <DOM/Chart/IAxesManager.h>
#include <DOM/Chart/IAxis.h>
#include <Export/SaveFormat.h>
#include <DOM/Chart/IChartTextFormat.h>
#include <DOM/Chart/IChartTextBlockFormat.h>
#include <DOM/Chart/IChartTitle.h>

using namespace Aspose::Slides;
using namespace Aspose::Slides::Charts;
using namespace Aspose::Slides::Export;

auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);

auto chart = slide->get_Shapes()->AddChart(ChartType::ClusteredColumn, 50, 50, 450, 300);
chart->get_Axes()->get_VerticalAxis()->set_HasTitle(true);
chart->get_Axes()->get_VerticalAxis()->get_Title()->AddTextFrameForOverriding(u"Value");
chart->get_Axes()->get_VerticalAxis()->get_Title()->get_TextFormat()->get_TextBlockFormat()->set_RotationAngle(90);

presentation->Save(u"RotatedAxisTitle.pptx", SaveFormat::Pptx);

在类别或数值坐标轴上设置坐标轴位置

使用set_AxisBetweenCategories可控制数值坐标轴是穿过类别坐标轴的类别之间还是在类别刻度线上。此属性适用于类别坐标轴。示例在柱形图的水平类别坐标轴上将其设为true并保存结果。

#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IChart.h>
#include <DOM/Chart/ChartType.h>
#include <DOM/Chart/IAxesManager.h>
#include <DOM/Chart/IAxis.h>
#include <Export/SaveFormat.h>

using namespace Aspose::Slides;
using namespace Aspose::Slides::Charts;
using namespace Aspose::Slides::Export;

auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);

auto chart = slide->get_Shapes()->AddChart(ChartType::ClusteredColumn, 50, 50, 450, 300);
chart->get_Axes()->get_HorizontalAxis()->set_AxisBetweenCategories(true);

presentation->Save(u"AxisBetweenCategories.pptx", SaveFormat::Pptx);

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

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

#include <DOM/Presentation.h>
#include <DOM/ISlide.h>
#include <DOM/IShapeCollection.h>
#include <DOM/IChart.h>
#include <DOM/Chart/ChartType.h>
#include <DOM/Chart/IAxesManager.h>
#include <DOM/Chart/IAxis.h>
#include <Export/SaveFormat.h>
#include <DOM/Chart/DisplayUnitType.h>

using namespace Aspose::Slides;
using namespace Aspose::Slides::Charts;
using namespace Aspose::Slides::Export;

auto presentation = System::MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);

auto chart = slide->get_Shapes()->AddChart(ChartType::ClusteredColumn, 50, 50, 450, 300);
chart->get_Axes()->get_VerticalAxis()->set_DisplayUnit(DisplayUnitType::Millions);

presentation->Save(u"Result.pptx", SaveFormat::Pptx);

常见问题解答

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

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

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

使用set_TickLabelPosition并从TickLabelPositionType中选择 Low、High、NextTo 或 None。若要控制刻度线本身,请使用set_MajorTickMark或set_MinorTickMark,它们独立于标签定位。