Управление данными серий диаграмм в презентациях на Android
Обзор
Диаграмма хранит построенные данные в рабочей книге данных диаграммы. IChartSeries представляет один набор связанных значений, а каждый IChartDataPoint в серии ссылается на одну или несколько ячеек рабочей книги. Объекты IChartCategory предоставляют метки или группирующие значения, общие для серий. Имя серии, категории и значения точек поэтому связаны с объектами IChartDataCell, а не только хранятся как отображаемый текст.
Для типичной диаграммы категорий рабочая книга по умолчанию использует строку 0 для имён серий, столбец 0 для имён категорий и остальные ячейки для значений серий. Индексы листа, строки и столбца, передаваемые в IChartDataWorkbook.getCell, начинаются с 0. Такой макет удобен при создании диаграммы с данными по умолчанию, но не следует полагаться, что каждая существующая диаграмма использует его. Для загруженной презентации проверьте ячейки, на которые ссылаются серии, категории и точки данных, прежде чем изменять значения в рабочей книге.
Настройки диаграммы имеют три разных уровня области действия:
- Настройки уровня серии, такие как IChartSeries.getFormat, задают оформление по умолчанию для всех точек в одной серии.
- Настройки точек данных, такие как IChartDataPoint.getFormat, переопределяют оформление серии для одной точки.
- Настройки группы применяются к совместимым сериям, принадлежащим одному IChartSeriesGroup. Обратитесь к группе через IChartSeries.getParentSeriesGroup, когда нужно задать такие параметры, как перекрытие или ширина промежутка.
Если явное заливание точки или серии не задано, стиль и тема диаграммы определяют автоматическое оформление. Когда присутствует как оформление серии, так и оформление точки, оформление точки имеет приоритет для этой точки.

