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

Установка перекрытия серий диаграммы
IChartSeries.getOverlap сообщает, насколько столбцы или полосы перекрываются в 2D‑диаграмме, от -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();
}
Результат:

Получение автоматического цвета заливки серии
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 если хотите сохранить остальные точки, потому что этот метод удаляет все точки из коллекции.
Управление отображением пустых ячеек
Пустая ячейка рабочей книги представляет отсутствие данных; ячейка, содержащая 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);
}
// Оставить третий день действительно пустым, сохранив его категорию и точку данных.
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. Поддерживаемые диаграммы могут отображать пустоты как разрывы, как нулевые значения или соединяя соседние точки. Выберите настройку, соответствующую смыслу отсутствующих данных в вашей презентации. См. раздел Управление отображением пустых ячеек для полного примера и визуального сравнения.
Как форматируются отрицательные значения?
Для поддерживаемых столбцов, полос и пузырьков вызовите IChartSeries.setInvertIfNegative и задайте цвет, возвращаемый IChartSeries.getInvertedSolidFillColor. Поведение отдельной точки можно переопределить с помощью IChartDataPoint.setInvertIfNegative. Эти методы влияют на форматирование, а не на сохранённые числовые значения.
Какой формат выигрывает, если и серия, и точка имеют формат?
Явное форматирование отдельной точки имеет приоритет для этой точки. Остальные точки продолжают использовать явный формат серии или, если формат серии не определён, автоматический стиль и тему диаграммы. Настройки группы, такие как перекрытие и ширина промежутка, управляют расположением и не являются переопределениями формата уровня точки.
Есть ли ограничение на количество серий в диаграмме?
Aspose.Slides не накладывает отдельного фиксированного ограничения на количество серий. На практике ограничения файлов презентации, доступная память, время рендеринга и читаемость диаграммы определяют практический предел.
Что менять, если столбцы слишком близко друг к другу или слишком далеко?
Вызовите IChartSeriesGroup.setGapWidth для соответствующей родительской группы серий. Увеличьте значение, чтобы расширить промежуток между кластерами, или уменьшите его, чтобы собрать кластеры ближе.