Управление сериями данных диаграмм в презентациях на .NET

Обзор

Диаграмма хранит свои построенные данные в рабочей книге данных диаграммы. IChartSeries представляет один набор связанных значений, и каждый IChartDataPoint в серии ссылается на одну или несколько ячеек рабочей книги. Объекты IChartCategory предоставляют подписи или группирующие значения, общие для серии. Поэтому имя серии, категории и значения точек связаны с объектами IChartDataCell, а не хранятся только как отображаемый текст.

Для типичной диаграммы категорий рабочая книга по умолчанию использует строку 0 для имён серий, столбец 0 для имён категорий и остальные ячейки для значений серий. Индексы листа, строки и столбца, передаваемые в IChartDataWorkbook.GetCell, начинаются с 0. Такой макет полезен, когда вы создаёте диаграмму с данными по умолчанию, но не следует полагаться, что каждая существующая диаграмма использует его. Для загруженной презентации проверьте ячейки, на которые ссылаются серии, категории и точки данных, перед изменением значений рабочей книги.

Настройки диаграммы имеют три различных уровня:

  • Настройки уровня серии, такие как IChartSeries.Format, задают внешний вид по умолчанию для всех точек в одной серии.
  • Настройки отдельной точки, такие как IChartDataPoint.Format, переопределяют внешний вид серии для одной точки.
  • Настройки группы применяются к совместимым сериям, принадлежащим одному IChartSeriesGroup. Доступ к группе осуществляется через IChartSeries.ParentSeriesGroup, когда необходимо задать параметры, такие как перекрытие или ширина промежутка.

Когда явное заполнение точки или серии не установлено, стиль диаграммы и тема определяют автоматический внешний вид. Когда присутствует как форматирование серии, так и точек, форматирование точки имеет приоритет для этой точки.

chart-series-powerpoint

Установить перекрытие серии диаграммы

IChartSeries.Overlap показывает, насколько бары или столбцы перекрываются в 2D‑диаграмме, от ‑100 % до 100 %. Это только чтение проекции параметра в родительской группе серий. Установите IChartSeriesGroup.Overlap, чтобы обновить каждую совместимую серию в этой группе. Эта опция применяется к типам диаграмм, отображающим группированные бары или столбцы; она не влияет на независимые группы серий в комбинированной диаграмме.

Следующий пример задаёт перекрытие для группы, содержащей первую серию:

using Aspose.Slides;
using Aspose.Slides.Charts;
using Aspose.Slides.Export;

const int firstSlideIndex = 0;
const int firstSeriesIndex = 0;
const sbyte overlapPercent = 30;

using var presentation = new Presentation();
var slide = presentation.Slides[firstSlideIndex];

// Новая диаграмма содержит примерные серии, категории и значения.
var chart = slide.Shapes.AddChart(ChartType.ClusteredColumn, 20, 20, 500, 200);

var series = chart.ChartData.Series[firstSeriesIndex];
series.ParentSeriesGroup.Overlap = overlapPercent;

presentation.Save("series_overlap.pptx", SaveFormat.Pptx);

Результат:

The series overlap

Изменить цвет заливки серии

Используйте IChartSeries.Format для установки заливки по умолчанию для всей серии. Если точка уже имеет явную заливку, её настройка IChartDataPoint.Format переопределяет заливку серии для этой точки.

Следующий пример применяет сплошную синюю заливку к первой серии:

using System.Drawing;
using Aspose.Slides;
using Aspose.Slides.Charts;
using Aspose.Slides.Export;

const int firstSlideIndex = 0;
const int firstSeriesIndex = 0;

using var presentation = new Presentation();
var slide = presentation.Slides[firstSlideIndex];

var chart = slide.Shapes.AddChart(ChartType.ClusteredColumn, 20, 20, 500, 200);

var series = chart.ChartData.Series[firstSeriesIndex];
series.Format.Fill.FillType = FillType.Solid;
series.Format.Fill.SolidFillColor.Color = Color.Blue;