Установить перекрытие серии диаграммы
IChartSeries.getOverlap сообщает, насколько столбцы или бары перекрываются в 2‑D‑диаграмме, в диапазоне от -100 до 100 процентов. Это только чтение проекции настройки в родительской группе серий. Используйте IChartSeriesGroup.setOverlap, чтобы обновить каждую совместимую серию в этой группе. Эта опция применяется к типам диаграмм, показывающим сгруппированные бары или столбцы; она не затрагивает несвязанные группы серий в комбинированной диаграмме.
Следующий пример задаёт перекрытие для группы, содержащей первую серию:
import com.aspose.slides.*;
final int firstSlideIndex = 0;
final int firstSeriesIndex = 0;
final byte overlapPercent = 30;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(firstSlideIndex);
// Новая диаграмма содержит примерные серии, категории и значения.
IChart chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 20, 20, 500, 200);
IChartSeries series = chart.getChartData().getSeries().get_Item(firstSeriesIndex);
series.getParentSeriesGroup().setOverlap(overlapPercent);
presentation.save("series_overlap.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Результат:

Изменить цвет заливки серии
Используйте IChartSeries.getFormat для задания заливки по умолчанию для всей серии. Если у точки уже задана явная заливка, её настройка IChartDataPoint.getFormat переопределяет заливку серии для этой точки.
Следующий пример применяет сплошную синюю заливку к первой серии:
import com.aspose.slides.*;
import android.graphics.Color;
final int firstSlideIndex = 0;
final int firstSeriesIndex = 0;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(firstSlideIndex);
IChart chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 20, 20, 500, 200);
IChartSeries series = chart.getChartData().getSeries().get_Item(firstSeriesIndex);
series.getFormat().getFill().setFillType(FillType.Solid);
series.getFormat().getFill().getSolidFillColor().setColor(Color.BLUE);
presentation.save("series_color.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Результат:

Изменить имя серии
Имя серии хранится в рабочей книге данных диаграммы и обычно отображается в легенде. В рабочей книге по умолчанию для кластерной столбчатой диаграммы ячейка B1 находится в строке 0, столбце 1 и содержит имя первой серии. Именованные константы в следующем примере делают эту структуру явной:
import com.aspose.slides.*;
final int firstSlideIndex = 0;
final int worksheetIndex = 0;
final int seriesNameRowIndex = 0;
final int firstSeriesColumnIndex = 1;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(firstSlideIndex);
IChart chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 20, 20, 500, 200);
IChartDataWorkbook workbook = chart.getChartData().getChartDataWorkbook();
IChartDataCell seriesNameCell = workbook.getCell(worksheetIndex, seriesNameRowIndex, firstSeriesColumnIndex);
seriesNameCell.setValue("Revenue");
presentation.save("series_name.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Вы также можете обновить ячейку, уже ссылку на которую имеет IChartSeries.getName. Этот подход избавляет от предположений о конкретных строках и столбцах в существующей диаграмме:
import com.aspose.slides.*;
final int firstSlideIndex = 0;
final int firstSeriesIndex = 0;
final int firstNameCellIndex = 0;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(firstSlideIndex);
IChart chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 20, 20, 500, 200);
IChartSeries series = chart.getChartData().getSeries().get_Item(firstSeriesIndex);
IChartDataCell seriesNameCell = series.getName().getAsCells().get_Item(firstNameCellIndex);
seriesNameCell.setValue("Revenue");
presentation.save("series_name.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Результат:

Создать серию с именем из нескольких ячеек
Составное имя серии полезно, когда название продукта и отчётный период хранятся в разных ячейках рабочей книги. Например, можно объединить Product A в B1 и 2026 в C1 в одно имя серии, оставив обе части связанными с их исходными ячейками.
Используйте IChartDataWorkbook.getCellCollection для получения диапазона имён, затем передайте эту коллекцию в IChartSeriesCollection.add. Параметр skipHiddenCells контролирует, включать ли скрытые ячейки: true — исключает, false — включает. В этом примере используется false, чтобы включить каждую ячейку в диапазоне имён.
Следующий пример создаёт презентацию с одной серией и двумя точками данных. Ячейки B1:C1 предоставляют только имя серии; A2:A3 — метки категорий, а B2:B3 — числовые значения.
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IChart chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 50, 50, 620, 180);
chart.getChartData().getSeries().clear();
chart.getChartData().getCategories().clear();
chart.setLegend(true);
IChartDataWorkbook workbook = chart.getChartData().getChartDataWorkbook();
workbook.clear(0);
// Эти две ячейки задают имя серии.
workbook.getCell(0, 0, 1, "Product A");
workbook.getCell(0, 0, 2, "2026");
IChartCellCollection nameCells = workbook.getCellCollection("Sheet1!$B$1:$C$1", false);
IChartSeries series = chart.getChartData().getSeries().add(nameCells, ChartType.ClusteredColumn);
// Отдельные ячейки задают категории и числовые точки данных.
IChartDataCell northCategory = workbook.getCell(0, 1, 0, "North");
IChartDataCell southCategory = workbook.getCell(0, 2, 0, "South");
chart.getChartData().getCategories().add(northCategory);
chart.getChartData().getCategories().add(southCategory);
IChartDataCell northValue = workbook.getCell(0, 1, 1, 120);
IChartDataCell southValue = workbook.getCell(0, 2, 1, 150);
series.getDataPoints().addDataPointForBarSeries(northValue);
series.getDataPoints().addDataPointForBarSeries(southValue);
presentation.save("composite_series_name.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Полученное имя серии — Product A 2026, с пробелом между значениями двух ячеек. Легенда отображает его как одну запись для обоих столбцов. Ниже изображён результат:

Получить автоматический цвет заливки серии
IChartSeries.getAutomaticSeriesColor возвращает цвет, вычисленный на основе индекса серии и стиля диаграммы, в виде Android ARGB‑целого. Это цвет, используемый, когда заливка серии не определена явно. Вызов метода лишь читает вычисленный цвет; он не задаёт новую заливку.
Следующий пример выводит целочисленное значение автоматического цвета для каждой серии по умолчанию:
import com.aspose.slides.*;
final int firstSlideIndex = 0;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(firstSlideIndex);
IChart chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 20, 20, 500, 200);
int seriesCount = chart.getChartData().getSeries().size();
for (int seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) {
IChartSeries series = chart.getChartData().getSeries().get_Item(seriesIndex);
int automaticColor = series.getAutomaticSeriesColor();
System.out.println("Series " + seriesIndex + ": " + automaticColor);
}
} finally {
presentation.dispose();
}
Точные целочисленные значения зависят от стиля и темы диаграммы.
Установить инвертированный цвет заливки для серии диаграммы
Для баров, столбцов и пузырьковых серий IChartSeries.setInvertIfNegative может отображать отрицательные значения другой заливкой. Установите обычную заливку серии сплошной, включите инверсию и задайте цвет отрицательного значения через IChartSeries.getInvertedSolidFillColor. Отрицательные числа остаются без изменений в рабочей книге; меняется лишь их цвет отображения.
Следующий пример заменяет данные диаграммы по умолчанию одной серией. Строка 0 листа содержит имя серии, столбец 0 — имена категорий, столбец 1 — значения:
import com.aspose.slides.*;
import android.graphics.Color;
final int firstSlideIndex = 0;
final int worksheetIndex = 0;
final int headerRowIndex = 0;
final int categoryColumnIndex = 0;
final int firstSeriesColumnIndex = 1;
final int firstDataRowIndex = 1;
String[] categoryNames = { "Category 1", "Category 2", "Category 3" };
int[] seriesValues = { -20, 50, -30 };
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(firstSlideIndex);
IChart chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 20, 20, 500, 200);
IChartData chartData = chart.getChartData();
IChartDataWorkbook workbook = chartData.getChartDataWorkbook();
chartData.getSeries().clear();
chartData.getCategories().clear();
IChartDataCell seriesNameCell = workbook.getCell(worksheetIndex, headerRowIndex, firstSeriesColumnIndex, "Series 1");
int chartType = chart.getType();
IChartSeries series = chartData.getSeries().add(seriesNameCell, chartType);
for (int categoryIndex = 0; categoryIndex < categoryNames.length; categoryIndex++) {
int dataRowIndex = firstDataRowIndex + categoryIndex;
String categoryName = categoryNames[categoryIndex];
int seriesValue = seriesValues[categoryIndex];
IChartDataCell categoryCell = workbook.getCell(worksheetIndex, dataRowIndex, categoryColumnIndex, categoryName);
chartData.getCategories().add(categoryCell);
IChartDataCell valueCell = workbook.getCell(worksheetIndex, dataRowIndex, firstSeriesColumnIndex, seriesValue);
series.getDataPoints().addDataPointForBarSeries(valueCell);
}
int automaticSeriesColor = series.getAutomaticSeriesColor();
series.getFormat().getFill().setFillType(FillType.Solid);
series.getFormat().getFill().getSolidFillColor().setColor(automaticSeriesColor);
series.setInvertIfNegative(true);
series.getInvertedSolidFillColor().setColor(Color.RED);
presentation.save("inverted_solid_fill_color.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Результат:

Можно включить инверсию для одной точки через IChartDataPoint.setInvertIfNegative. В следующем примере инверсия отключена для серии и включена только для выбранной точки. Точке также задаётся отрицательное значение, чтобы эффект был видим:
import com.aspose.slides.*;
import android.graphics.Color;
final int firstSlideIndex = 0;
final int firstSeriesIndex = 0;
final int targetDataPointIndex = 2;
final int negativeValue = -30;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(firstSlideIndex);
IChart chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 20, 20, 500, 200);
IChartSeries series = chart.getChartData().getSeries().get_Item(firstSeriesIndex);
int automaticSeriesColor = series.getAutomaticSeriesColor();
series.getFormat().getFill().setFillType(FillType.Solid);
series.getFormat().getFill().getSolidFillColor().setColor(automaticSeriesColor);
series.getInvertedSolidFillColor().setColor(Color.RED);
series.setInvertIfNegative(false);
IChartDataPoint dataPoint = series.getDataPoints().get_Item(targetDataPointIndex);
dataPoint.getValue().getAsCell().setValue(negativeValue);
dataPoint.setInvertIfNegative(true);
presentation.save("data_point_invert_color_if_negative.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Очистить конкретное значение точки данных
Чтобы сделать одну точку пустой, не удаляя остальные, задайте её ячейке в рабочей книге значение null. Для столбчатой диаграммы построенное значение доступно через IChartDataPoint.getValue. Точка остаётся на той же позиции категории, но диаграмма рассматривает её значение как пустое в соответствии с настройками обработки пустых значений.
Следующий пример очищает только вторую точку в первой серии:
import com.aspose.slides.*;
final int firstSlideIndex = 0;
final int firstSeriesIndex = 0;
final int targetDataPointIndex = 1;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(firstSlideIndex);
IChart chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 20, 20, 500, 200);
IChartSeries series = chart.getChartData().getSeries().get_Item(firstSeriesIndex);
IChartDataPoint dataPoint = series.getDataPoints().get_Item(targetDataPointIndex);
dataPoint.getValue().getAsCell().setValue(null);
presentation.save("clear_data_point_value.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Диаграммы разброса используют отдельные ячейки X и Y, а пузырьковые диаграммы также используют ячейку размера. Очищайте только ту ячейку, которая представляет значение, которое вы хотите удалить. Не вызывайте IChartDataPointCollection.clear, если хотите сохранить остальные точки, поскольку этот метод удаляет все точки из коллекции.
Управление отображением пустых ячеек
Скрытые ячейки, содержащие значения, — отдельный случай от пустых ячеек. Чтобы включать или исключать данные из скрытых строк и столбцов листа, см. Include Data from Hidden Rows and Columns.
Пустая ячейка рабочей книги представляет отсутствие данных; ячейка, содержащая 0, представляет известное числовое значение. Вызовите IChartDataCell.setValue с null, чтобы сделать ячейку пустой. Числовой ноль остаётся нулём независимо от настройки пустой ячейки.
Используйте IChart.setDisplayBlanksAs для выбора способа отображения пустых ячеек диаграммой. Эта настройка применяется ко всей диаграмме. Она изменяет способ построения пустот без заполнения пустой ячейки нулём или интерполированным значением.
Следующий автономный пример создаёт линейную диаграмму с одной серией, очищает значение для 3‑го дня и сохраняет диаграмму в каждом режиме. Входной файл не требуется. IChartDataWorkbook использует лист 0, столбец 0 для меток категорий и столбец 1 для значений; строка 0 содержит имя серии. Окончательные данные: 10, 20, empty, 30, 40.
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IChart chart = slide.getShapes().addChart(ChartType.LineWithMarkers, 40, 40, 640, 400);
IChartData chartData = chart.getChartData();
IChartDataWorkbook workbook = chartData.getChartDataWorkbook();
chartData.getSeries().clear();
chartData.getCategories().clear();
IChartDataCell seriesNameCell = workbook.getCell(0, 0, 1, "Measurements");
IChartSeries series = chartData.getSeries().add(seriesNameCell, chart.getType());
int[] values = { 10, 20, 25, 30, 40 };
for (int i = 0; i < values.length; i++) {
IChartDataCell categoryCell = workbook.getCell(0, i + 1, 0, "Day " + (i + 1));
chartData.getCategories().add(categoryCell);
IChartDataCell valueCell = workbook.getCell(0, i + 1, 1, values[i]);
series.getDataPoints().addDataPointForLineSeries(valueCell);
}
// Оставить 3‑й день действительно пустым, при этом сохранять его категорию и точку данных.
workbook.getCell(0, 3, 1).setValue(null);
int[] modes = { DisplayBlanksAsType.Gap, DisplayBlanksAsType.Zero, DisplayBlanksAsType.Span };
String[] modeNames = { "Gap", "Zero", "Span" };
for (int i = 0; i < modes.length; i++) {
chart.setDisplayBlanksAs(modes[i]);
presentation.save("empty_cells_" + modeNames[i] + ".pptx", SaveFormat.Pptx);
}
} finally {
presentation.dispose();
}
Каждый выходной файл сохраняет режим, выбранный перед сохранением: empty_cells_Gap.pptx, empty_cells_Zero.pptx и empty_cells_Span.pptx. Чтобы сохранить только одну версию, задайте нужный режим и сохраните презентацию один раз, вместо перебора режимов.
Сравнение ниже показывает одинаковые данные во всех трёх файлах. День 3 пуст в рабочей книге во всех случаях:

