Управление метками данных диаграмм в презентациях с помощью PHP
Введение
Метки данных отображают информацию о сериях диаграммы и отдельных точках данных, помогая читателям определять значения и понимать диаграмму. В этой статье объясняется, как форматировать значения, отображать проценты, считывать текст метки, управлять метками за пределами максимума оси, регулировать интервал меток оси категорий и позиционировать метки круговой диаграммы.
Установка точности данных в метках диаграмм
Используйте setNumberFormatOfValues для форматирования значений серии. В этом примере создаётся линейная диаграмма с данными по умолчанию, отображается её табличные данные и включаются метки значений для первой серии. Формат #,##0.00 показывает разделитель тысяч и две десятичные части без изменения исходных значений.
use aspose\slides\Presentation;
use aspose\slides\ChartType;
use aspose\slides\SaveFormat;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$chart = $slide->getShapes()->addChart(ChartType::Line, 50, 50, 450, 300);
$chart->setDataTable(true);
$series = $chart->getChartData()->getSeries()->get_Item(0);
$series->setNumberFormatOfValues("#,##0.00");
$series->getLabels()->getDefaultDataLabelFormat()->setShowValue(true);
$presentation->save("PrecisionOfDatalabels_out.pptx", SaveFormat::Pptx);
} finally {
$presentation->dispose();
}
Отображение процентов в виде меток
Для накопленной столбчатой диаграммы вычислите каждое значение как процент от общей суммы категории и присвойте текст текстовому фрейму, возвращаемому getTextFrameForOverriding. В этом примере используются данные диаграммы по умолчанию и отображаются проценты с двумя знаками после запятой шрифтом 8 пунктов. Категории с общей суммой, равной нулю, пропускаются, чтобы избежать деления на ноль. При изменении данных диаграммы пересчитайте пользовательский текст метки.
use aspose\slides\Presentation;
use aspose\slides\ChartType;
use aspose\slides\Portion;
use aspose\slides\SaveFormat;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$chart = $slide->getShapes()->addChart(ChartType::StackedColumn, 20, 20, 400, 400);
$categoryCount = java_values($chart->getChartData()->getCategories()->size());
$categoryTotals = array_fill(0, $categoryCount, 0.0);
for ($k = 0; $k < $categoryCount; $k++) {
for ($i = 0; $i < java_values($chart->getChartData()->getSeries()->size()); $i++) {
$series = $chart->getChartData()->getSeries()->get_Item($i);
$pointValue = java_values($series->getDataPoints()->get_Item($k)->getValue()->getData());
$categoryTotals[$k] += $pointValue;
}
}
for ($x = 0; $x < java_values($chart->getChartData()->getSeries()->size()); $x++) {
$series = $chart->getChartData()->getSeries()->get_Item($x);
$series->getLabels()->getDefaultDataLabelFormat()->setShowLegendKey(false);
for ($j = 0; $j < java_values($series->getDataPoints()->size()); $j++) {
$label = $series->getDataPoints()->get_Item($j)->getLabel();
if ($categoryTotals[$j] == 0) {
continue;
}
$pointValue = java_values($series->getDataPoints()->get_Item($j)->getValue()->getData());
$dataPointPercent = ($pointValue / $categoryTotals[$j]) * 100;
$portion = new Portion();
$portion->setText(sprintf("%.2F %%", $dataPointPercent));
$portion->getPortionFormat()->setFontHeight(8);
$label->getTextFrameForOverriding()->setText("");
$paragraph = $label->getTextFrameForOverriding()->getParagraphs()->get_Item(0);
$paragraph->getPortions()->add($portion);
$label->getDataLabelFormat()->setShowValue(true);
$label->getDataLabelFormat()->setShowSeriesName(false);
$label->getDataLabelFormat()->setShowPercentage(false);
$label->getDataLabelFormat()->setShowLegendKey(false);
$label->getDataLabelFormat()->setShowCategoryName(false);
$label->getDataLabelFormat()->setShowBubbleSize(false);
}
}
$presentation->save("DisplayPercentageAsLabels_out.pptx", SaveFormat::Pptx);
} finally {
$presentation->dispose();
}
Установка знака процента в метках данных диаграммы
Когда значения хранятся в виде дробей, используйте setNumberFormat для отображения процентов. Передайте false в setNumberFormatLinkedToSource, чтобы применить формат метки независимо от ячеек‑источников.
В этом примере создаётся 100% накопленная столбчатая диаграмма с красными и синими сериями для четырёх категорий. Каждая пара значений в сумме даёт 1. Формат метки 0.0% отображает 0,30 как 30,0 %, тогда как вертикальная ось использует два знака после запятой. Обе серии используют белый текст метки размером 10 пунктов.
use aspose\slides\Presentation;
use aspose\slides\ChartType;
use aspose\slides\FillType;
use aspose\slides\SaveFormat;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$chart = $slide->getShapes()->addChart(ChartType::PercentsStackedColumn, 20, 20, 500, 400);
$chart->getAxes()->getVerticalAxis()->setNumberFormatLinkedToSource(false);
$chart->getAxes()->getVerticalAxis()->setNumberFormat("0.00%");
$chart->getChartData()->getSeries()->clear();
$chart->getChartData()->getCategories()->clear();
$workbook = $chart->getChartData()->getChartDataWorkbook();
$worksheetIndex = 0;
for ($i = 0; $i < 4; $i++) {
$categoryCell = $workbook->getCell($worksheetIndex, $i + 1, 0, "Category " . ($i + 1));
$chart->getChartData()->getCategories()->add($categoryCell);
}
$colors = java("java.awt.Color");
$seriesNames = [ "Reds", "Blues" ];
$seriesColors = [ $colors->RED, $colors->BLUE ];
$values = [ [ 0.30, 0.50, 0.80, 0.65 ], [ 0.70, 0.50, 0.20, 0.35 ] ];
for ($i = 0; $i < count($seriesNames); $i++) {
$seriesCell = $workbook->getCell($worksheetIndex, 0, $i + 1, $seriesNames[$i]);
$series = $chart->getChartData()->getSeries()->add($seriesCell, $chart->getType());
for ($j = 0; $j < 4; $j++) {
$valueCell = $workbook->getCell($worksheetIndex, $j + 1, $i + 1, $values[$i][$j]);
$series->getDataPoints()->addDataPointForBarSeries($valueCell);
}
$series->getFormat()->getFill()->setFillType(FillType::Solid);
$series->getFormat()->getFill()->getSolidFillColor()->setColor($seriesColors[$i]);
$labelFormat = $series->getLabels()->getDefaultDataLabelFormat();
$labelFormat->setShowValue(true);
$labelFormat->setNumberFormatLinkedToSource(false);
$labelFormat->setNumberFormat("0.0%");
$labelFormat->getTextFormat()->getPortionFormat()->setFontHeight(10);
$labelFormat->getTextFormat()->getPortionFormat()->getFillFormat()->setFillType(FillType::Solid);
$labelFormat->getTextFormat()->getPortionFormat()->getFillFormat()->getSolidFillColor()->setColor($colors->WHITE);
}
$presentation->save("SetDataLabelsPercentageSign_out.pptx", SaveFormat::Pptx);
} finally {
$presentation->dispose();
}
Чтение фактического текста меток данных
Используйте getActualLabelText для получения текста, сформированного настройками метки данных. Это полезно при извлечении меток для отчётов, поиске содержимого презентации или проверке сгенерированных диаграмм. В примере ниже формат метки данных по умолчанию data label format объединяет название каждой категории, название серии и значение. Одна точка форматирует своё значение как процент, а другая использует пользовательский текст из getTextFrameForOverriding.
use aspose\slides\Presentation;
use aspose\slides\ChartType;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$chart = $slide->getShapes()->addChart(ChartType::ClusteredColumn, 20, 20, 500, 300);
$chart->getChartData()->getSeries()->clear();
$chart->getChartData()->getCategories()->clear();
$workbook = $chart->getChartData()->getChartDataWorkbook();
$firstCategoryCell = $workbook->getCell(0, 1, 0, "Q1");
$chart->getChartData()->getCategories()->add($firstCategoryCell);
$secondCategoryCell = $workbook->getCell(0, 2, 0, "Q2");
$chart->getChartData()->getCategories()->add($secondCategoryCell);
$northSeriesCell = $workbook->getCell(0, 0, 1, "North");
$north = $chart->getChartData()->getSeries()->add($northSeriesCell, $chart->getType());
$northFirstValueCell = $workbook->getCell(0, 1, 1, 0.25);
$north->getDataPoints()->addDataPointForBarSeries($northFirstValueCell);
$northSecondValueCell = $workbook->getCell(0, 2, 1, 0.75);
$north->getDataPoints()->addDataPointForBarSeries($northSecondValueCell);
$southSeriesCell = $workbook->getCell(0, 0, 2, "South");
$south = $chart->getChartData()->getSeries()->add($southSeriesCell, $chart->getType());
$southFirstValueCell = $workbook->getCell(0, 1, 2, 0.40);
$south->getDataPoints()->addDataPointForBarSeries($southFirstValueCell);
$southSecondValueCell = $workbook->getCell(0, 2, 2, 0.60);
$south->getDataPoints()->addDataPointForBarSeries($southSecondValueCell);
for ($i = 0; $i < java_values($chart->getChartData()->getSeries()->size()); $i++) {
$series = $chart->getChartData()->getSeries()->get_Item($i);
$format = $series->getLabels()->getDefaultDataLabelFormat();
$format->setShowCategoryName(true);
$format->setShowSeriesName(true);
$format->setShowValue(true);
}
$north->getLabels()->get_Item(1)->getDataLabelFormat()->setNumberFormatLinkedToSource(false);
$north->getLabels()->get_Item(1)->getDataLabelFormat()->setNumberFormat("0%");
$south->getLabels()->get_Item(0)->getTextFrameForOverriding()->setText("Reviewed");
for ($i = 0; $i < java_values($chart->getChartData()->getSeries()->size()); $i++) {
$series = $chart->getChartData()->getSeries()->get_Item($i);
for ($j = 0; $j < java_values($series->getDataPoints()->size()); $j++) {
$point = $series->getDataPoints()->get_Item($j);
$label = $point->getLabel();
if (!java_values($label->isVisible())) {
continue;
}
echo "Value: " . java_values($point->getValue()->getData()) . "; label: " . java_values($label->getActualLabelText()) . PHP_EOL;
}
}
} finally {
$presentation->dispose();
}
Число, хранящееся в точке данных, остаётся 0.75, даже если её метка отображает 75% вместе с названиями категории и серии. Пользовательский текст заменяет сгенерированный текст метки. getActualLabelText возвращает полученную строку метки в любом случае. Проверяйте isVisible отдельно, как показано выше, если нужно извлекать только видимые метки.
Управление метками данных за пределами максимума оси
Когда диапазон оси задаётся вручную, некоторые точки данных могут превышать её максимум. Используйте setShowDataLabelsOverMaximum для управления тем, отображаются ли их метки данных. Эта настройка изменяет видимость меток; она не меняет диапазон оси и исходные значения данных.
В примере ниже создаётся двумерная сгруппированная столбчатая диаграмма со значениями 60 и 120. В неё передаётся false в setAutomaticMaxValue и устанавливается максимум 100 с помощью setMaxValue на вертикальной оси. На первом слайде разрешены метки за пределами максимума; копия этого слайда отключает их. Оба слайда сохраняются в DataLabelsOverMaximum.pptx.
Включите метки значений с помощью setShowValue. Настройка уровня диаграммы не включает отображение значений сама по себе и не переопределяет отключённое отображение значений отдельной метки. В этом примере включаются значения для всей серии и используется setPosition для размещения меток в наружном конце каждого столбца.
use aspose\slides\Presentation;
use aspose\slides\ChartType;
use aspose\slides\LegendDataLabelPosition;
use aspose\slides\SaveFormat;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$chart = $slide->getShapes()->addChart(ChartType::ClusteredColumn, 50, 50, 600, 400);
$chart->setLegend(false);
$chart->getChartData()->getSeries()->clear();
$chart->getChartData()->getCategories()->clear();
$workbook = $chart->getChartData()->getChartDataWorkbook();
$firstCategory = $workbook->getCell(0, 1, 0, "Within range");
$secondCategory = $workbook->getCell(0, 2, 0, "Above maximum");
$chart->getChartData()->getCategories()->add($firstCategory);
$chart->getChartData()->getCategories()->add($secondCategory);
$seriesName = $workbook->getCell(0, 0, 1, "Values");
$series = $chart->getChartData()->getSeries()->add($seriesName, $chart->getType());
$firstValue = $workbook->getCell(0, 1, 1, 60);
$secondValue = $workbook->getCell(0, 2, 1, 120);
$series->getDataPoints()->addDataPointForBarSeries($firstValue);
$series->getDataPoints()->addDataPointForBarSeries($secondValue);
$series->getLabels()->getDefaultDataLabelFormat()->setShowValue(true);
$series->getLabels()->getDefaultDataLabelFormat()->setPosition(LegendDataLabelPosition::OutsideEnd);
$chart->getAxes()->getVerticalAxis()->setAutomaticMaxValue(false);
$chart->getAxes()->getVerticalAxis()->setMaxValue(100);
$chart->setShowDataLabelsOverMaximum(true);
$secondSlide = $presentation->getSlides()->addClone($slide);
$secondChart = $secondSlide->getShapes()->get_Item(0);
$secondChart->setShowDataLabelsOverMaximum(false);
$presentation->save("DataLabelsOverMaximum.pptx", SaveFormat::Pptx);
} finally {
$presentation->dispose();
}
Ниже показаны изображения сохранённых слайдов, отрисованных в Microsoft PowerPoint. При true метка 120 видна у верхней границы; при false она скрыта. Метка 60 остаётся видимой, максимум оси остаётся 100, и в обоих случаях второй пункт данных остаётся 120.
| setShowDataLabelsOverMaximum(true) | setShowDataLabelsOverMaximum(false) |
|---|---|
![]() |
![]() |
Chart Type
В этом примере используется двумерная столбчатая диаграмма с осью значений. Диаграммы без оси значений, такие как круговые и кольцевые диаграммы, не имеют максимума оси, который можно ограничить таким образом.Установка расстояния метки от оси
Используйте setLabelOffset для контроля расстояния между метками оси категорий и самой осью. Значение представляет собой процент от максимального размера шрифта меток оси. В этом примере создаётся сгруппированная столбчатая диаграмма и устанавливается смещение метки горизонтальной оси равным 500. Эта настройка влияет на метки оси категорий, а не на метки, привязанные к отдельным точкам данных.
use aspose\slides\Presentation;
use aspose\slides\ChartType;
use aspose\slides\SaveFormat;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$chart = $slide->getShapes()->addChart(ChartType::ClusteredColumn, 20, 20, 500, 300);
$chart->getAxes()->getHorizontalAxis()->setLabelOffset(500);
$presentation->save("SetCategoryAxisLabelDistance_out.pptx", SaveFormat::Pptx);
} finally {
$presentation->dispose();
}
Регулировка положения меток
На круговой диаграмме отрегулируйте позиции меток данных, чтобы улучшить интервал и освободить место для выноски.
В этом примере отображается значение первой точки данных, её метка помещается за пределы сектора и регулируются горизонтальное и вертикальное смещения с помощью setX и setY. Эти смещения относительно ширины и высоты диаграммы соответственно.
use aspose\slides\Presentation;
use aspose\slides\ChartType;
use aspose\slides\LegendDataLabelPosition;
use aspose\slides\SaveFormat;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$chart = $slide->getShapes()->addChart(ChartType::Pie, 50, 50, 200, 200);
$series = $chart->getChartData()->getSeries();
$label = $series->get_Item(0)->getLabels()->get_Item(0);
$label->getDataLabelFormat()->setShowValue(true);
$label->getDataLabelFormat()->setPosition(LegendDataLabelPosition::OutsideEnd);
$label->setX(0.71);
$label->setY(0.04);
$presentation->save("presentation.pptx", SaveFormat::Pptx);
} finally {
$presentation->dispose();
}