presentation.Save("series_color.pptx", SaveFormat.Pptx);

Результат:

The color of the series

Изменить имя серии

Имя серии хранится в рабочей книге данных диаграммы и обычно отображается в легенде. В рабочей книге по умолчанию для сгруппированной столбчатой диаграммы ячейка B1 находится в строке 0, столбце 1 и содержит имя первой серии. Именованные константы в следующем примере делают эту структуру явной:

using Aspose.Slides;
using Aspose.Slides.Charts;
using Aspose.Slides.Export;

const int firstSlideIndex = 0;
const int worksheetIndex = 0;
const int seriesNameRowIndex = 0;
const int firstSeriesColumnIndex = 1;

using var presentation = new Presentation();
var slide = presentation.Slides[firstSlideIndex];

var chart = slide.Shapes.AddChart(ChartType.ClusteredColumn, 20, 20, 500, 200);

var workbook = chart.ChartData.ChartDataWorkbook;
var seriesNameCell = workbook.GetCell(worksheetIndex, seriesNameRowIndex, firstSeriesColumnIndex);
seriesNameCell.Value = "Revenue";

presentation.Save("series_name.pptx", SaveFormat.Pptx);

Вы также можете обновить ячейку, уже ссылку на которую имеет IChartSeries.Name. Такой подход позволяет не полагаться на конкретные строки и столбцы в существующей диаграмме:

using Aspose.Slides;
using Aspose.Slides.Charts;
using Aspose.Slides.Export;

const int firstSlideIndex = 0;
const int firstSeriesIndex = 0;
const int firstNameCellIndex = 0;

using var presentation = new Presentation();
var slide = presentation.Slides[firstSlideIndex];

var chart = slide.Shapes.AddChart(ChartType.ClusteredColumn, 20, 20, 500, 200);

var series = chart.ChartData.Series[firstSeriesIndex];
var seriesNameCell = series.Name.AsCells[firstNameCellIndex];
seriesNameCell.Value = "Revenue";

presentation.Save("series_name.pptx", SaveFormat.Pptx);

Результат:

The series name

Создать серию с именем из нескольких ячеек

Составное имя серии полезно, когда название продукта и отчетный период хранятся в отдельных ячейках рабочей книги. Например, можно объединить Product A в B1 и 2026 в C1 в одно имя серии, сохранив связь обеих частей с их исходными ячейками.

Используйте IChartDataWorkbook.GetCellCollection для получения диапазона имён, затем передайте эту коллекцию в IChartSeriesCollection.Add. Параметр skipHiddenCells определяет, включать ли скрытые ячейки: true исключает их, false — включает. В этом примере используется false, чтобы включить каждую ячейку диапазона имён.

Следующий пример создаёт презентацию с одной серией и двумя точками данных. Ячейки B1:C1 содержат только имя серии; A2:A3 — подписи категорий, а B2:B3 — числовые значения.

using Aspose.Slides;
using Aspose.Slides.Charts;
using Aspose.Slides.Export;

using var presentation = new Presentation();
var slide = presentation.Slides[0];

var chart = slide.Shapes.AddChart(ChartType.ClusteredColumn, 50, 50, 620, 180);

chart.ChartData.Series.Clear();
chart.ChartData.Categories.Clear();
chart.HasLegend = true;

var workbook = chart.ChartData.ChartDataWorkbook;
workbook.Clear(0);

// Эти две ячейки задают имя серии.
workbook.GetCell(0, 0, 1, "Product A");
workbook.GetCell(0, 0, 2, "2026");
var nameCells = workbook.GetCellCollection("Sheet1!$B$1:$C$1", skipHiddenCells: false);
var series = chart.ChartData.Series.Add(nameCells, ChartType.ClusteredColumn);

