Управление рабочими книгами диаграмм в презентациях на Android
Обзор
В этой статье объясняется, как работать с рабочими книгами диаграмм в Aspose.Slides. Показано, как читать и записывать данные диаграмм через потоки рабочей книги, использовать ячейки рабочей книги в качестве меток данных диаграммы, получать доступ к коллекциям листов и указывать тип источника данных для значений диаграммы.
Также рассматривается работа с внешними рабочими книгами в качестве источников данных диаграмм. Примеры демонстрируют, как создать и привязать внешнюю рабочую книгу, получить путь внешней рабочей книги, связанной с диаграммой, и редактировать данные диаграммы, когда рабочая книга доступна.
Для ячеек рабочей книги, представляющих отсутствующие данные, см. Управление отображением пустых ячеек — различия между пустой ячейкой и нулём, а также сравнение отображения в линейной диаграмме.
Включать данные из скрытых строк и столбцов
Используйте IChart.setPlotVisibleCellsOnly — чтобы управлять тем, будет ли диаграмма строить график по данным скрытых строк и столбцов листа. Установите true, чтобы строить график только по видимым ячейкам, или false, чтобы включать и видимые, и скрытые ячейки. Эта настройка управляет построением диаграммы; она не скрывает и не отображает строки или столбцы листа.
Пример презентации содержит столбчатую диаграмму как первую форму на первом слайде. Встроенный лист Sheet1 имеет диапазон источника A1:C4. Строка 3 и столбец C скрыты, но их ячейки всё равно содержат значения.
| Строка листа | A: Месяц | B: Розничные продажи | C: Оптовые продажи (скрытый столбец) |
|---|---|---|---|
| 2 | Январь | 10 | 30 |
| 3 (скрытая строка) | Февраль | 40 | 60 |
| 4 | Март | 20 | 50 |
Получайте доступ к ячейкам‑источникам через IChartData.getChartDataWorkbook и проверяйте их статус скрытости с помощью IChartDataCell.isHidden. Этот метод сообщает о статусе скрытости без изменения его. В этом примере B2 видима, B3 принадлежит скрытой строке, а C2 — скрытому столбцу; пример выводит false, true и true соответственно.
Для этого примера обновите данные диаграммы после изменения настройки построения: сохраните встроенную рабочую книгу с помощью readWorkbookStream и загрузите её вновь с помощью writeWorkbookStream. При включении всех ячеек также используйте setRange — чтобы восстановить полный диапазон, включая скрытую категорию «Февраль». Простая смена флага недостаточна для обновления кэшированных данных и меток категорий в этом примере.
import com.aspose.slides.*;
Presentation presentation = new Presentation("hidden-source-data.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
int shapeCount = slide.getShapes().size();
if (shapeCount > 0 && slide.getShapes().get_Item(0) instanceof IChart) {
IChart chart = (IChart) slide.getShapes().get_Item(0);
IChartDataWorkbook workbook = chart.getChartData().getChartDataWorkbook();
System.out.println("B2 hidden: " + workbook.getCell(0, "B2").isHidden());
System.out.println("B3 hidden: " + workbook.getCell(0, "B3").isHidden());
System.out.println("C2 hidden: " + workbook.getCell(0, "C2").isHidden());
byte[] workbookData = chart.getChartData().readWorkbookStream();
for (boolean visibleOnly : new boolean[] { true, false }) {
chart.setPlotVisibleCellsOnly(visibleOnly);
// Обновить данные диаграммы из встроенной рабочей книги.
chart.getChartData().writeWorkbookStream(workbookData);
if (!visibleOnly) {
// Восстановить полный исходный диапазон, включая скрытые категории.
chart.getChartData().setRange("Sheet1!$A$1:$C$4");
}
presentation.save("hidden_cells_" + visibleOnly + ".pptx", SaveFormat.Pptx);
}
} else {
System.out.println("The first shape is not a chart.");
}
} finally {
presentation.dispose();
}
Пример сохраняет две версии презентации: одну только с видимыми значениями розничных продаж (10 и 20), а другую со всеми шестью значениями. Изображения ниже иллюстрируют два режима построения. Строка 3 и столбец C остаются скрытыми в обеих встроенных рабочих книгах.
Только видимые ячейки (true) |
Все ячейки (false) |
|---|---|
![]() |
![]() |
Скрытая ячейка, содержащая значение, отлична от пустой ячейки. IChart.setDisplayBlanksAs — управляет тем, как отображаются отсутствующие значения; он не включает и не исключает скрытые исходные данные. См. Управление отображением пустых ячеек для примера.
Получить диапазон данных диаграммы
Прежде чем обновлять данные рабочей книги в существующей презентации, проверьте диапазоны источников, чтобы определить, какие ячейки листа использует каждая диаграмма. Метод IChartData.getRange возвращает текущий диапазон данных в виде формулы, квалифицированной листом, например Sheet1!$A$1:$D$5. Здесь Sheet1 — имя листа, ! разделяет его от диапазона ячеек, а $A$1:$D$5 определяет ячейки от A1 до D5 включительно. Доллары указывают на абсолютные ссылки на строки и столбцы.
Метод читает текущий диапазон без изменения диаграммы или её рабочей книги. Если диаграмма не использует рабочую книгу в качестве источника данных, генерируется InvalidOperationException. Подробности см. в Справочнике API ChartData.
В этом примере открывается презентация и проверяются формы на каждом слайде на предмет диаграмм. Выводятся имя каждой диаграммы и её исходный диапазон. Если диаграмма не использует рабочую книгу, выводится сообщение и переходим к следующей диаграмме.
import com.aspose.slides.*;
import com.aspose.slides.exceptions.InvalidOperationException;
Presentation presentation = new Presentation("presentation.pptx");
try {
for (ISlide slide : presentation.getSlides()) {
for (IShape shape : slide.getShapes()) {
if (shape instanceof IChart) {
IChart chart = (IChart) shape;
try {
String range = chart.getChartData().getRange();
System.out.println(chart.getName() + ": " + range);
} catch (InvalidOperationException exception) {
System.out.println(chart.getName() + ": The chart does not use a workbook as its data source.");
}
}
}
}
} finally {
presentation.dispose();
}
Чтение и запись данных диаграммы из рабочей книги
Aspose.Slides for Android via Java предоставляет методы readWorkbookStream и writeWorkbookStream, позволяющие читать и записывать рабочие книги данных диаграмм (содержащие данные, отредактированные с помощью Aspose.Cells). Примечание — данные диаграммы должны быть организованы аналогичным образом или иметь структуру, похожую на исходную.
В этом примере используется презентация с диаграммой как первой формой на первом слайде. Встроенная рабочая книга считывается в массив байтов, существующие серии и категории очищаются, после чего та же рабочая книга записывается обратно. Изменения остаются в памяти; пример не сохраняет презентацию.
import com.aspose.slides.*;
Presentation presentation = new Presentation("chart.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
int shapeCount = slide.getShapes().size();
if (shapeCount > 0 && slide.getShapes().get_Item(0) instanceof IChart) {
IChart chart = (IChart) slide.getShapes().get_Item(0);
IChartData chartData = chart.getChartData();
byte[] workbookData = chartData.readWorkbookStream();
chartData.getSeries().clear();
chartData.getCategories().clear();
chartData.writeWorkbookStream(workbookData);
} else {
System.out.println("The first shape is not a chart.");
}
} finally {
presentation.dispose();
}
Проверка макета диаграммы после изменения рабочей книги
Когда вы заменяете встроенную рабочую книгу изменённой, диаграмма сохраняет исходные коллекции серий и категорий. Это несоответствие может вызвать ошибку в IChart.validateChartLayout — исключение «индекс вне диапазона». Очистите существующие серии и категории перед записью обновлённой рабочей книги обратно в диаграмму. Пример использует диаграмму, являющуюся первой формой на первом слайде. Комментарий отмечает место, где может происходить редактирование рабочей книги; исполняемый пример записывает оригинальную книгу обратно и проверяет макет в памяти.
import com.aspose.slides.*;
Presentation presentation = new Presentation("chart.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
int shapeCount = slide.getShapes().size();
if (shapeCount > 0 && slide.getShapes().get_Item(0) instanceof IChart) {
IChart chart = (IChart) slide.getShapes().get_Item(0);
IChartData chartData = chart.getChartData();
byte[] workbookData = chartData.readWorkbookStream();
// Измените байты рабочей книги здесь, например, с помощью Aspose.Cells.
chartData.getSeries().clear();
chartData.getCategories().clear();
chartData.writeWorkbookStream(workbookData);
chart.validateChartLayout();
} else {
System.out.println("The first shape is not a chart.");
}
} finally {
presentation.dispose();
}
Очистка коллекций удаляет устаревшие ссылки перед записью рабочей книги. Перед использованием диаграммы перестройте необходимые отображения серий и категорий для обновлённой книги.
Установить ячейку рабочей книги в качестве метки данных диаграммы
Можно использовать текст из ячеек рабочей книги в качестве меток данных диаграммы.
В этом примере к первому слайду существующей презентации добавляется пузырьковая диаграмма с данными по умолчанию. Используются ячейки A10:A12 листа 0 для первых трёх меток первой серии, включаются метки из ячеек, и презентация сохраняется.
import com.aspose.slides.*;
Presentation presentation = new Presentation("chart2.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
IChart chart = slide.getShapes().addChart(ChartType.Bubble, 50, 50, 600, 400, true);
IChartSeries series = chart.getChartData().getSeries().get_Item(0);
IChartDataWorkbook workbook = chart.getChartData().getChartDataWorkbook();
series.getLabels().getDefaultDataLabelFormat().setShowLabelValueFromCell(true);
series.getLabels().get_Item(0).setValueFromCell(workbook.getCell(0, "A10", "Label 0 cell value"));
series.getLabels().get_Item(1).setValueFromCell(workbook.getCell(0, "A11", "Label 1 cell value"));
series.getLabels().get_Item(2).setValueFromCell(workbook.getCell(0, "A12", "Label 2 cell value"));
presentation.save("resultchart.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Управление листами
Метод IChartDataWorkbook.getWorksheets предоставляет доступ к листам в рабочей книге диаграммы. В примере создаётся круговая диаграмма с данными по умолчанию и выводятся имена всех листов в консоль.
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IChart chart = slide.getShapes().addChart(ChartType.Pie, 50, 50, 400, 500);
IChartDataWorkbook workbook = chart.getChartData().getChartDataWorkbook();
for (int i = 0; i < workbook.getWorksheets().size(); i++) {
System.out.println(workbook.getWorksheets().get_Item(i).getName());
}
} finally {
presentation.dispose();
}
Указание типа источника данных
В примере создаётся 3D‑столбчатая диаграмма с данными по умолчанию и задаются два имени серий, использующие разные источники данных. Первое имя задаётся строковым литералом; второе — ячейкой C1 листа 0. Перечисление DataSourceType выбирает источник для каждого имени. Пример сохраняет презентацию с обновлёнными именами серий.
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IChart chart = slide.getShapes().addChart(ChartType.Column3D, 50, 50, 600, 400, true);
IStringChartValue literalName = chart.getChartData().getSeries().get_Item(0).getName();
literalName.setDataSourceType(DataSourceType.StringLiterals);
literalName.setData("LiteralString");
IStringChartValue cellName = chart.getChartData().getSeries().get_Item(1).getName();
IChartDataCell nameCell = chart.getChartData().getChartDataWorkbook().getCell(0, "C1", "NewCell");
cellName.setDataSourceType(DataSourceType.Worksheet);
cellName.setData(nameCell);
presentation.save("pres.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Обнаружение неподдерживаемых форматов встроенных рабочих книг
Aspose.Slides не поддерживает формат двоичной рабочей книги Excel (.xlsb), который может быть встроен в некоторые диаграммы. Вы можете использовать метод getEmbeddedWorkbookType на IChartData совместно с перечислением WorkbookType для обнаружения неподдерживаемых форматов и пропуска таких диаграмм. Пример проверяет формы на первом слайде существующей презентации, пропускает не‑диаграммные формы и выводит диагностическое сообщение для каждой диаграммы со встроенной книгой .xlsb.
import com.aspose.slides.*;
Presentation presentation = new Presentation("sample.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
for (IShape shape : slide.getShapes()) {
if (!(shape instanceof IChart)) {
continue;
}
IChart chart = (IChart) shape;
IChartData chartData = chart.getChartData();
boolean isInternalWorkbook = chartData.getDataSourceType() == ChartDataSourceType.InternalWorkbook;
boolean isBinaryMacro = chartData.getEmbeddedWorkbookType() == WorkbookType.WorkbookBinaryMacro;
if (isInternalWorkbook && isBinaryMacro) {
System.out.println("Skipping a chart with an unsupported .xlsb workbook.");
continue;
}
// Читать или изменять поддерживаемые данные рабочей книги диаграммы здесь.
}
} finally {
presentation.dispose();
}
Внешняя рабочая книга
Aspose.Slides поддерживает использование внешних рабочих книг в качестве источника данных для диаграмм.
Создание внешней рабочей книги
Используйте readWorkbookStream и setExternalWorkbook — чтобы экспортировать встроенную рабочую книгу диаграммы в файл и привязать диаграмму к этой внешней книге.
В примере создаётся круговая диаграмма с данными по умолчанию и экспортируется её рабочая книга. Запись в файл завершается до назначения внешней рабочей книги в качестве источника данных диаграммы, после чего сохраняется связанная презентация.
import com.aspose.slides.*;
import java.io.IOException;
import java.io.File;
import java.io.FileOutputStream;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IChart chart = slide.getShapes().addChart(ChartType.Pie, 50, 50, 400, 600);
File workbookFile = new File("externalWorkbook1.xlsx").getAbsoluteFile();
byte[] workbookData = chart.getChartData().readWorkbookStream();
try {
try (FileOutputStream workbookStream = new FileOutputStream(workbookFile)) {
workbookStream.write(workbookData);
}
chart.getChartData().setExternalWorkbook(workbookFile.getAbsolutePath());
presentation.save("externalWorkbook.pptx", SaveFormat.Pptx);
} catch (IOException exception) {
System.out.println("Could not write the external workbook: " + exception.getMessage());
}
} finally {
presentation.dispose();
}
Установка внешней рабочей книги
С помощью метода setExternalWorkbook можно привязать внешнюю рабочую книгу к диаграмме в качестве её источника данных. Этот метод также может использоваться для обновления пути к внешней книге (если она была перемещена).
Хотя редактировать данные в рабочих книгах, хранящихся в удалённых ресурсах, нельзя, такие книги всё равно могут использоваться как внешний источник данных. Если указан относительный путь к внешней книге, он автоматически преобразуется в полный путь.
В примере используется внешняя рабочая книга, лист Sheet1 которой содержит имя серии в B1, имена категорий в A2:A4 и числовые значения в B2:B4. Пример создаёт круговую диаграмму, связывает книгу и использует setRange — чтобы сопоставить A1:B4 одной серии и трем категориям. Презентация сохраняется с привязанной диаграммой.
import com.aspose.slides.*;
import java.io.File;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IChart chart = slide.getShapes().addChart(ChartType.Pie, 50, 50, 400, 600, true);
IChartData chartData = chart.getChartData();
File workbookFile = new File("externalWorkbook.xlsx");
String workbookPath = workbookFile.getAbsolutePath();
chartData.setExternalWorkbook(workbookPath);
chartData.setRange("Sheet1!$A$1:$B$4");
presentation.save("Presentation_with_externalWorkbook.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Параметр updateChartData метода setExternalWorkbook управляет загрузкой рабочей книги.
- При
updateChartData=falseобновляется только путь к книге. Данные диаграммы не загружаются и не обновляются из целевой книги, поэтому книга может быть недоступна. - При
updateChartData=trueданные диаграммы обновляются из целевой книги.
В следующем примере задаётся фиктивный URL с updateChartData = false. Диаграмма сохраняет свои данные по умолчанию, а презентация сохраняется без загрузки недоступной книги.
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IChart chart = slide.getShapes().addChart(ChartType.Pie, 50, 50, 400, 600, true);
chart.getChartData().setExternalWorkbook("https://example.com/unavailable-workbook.xlsx", false);
presentation.save("SetExternalWorkbookWithUpdateChartData.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Получить путь к внешнему источнику данных книги диаграммы
Чтобы определить, к какой книге привязана диаграмма, проверьте, использует ли диаграмма внешний источник данных, и получите путь к её рабочей книге.
Пример проверяет первую форму на первом слайде презентации с привязанной внешней книгой. Если это диаграмма, связанная с внешней книгой, пример выводит getExternalWorkbookPath в консоль, затем сохраняет копию презентации.
import com.aspose.slides.*;
Presentation presentation = new Presentation("externalWorkbook.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
if (slide.getShapes().size() > 0 && slide.getShapes().get_Item(0) instanceof IChart) {
IChart chart = (IChart) slide.getShapes().get_Item(0);
IChartData chartData = chart.getChartData();
if (chartData.getDataSourceType() == ChartDataSourceType.ExternalWorkbook) {
System.out.println(chartData.getExternalWorkbookPath());
} else {
System.out.println("The chart does not use an external workbook.");
}
} else {
System.out.println("The first shape is not a chart.");
}
presentation.save("Result.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Редактирование данных диаграммы
Можно редактировать данные во внешних рабочих книгах так же, как и во внутренних. Если внешняя книга не может быть загружена, генерируется исключение.
В примере используется диаграмма, первая форма на первом слайде, привязанная к доступной внешней книге. Значение первой точки первой серии задаётся равным 100, презентация сохраняется. Редактирование значений ячеек может обновлять связанный внешний файл XLSX, поэтому используйте копию, если нужно сохранить оригинальную книгу.
import com.aspose.slides.*;
Presentation presentation = new Presentation("presentation.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
int shapeCount = slide.getShapes().size();
if (shapeCount > 0 && slide.getShapes().get_Item(0) instanceof IChart) {
IChart chart = (IChart) slide.getShapes().get_Item(0);
IChartSeriesCollection series = chart.getChartData().getSeries();
if (series.size() > 0 && series.get_Item(0).getDataPoints().size() > 0) {
IChartDataCell valueCell = series.get_Item(0).getDataPoints().get_Item(0).getValue().getAsCell();
if (valueCell != null) {
valueCell.setValue(100);
presentation.save("presentation_out.pptx", SaveFormat.Pptx);
} else {
System.out.println("The first data point is not linked to a workbook cell.");
}
} else {
System.out.println("The chart has no data points to edit.");
}
} else {
System.out.println("The first shape is not a chart.");
}
} finally {
presentation.dispose();
}
Восстановление рабочей книги из кэша диаграммы
Если диаграмма использует внешнюю книгу, которая отсутствует или недоступна, Aspose.Slides может восстановить рабочую книгу диаграммы из кэшированных данных презентации. Создайте LoadOptions, вызовите LoadOptions.setSpreadsheetOptions, и задайте ISpreadsheetOptions.setRecoverWorkbookFromChartCache = true перед открытием презентации.
Следующий пример на Java восстанавливает данные рабочей книги для диаграммы, первой формы на первом слайде, ссылающейся на недоступную внешнюю книгу. Доступ к восстановленным данным выполняется через IChart.getChartData и IChartData.getChartDataWorkbook:
import com.aspose.slides.*;
SpreadsheetOptions spreadsheetOptions = new SpreadsheetOptions();
spreadsheetOptions.setRecoverWorkbookFromChartCache(true);
LoadOptions loadOptions = new LoadOptions();
loadOptions.setSpreadsheetOptions(spreadsheetOptions);
Presentation presentation = new Presentation("presentation.pptx", loadOptions);
try {
ISlide slide = presentation.getSlides().get_Item(0);
int shapeCount = slide.getShapes().size();
if (shapeCount > 0 && slide.getShapes().get_Item(0) instanceof IChart) {
IChart chart = (IChart) slide.getShapes().get_Item(0);
IChartDataWorkbook recoveredWorkbook = chart.getChartData().getChartDataWorkbook();
// Читать или изменять восстановленные данные рабочей книги здесь.
} else {
System.out.println("The first shape is not a chart.");
}
} finally {
presentation.dispose();
}
Если внешняя книга недоступна и восстановление отключено, Aspose.Slides генерирует исключение. Включайте восстановление только тогда, когда использование кэшированных данных диаграммы является приемлемым резервным вариантом, поскольку кэш может не содержать изменений, внесённых во внешнюю книгу после последнего обновления презентации.
FAQ
Могу ли я определить, привязана ли конкретная диаграмма к внешней или встроенной рабочей книге?
Да. Диаграмма имеет тип источника данных и путь к внешней рабочей книге; если источник — внешняя книга, можно прочитать полный путь, чтобы убедиться, что используется внешний файл.
Поддерживаются ли относительные пути к внешним рабочим книгам и как они хранятся?
Да. Если указать относительный путь, он автоматически преобразуется в абсолютный. Презентация сохраняет абсолютный путь в файле PPTX, поэтому перемещение книги может потребовать обновления ссылки.
Можно ли использовать книги, расположенные на сетевых ресурсах/общих папках?
Да, такие книги могут быть использованы как внешний источник данных. Однако прямое редактирование удалённых книг из Aspose.Slides не поддерживается — их можно только использовать в качестве источника.
Перезаписывает ли Aspose.Slides внешний XLSX при сохранении презентации?
Презентация сохраняет ссылку на внешний файл. Редактирование данных диаграммы, привязанных к ячейкам, может также обновлять связанный локальный файл XLSX. Используйте копию книги, если оригинал должен оставаться неизменным.
Что делать, если внешний файл защищён паролем?
Aspose.Slides не принимает пароль при привязке. Обычно защищённость снимают заранее или готовят расшифрованную копию (например, с помощью Aspose.Cells) и привязывают к ней.
Могут ли несколько диаграмм ссылаться на одну и ту же внешнюю рабочую книгу?
Да. Каждая диаграмма хранит свою собственную ссылку. Если все они указывают на один и тот же файл, изменение файла будет отражено в каждой диаграмме при следующей загрузке данных.