Видимый эффект зависит от типа диаграммы. Линейная диаграмма позволяет легко сравнивать все три режима. Бар‑ и столбчатые диаграммы не имеют линии, соединяющей пропущенную категорию, поэтому Span не может создать соединительный сегмент, показанный выше; отсутствующий столбец и столбец нулевой высоты могут выглядеть одинаково. Аналогично, диаграмма разброса только с маркерами не имеет соединительной линии. Не ожидайте три разных результата для каждого типа диаграммы; проверьте вывод для используемого типа.
Установить ширину промежутка между сериями
Ширина промежутка — это пространство между соседними кластерами баров или столбцов, выраженное в процентах от ширины бара или столбца. Как и перекрытие, она относится к родительской группе серий, а не к отдельной серии. Вызовите IChartSeriesGroup.setGapWidth один раз для группы. Большее значение создаёт больше пространства между кластерами; меньшее значение делает их плотнее.
Следующий пример меняет ширину промежутка и сохраняет только финальную презентацию:
import com.aspose.slides.*;
final int firstSlideIndex = 0;
final int firstSeriesIndex = 0;
final int gapWidthPercent = 30;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(firstSlideIndex);
IChart chart = slide.getShapes().addChart(ChartType.StackedColumn, 20, 20, 500, 200);
IChartSeries series = chart.getChartData().getSeries().get_Item(firstSeriesIndex);
series.getParentSeriesGroup().setGapWidth(gapWidthPercent);
presentation.save("gap_width_30.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Результат:

FAQ
Какие типы диаграмм поддерживают серии данных?
Все типы диаграмм, представленные перечислением ChartType, используют данные диаграммы, но их серии не имеют одинаковой структуры значений или настроек. Например, категориальные диаграммы используют категории и значения, диаграммы разброса — X и Y, а пузырьковые диаграммы добавляют размеры пузырей. Используйте метод создания точек данных, соответствующий типу серии. Параметры, такие как перекрытие и ширина промежутка, применимы только к совместимым группам баров или столбцов.
Что такое группа серий диаграммы?
IChartSeriesGroup содержит совместимые серии, которые разделяют настройки построения уровня группы. Комбинированная диаграмма может содержать более одной группы, поэтому изменение группы, достигнутой через одну серию, не обязательно меняет все серии в диаграмме.
Создаёт ли вновь созданная диаграмма данные по умолчанию?
Да. По умолчанию IShapeCollection.addChart создаёт примерные серии, категории и значения. Вы можете отредактировать эти ячейки или очистить коллекции серий и категорий перед добавлением полностью пользовательского набора данных. Существует перегрузка, позволяющая создать диаграмму без данных по умолчанию.
Как объекты диаграммы связаны с ячейками рабочей книги?
Имена серий, метки категорий и значения точек данных ссылаются на ячейки в IChartDataWorkbook. Изменение ссылки ячейки обновляет соответствующий элемент диаграммы. При построении пользовательских данных сохраняйте выравнивание строк категорий и строк значений серий, чтобы каждая точка строилась под нужной категорией.
Как очистить одну точку, а не всю серию?
Установите соответствующую ячейку значения в null, чтобы точка оставалась в позиции категории как пустая точка. Используйте IChartDataPointCollection.clear только когда нужно удалить все точки из серии. Если вы также удаляете категории, обновите каждую серию, чтобы их значения оставались согласованными с коллекцией категорий.
Как отображаются пустые точки?
Результат зависит от типа диаграммы и настройки, заданной через IChart.setDisplayBlanksAs. Поддерживаемые диаграммы могут показывать пустоты как разрывы, как нулевые значения или соединяя соседние точки. Выберите настройку, соответствующую смыслу отсутствующих данных в вашей презентации. См. Control the Display of Empty Cells для полного примера и визуального сравнения.
Как форматируются отрицательные значения?
Для поддерживаемых баров, столбцов и пузырьковых серий вызовите IChartSeries.setInvertIfNegative и задайте цвет, возвращаемый IChartSeries.getInvertedSolidFillColor. Для отдельной точки поведение можно переопределить с помощью IChartDataPoint.setInvertIfNegative. Эти методы влияют только на оформление, а не на сохранённые числовые значения.
Какой формат имеет приоритет, когда и серия, и точка отформатированы?
Явное форматирование точки имеет приоритет для этой точки. Другие точки продолжают использовать явный формат серии или, при отсутствии формата серии, автоматический стиль и тему диаграммы. Настройки группы, такие как перекрытие и ширина промежутка, управляют расположением и не являются переопределяющими форматирование точек.
Есть ли ограничение на количество серий в диаграмме?
Aspose.Slides не накладывает отдельного фиксированного ограничения на количество серий. На практике ограничения задаются размером файла презентации, доступной памятью, временем рендеринга и читаемостью диаграммы.
Что менять, если столбцы слишком близко или слишком далеко друг от друга?
Вызовите IChartSeriesGroup.setGapWidth для соответствующей родительской группы серий. Увеличьте значение, чтобы расширить пространство между кластерами, или уменьшите его, чтобы сблизить кластеры.