// Отдельные ячейки задают категории и числовые точки данных.
var northCategory = workbook.GetCell(0, 1, 0, "North");
var southCategory = workbook.GetCell(0, 2, 0, "South");
chart.ChartData.Categories.Add(northCategory);
chart.ChartData.Categories.Add(southCategory);
var northValue = workbook.GetCell(0, 1, 1, 120);
var southValue = workbook.GetCell(0, 2, 1, 150);
series.DataPoints.AddDataPointForBarSeries(northValue);
series.DataPoints.AddDataPointForBarSeries(southValue);

presentation.Save("composite_series_name.pptx", SaveFormat.Pptx);

Полученное имя серии — Product A 2026, между двумя значениями вставлен пробел. Легенда отображает его как одну запись для обоих столбцов. Ниже изображение, полученное из сохранённой презентации:

Column chart with North and South values and the composite series name Product A 2026 in the legend

Получить автоматический цвет заливки серии

IChartSeries.GetAutomaticSeriesColor возвращает цвет, рассчитанный из индекса серии и стиля диаграммы. Это цвет, используемый, когда заливка серии явно не определена. Вызов метода лишь получает рассчитанный цвет; он не задаёт новую заливку.

Следующий пример выводит автоматический цвет каждой серии по умолчанию:

using System;
using Aspose.Slides;
using Aspose.Slides.Charts;

const int firstSlideIndex = 0;

using var presentation = new Presentation();
var slide = presentation.Slides[firstSlideIndex];

var chart = slide.Shapes.AddChart(ChartType.ClusteredColumn, 20, 20, 500, 200);

var seriesCount = chart.ChartData.Series.Count;
for (var seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++)
{
    var series = chart.ChartData.Series[seriesIndex];
    var automaticColor = series.GetAutomaticSeriesColor();
    Console.WriteLine($"Series {seriesIndex}: {automaticColor.Name}");
}

Пример вывода для стиля диаграммы по умолчанию:

Series 0: ff4f81bd
Series 1: ffc0504d
Series 2: ff9bbb59

Точные цвета зависят от стиля и темы диаграммы.

Установить инвертированный цвет заливки для серии диаграммы

Для баровых, столбчатых и пузырьковых серий IChartSeries.InvertIfNegative позволяет отображать отрицательные значения другим цветом заливки. Установите обычную заливку серии сплошным цветом, включите инверсию и задайте цвет отрицательного значения через IChartSeries.InvertedSolidFillColor. Отрицательные числа в рабочей книге остаются неизменными; меняется только их отображаемый цвет.

Следующий пример заменяет данные диаграммы по умолчанию одной серией. Строка 0 листа содержит имя серии, столбец 0 — названия категорий, столбец 1 — значения:

using System.Drawing;
using Aspose.Slides;
using Aspose.Slides.Charts;
using Aspose.Slides.Export;

const int firstSlideIndex = 0;
const int worksheetIndex = 0;
const int headerRowIndex = 0;
const int categoryColumnIndex = 0;
const int firstSeriesColumnIndex = 1;
const int firstDataRowIndex = 1;

var categoryNames = new[] { "Category 1", "Category 2", "Category 3" };
var seriesValues = new[] { -20, 50, -30 };

using var presentation = new Presentation();
var slide = presentation.Slides[firstSlideIndex];

var chart = slide.Shapes.AddChart(ChartType.ClusteredColumn, 20, 20, 500, 200);
var chartData = chart.ChartData;
var workbook = chartData.ChartDataWorkbook;

chartData.Series.Clear();
chartData.Categories.Clear();

var seriesNameCell = workbook.GetCell(worksheetIndex, headerRowIndex, firstSeriesColumnIndex, "Series 1");
var series = chartData.Series.Add(seriesNameCell, chart.Type);

for (var categoryIndex = 0; categoryIndex < categoryNames.Length; categoryIndex++)
{
    var dataRowIndex = firstDataRowIndex + categoryIndex;
    var categoryName = categoryNames[categoryIndex];
    var seriesValue = seriesValues[categoryIndex];

    var categoryCell = workbook.GetCell(worksheetIndex, dataRowIndex, categoryColumnIndex, categoryName);
    chartData.Categories.Add(categoryCell);

    var valueCell = workbook.GetCell(worksheetIndex, dataRowIndex, firstSeriesColumnIndex, seriesValue);
    series.DataPoints.AddDataPointForBarSeries(valueCell);
}