Добавление нескольких строк меток над столбчатой диаграммой
В этом примере создаётся столбчатая диаграмма с двумя строками меток над областью построения. Серия A отображает видимые столбцы, а серии B и C предоставляют дополнительные метки. Их столбцы скрыты за счёт удаления заливки и контура. Метод ChartSeriesGroup::setOverlap выравнивает все три серии по тем же центрам категорий.
Настройки ChartPlotArea резервируют место для строк меток. После того как Chart::validateChartLayout вычисляет позиции по умолчанию, DataLabel::setX и DataLabel::setY сохраняют горизонтальное выравнивание и применяют вертикальные смещения для размещения меток в две строки. Числа остаются метками данных, связанными со значениями серии; только заголовки строк являются отдельными текстовыми фигурами.
use aspose\slides\Presentation;
use aspose\slides\ChartType;
use aspose\slides\FillType;
use aspose\slides\LegendDataLabelPosition;
use aspose\slides\LayoutTargetType;
use aspose\slides\ShapeType;
use aspose\slides\SaveFormat;
$colors = java("java.awt.Color");
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$chart = $slide->getShapes()->addChart(ChartType::ClusteredColumn, 40, 40, 640, 200);
$chart->setTitle(false);
$chart->setLegend(false);
$chart->getTextFormat()->getPortionFormat()->setFontHeight(12);
$chart->getChartData()->getSeries()->clear();
$chart->getChartData()->getCategories()->clear();
$workbook = $chart->getChartData()->getChartDataWorkbook();
$workbook->clear(0);
$categories = [ "North", "South", "East", "West" ];
$seriesNames = [ "Series A", "Series B", "Series C" ];
$seriesValues = [
[ 35, 42, 28, 47 ],
[ 22, 31, 19, 26 ],
[ 12, 16, 14, 18 ]
];
for ($categoryIndex = 0; $categoryIndex < count($categories); $categoryIndex++) {
$categoryCell = $workbook->getCell(0, $categoryIndex + 1, 0, $categories[$categoryIndex]);
$chart->getChartData()->getCategories()->add($categoryCell);
}
for ($seriesIndex = 0; $seriesIndex < count($seriesNames); $seriesIndex++) {
$seriesCell = $workbook->getCell(0, 0, $seriesIndex + 1, $seriesNames[$seriesIndex]);
$series = $chart->getChartData()->getSeries()->add($seriesCell, ChartType::ClusteredColumn);
for ($categoryIndex = 0; $categoryIndex < count($categories); $categoryIndex++) {
$valueCell = $workbook->getCell(0, $categoryIndex + 1, $seriesIndex + 1, $seriesValues[$seriesIndex][$categoryIndex]);
$series->getDataPoints()->addDataPointForBarSeries($valueCell);
}
if ($seriesIndex > 0) {
// Скрыть столбцы B и C, но оставить их метки данных.
$series->getFormat()->getFill()->setFillType(FillType::NoFill);
$series->getFormat()->getLine()->getFillFormat()->setFillType(FillType::NoFill);
$labelFormat = $series->getLabels()->getDefaultDataLabelFormat();
$labelFormat->setShowValue(true);
$labelFormat->getTextFormat()->getPortionFormat()->setFontHeight(12);
$labelFill = $labelFormat->getTextFormat()->getPortionFormat()->getFillFormat();
$labelFill->setFillType(FillType::Solid);
$labelFill->getSolidFillColor()->setColor($colors->BLACK);
$labelFormat->setPosition(LegendDataLabelPosition::InsideBase);
}
}
// Выравниваем все три серии по тем же центрам категорий.
$chart->getChartData()->getSeries()->get_Item(0)->getParentSeriesGroup()->setOverlap(100);
// Используем меньше сеточных линий для этого компактного примера.
$chart->getAxes()->getVerticalAxis()->setAutomaticMajorUnit(false);
$chart->getAxes()->getVerticalAxis()->setMajorUnit(10);
// Зарезервировать пространство над областью построения для двух строк меток данных.
$chart->getPlotArea()->setLayoutTargetType(LayoutTargetType::Inner);
$chart->getPlotArea()->setX(0.15);
$chart->getPlotArea()->setY(0.32);
$chart->getPlotArea()->setWidth(0.80);
$chart->getPlotArea()->setHeight(0.48);
$chart->validateChartLayout();
$chartX = java_values($chart->getX());
$chartY = java_values($chart->getY());
$chartHeight = java_values($chart->getHeight());
for ($seriesIndex = 1; $seriesIndex < count($seriesNames); $seriesIndex++) {
$series = $chart->getChartData()->getSeries()->get_Item($seriesIndex);
$rowTop = $seriesIndex == 1 ? 0.15 : 0.03;
for ($categoryIndex = 0; $categoryIndex < count($categories); $categoryIndex++) {
$dataLabel = $series->getDataPoints()->get_Item($categoryIndex)->getLabel();
// Оставить положение по умолчанию по горизонтали. Y — смещение от
// позиции метки по умолчанию, выраженное как доля высоты диаграммы.
$actualY = java_values($dataLabel->getActualY());
$dataLabel->setX(0);
$dataLabel->setY($rowTop - $actualY / $chartHeight);
}
// Только заголовок строки является отдельной текстовой фигурой.
$rowHeading = $slide->getShapes()->addAutoShape(ShapeType::Rectangle, $chartX, $chartY + $rowTop * $chartHeight, 85, 18);
$rowHeading->getFillFormat()->setFillType(FillType::NoFill);
$rowHeading->getLineFormat()->getFillFormat()->setFillType(FillType::NoFill);
$rowHeading->addTextFrame($seriesNames[$seriesIndex]);
$rowHeading->getTextFrame()->getTextFrameFormat()->setMarginTop(0);
$rowHeading->getTextFrame()->getTextFrameFormat()->setMarginBottom(0);
$headingFormat = $rowHeading->getTextFrame()->getParagraphs()->get_Item(0)->getPortions()->get_Item(0)->getPortionFormat();
$headingFormat->setFontHeight(12);
$headingFormat->getFillFormat()->setFillType(FillType::Solid);
$headingFormat->getFillFormat()->getSolidFillColor()->setColor($colors->BLACK);
}
$presentation->save("multiple-rows-of-labels.pptx", SaveFormat::Pptx);
} finally {
$presentation->dispose();
}

FAQ
Как предотвратить наложение меток данных на плотных диаграммах?
Сочетайте автоматическое размещение меток, выносные линии и уменьшенный размер шрифта; при необходимости скрывайте некоторые поля (например, категорию) или отображайте метки только для экстремальных значений или ключевых точек.
Как отключить метки только для нулевых, отрицательных или пустых значений?
Отфильтруйте точки данных перед включением меток и отключите отображение для значений 0, отрицательных значений или отсутствующих значений в соответствии с определённым правилом.
Как обеспечить единый стиль меток при экспорте в PDF/изображения?
Явно задайте семейство шрифта и размер и убедитесь, что шрифт доступен в среде рендеринга, чтобы избежать подстановки.