var automaticSeriesColor = series.GetAutomaticSeriesColor();
series.Format.Fill.FillType = FillType.Solid;
series.Format.Fill.SolidFillColor.Color = automaticSeriesColor;
series.InvertIfNegative = true;
series.InvertedSolidFillColor.Color = Color.Red;

presentation.Save("inverted_solid_fill_color.pptx", SaveFormat.Pptx);

Результат:

The inverted solid fill color

Вы можете включить инверсию для отдельной точки через IChartDataPoint.InvertIfNegative. В следующем примере инверсия отключена для серии и включена только для выбранной точки. Точке также присвоено отрицательное значение, чтобы эффект был виден:

using System.Drawing;
using Aspose.Slides;
using Aspose.Slides.Charts;
using Aspose.Slides.Export;

const int firstSlideIndex = 0;
const int firstSeriesIndex = 0;
const int targetDataPointIndex = 2;
const int negativeValue = -30;

using var presentation = new Presentation();
var slide = presentation.Slides[firstSlideIndex];

var chart = slide.Shapes.AddChart(ChartType.ClusteredColumn, 20, 20, 500, 200);

var series = chart.ChartData.Series[firstSeriesIndex];
var automaticSeriesColor = series.GetAutomaticSeriesColor();
series.Format.Fill.FillType = FillType.Solid;
series.Format.Fill.SolidFillColor.Color = automaticSeriesColor;
series.InvertedSolidFillColor.Color = Color.Red;
series.InvertIfNegative = false;

var dataPoint = series.DataPoints[targetDataPointIndex];
dataPoint.YValue.AsCell.Value = negativeValue;
dataPoint.InvertIfNegative = true;

presentation.Save("data_point_invert_color_if_negative.pptx", SaveFormat.Pptx);

Очистить значение конкретной точки данных

Чтобы сделать одну точку пустой, не удаляя остальные, задайте её ячейке в рабочей книге значение null. Для столбчатой диаграммы построенное значение доступно через IChartDataPoint.YValue. Точка остаётся на той же позиции категории, но диаграмма рассматривает её значение как пустое согласно настройкам обработки пустых значений.

Следующий пример очищает только вторую точку в первой серии:

using Aspose.Slides;
using Aspose.Slides.Charts;
using Aspose.Slides.Export;

const int firstSlideIndex = 0;
const int firstSeriesIndex = 0;
const int targetDataPointIndex = 1;

using var presentation = new Presentation();
var slide = presentation.Slides[firstSlideIndex];

var chart = slide.Shapes.AddChart(ChartType.ClusteredColumn, 20, 20, 500, 200);

var series = chart.ChartData.Series[firstSeriesIndex];
var dataPoint = series.DataPoints[targetDataPointIndex];
dataPoint.YValue.AsCell.Value = null;

presentation.Save("clear_data_point_value.pptx", SaveFormat.Pptx);

Диаграммы разброса используют отдельные ячейки X и Y, а пузырьковые диаграммы — также ячейку размера. Очищайте только ту ячейку, которая представляет удаляемое значение. Не вызывайте IChartDataPointCollection.Clear, если хотите оставить остальные точки, поскольку этот метод удаляет все точки из коллекции.

Управление отображением пустых ячеек

Скрытые ячейки, содержащие значения, — отдельный случай от пустых ячеек. Чтобы включать или исключать данные из скрытых строк и столбцов листа, смотрите Include Data from Hidden Rows and Columns.

Пустая ячейка рабочей книги представляет отсутствующие данные; ячейка, содержащая 0, представляет известное числовое значение. Установите IChartDataCell.Value в null, чтобы сделать ячейку пустой. Числовой ноль остаётся нулём независимо от настройки обработки пустых ячеек.

Используйте IChart.DisplayBlanksAs для выбора способа отображения пустых ячеек. Эта настройка применяется ко всей диаграмме. Она меняет способ построения пустых точек, не заполняя пустую ячейку нулём или интерполированным значением.

Следующий автономный пример создаёт линейную диаграмму с одной серией, очищает значение для 3‑го дня и сохраняет диаграмму в каждом режиме. Входной файл не требуется. IChartDataWorkbook использует лист 0, столбец 0 — подписи категорий, столбец 1 — значения; строка 0 — имя серии. Итоговые данные: 10, 20, empty, 30, 40.

using Aspose.Slides;
using Aspose.Slides.Charts;
using Aspose.Slides.Export;

using var presentation = new Presentation();
var slide = presentation.Slides[0];

var chart = slide.Shapes.AddChart(ChartType.LineWithMarkers, 40, 40, 640, 400);
var chartData = chart.ChartData;
var workbook = chartData.ChartDataWorkbook;

chartData.Series.Clear();
chartData.Categories.Clear();

var seriesNameCell = workbook.GetCell(0, 0, 1, "Measurements");
var series = chartData.Series.Add(seriesNameCell, chart.Type);
var values = new[] { 10, 20, 25, 30, 40 };

for (var i = 0; i < values.Length; i++)
{
    var categoryCell = workbook.GetCell(0, i + 1, 0, $"Day {i + 1}");
    chartData.Categories.Add(categoryCell);
    var valueCell = workbook.GetCell(0, i + 1, 1, values[i]);
    series.DataPoints.AddDataPointForLineSeries(valueCell);
}

// Оставить 3-й день действительно пустым, при этом сохранить его категорию и точку данных.
workbook.GetCell(0, 3, 1).Value = null;

var modes = new[] { DisplayBlanksAsType.Gap, DisplayBlanksAsType.Zero, DisplayBlanksAsType.Span };
foreach (var mode in modes)
{
    chart.DisplayBlanksAs = mode;
    presentation.Save($"empty_cells_{mode}.pptx", SaveFormat.Pptx);
}

Каждый выходной файл сохраняет режим, выбранный перед сохранением: empty_cells_Gap.pptx, empty_cells_Zero.pptx и empty_cells_Span.pptx. Чтобы сохранить только одну версию, задайте нужный режим и сохраните презентацию один раз, вместо перебора режимов.

Сравнение ниже показывает одни и те же данные во всех трёх файлах. День 3 пуст в рабочей книге во всех случаях:

Line charts with identical data: Gap breaks the line at Day 3, Zero drops the line to zero, and Span connects Day 2 to Day 4.

Видимый эффект зависит от типа диаграммы. Линейная диаграмма позволяет легко сравнивать все три режима. Баровые и столбчатые диаграммы не имеют линии, соединяющей пропущенную категорию, поэтому Span не может создать показанный выше соединительный сегмент; пустой столбец и столбец нулевой высоты также могут выглядеть одинаково. Аналогично, диаграмма разброса только с маркерами не имеет соединяющей линии. Не ожидайте трех различных результатов для каждого типа диаграммы; проверьте вывод для используемого типа.

Установить ширину промежутка между сериями

Ширина промежутка — это пространство между соседними группами баров или столбцов, выраженное в процентах от ширины бара или столбца. Как и перекрытие, она относится к родительской группе серий, а не к отдельной серии. Установите IChartSeriesGroup.GapWidth один раз для группы. Большее значение создаёт больше пространства между кластерами; меньшее — делает их плотнее.

Следующий пример меняет ширину промежутка и сохраняет только окончательную презентацию:

using Aspose.Slides;
using Aspose.Slides.Charts;
using Aspose.Slides.Export;

const int firstSlideIndex = 0;
const int firstSeriesIndex = 0;
const int gapWidthPercent = 30;

using var presentation = new Presentation();
var slide = presentation.Slides[firstSlideIndex];

var chart = slide.Shapes.AddChart(ChartType.StackedColumn, 20, 20, 500, 200);

var series = chart.ChartData.Series[firstSeriesIndex];
series.ParentSeriesGroup.GapWidth = gapWidthPercent;

presentation.Save("gap_width_30.pptx", SaveFormat.Pptx);

Результат:

The gap width

FAQ

Какие типы диаграмм поддерживают серии данных?

Все типы диаграмм, представленные перечислением ChartType, используют данные диаграммы, но их серии не имеют одинаковой структуры значений или одинаковых параметров. Например, диаграммы категорий используют категории и значения, диаграммы разброса — значения X и Y, а пузырьковые диаграммы добавляют размеры пузырей. Используйте метод создания точек данных, соответствующий типу серии. Параметры, такие как перекрытие и ширина промежутка, применимы только к совместимым группам баров или столбцов.

Что такое группа серий диаграммы?

IChartSeriesGroup содержит совместимые серии, которые разделяют настройки группового построения. Комбинированная диаграмма может содержать более одной группы, поэтому изменение группы, полученной через одну серию, не обязательно меняет все серии в диаграмме.

Создаётся ли в новой диаграмме набор данных по умолчанию?

Да. По умолчанию IShapeCollection.AddChart создаёт образцы серий, категорий и значений. Вы можете отредактировать эти ячейки или очистить коллекции серий и категорий перед добавлением полностью пользовательского набора данных. Перегрузка метода также позволяет создать диаграмму без данных по умолчанию.

Как диаграммы связываются с ячейками рабочей книги?

Имена серий, подписи категорий и значения точек данных ссылаются на ячейки в IChartDataWorkbook. Изменение ячейки, на которую есть ссылка, обновляет соответствующий элемент диаграммы. При построении пользовательских данных сохраняйте согласованность строк категорий и строк значений серий, чтобы каждая точка отображалась под нужной категорией.

Как очистить одну точку, а не всю серию?

Установите соответствующую ячейку значения в null, чтобы точка сохранила позицию категории как пустую. Используйте IChartDataPointCollection.Clear только если хотите удалить все точки из этой серии. Если удаляете также категории, обновите все серии, чтобы их значения оставались согласованными с коллекцией категорий.

Как отображаются пустые точки?

Результат зависит от типа диаграммы и IChart.DisplayBlanksAs. Поддерживаемые диаграммы могут отображать пустоты как разрывы, нулевые значения или соединяя соседние точки. Выберите настройку, соответствующую смыслу отсутствующих данных в вашей презентации. См. раздел Control the Display of Empty Cells для полного примера и визуального сравнения.

Как форматируются отрицательные значения?

Для поддерживаемых баровых, столбчатых и пузырьковых серий включите IChartSeries.InvertIfNegative и задайте IChartSeries.InvertedSolidFillColor. Вы можете переопределить поведение для отдельной точки с помощью IChartDataPoint.InvertIfNegative. Эти свойства влияют только на форматирование, а не на хранимые числовые значения.

Какой формат имеет приоритет, если заданы и серия, и точка?

Явное форматирование отдельной точки имеет приоритет для этой точки. Остальные точки продолжают использовать явный формат серии или, если формат серии не определён, автоматический стиль и тему диаграммы. Групповые свойства, такие как перекрытие и ширина промежутка, управляют расположением и не переопределяют форматирование точек.

Есть ли ограничение на количество серий в диаграмме?

Aspose.Slides не накладывает отдельного фиксированного ограничения на количество серий. На практике ограничения файлов презентации, доступная память, время рендеринга и читаемость диаграммы определяют практический предел.

Что менять, если столбцы находятся слишком близко или слишком далеко друг от друга?

Установите IChartSeriesGroup.GapWidth в нужной родительской группе серий. Увеличьте значение, чтобы расширить пространство между кластерами, или уменьшите, чтобы собрать их ближе.