Управление рабочими книгами диаграмм в презентациях на .NET

Обзор

Эта статья объясняет, как работать с рабочими книгами диаграмм в Aspose.Slides. Она показывает, как считывать и записывать данные диаграмм через потоки рабочей книги, использовать ячейки рабочей книги в качестве подписей данных диаграммы, получать доступ к коллекциям листов и указывать тип источника данных для значений диаграммы.

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

Для ячеек рабочей книги, представляющих отсутствующие данные, смотрите Control the Display of Empty Cells для различий между пустой ячейкой и нулём, а также сравнение режимов отображения в линейных диаграммах.

Чтение и запись данных диаграммы из рабочей книги

Aspose.Slides предоставляет методы ReadWorkbookStream и WriteWorkbookStream, позволяющие считывать и записывать рабочие книги данных диаграмм (содержащие данные диаграмм, отредактированные с помощью Aspose.Cells). Note что данные диаграммы должны быть организованы одинаково или иметь структуру, похожую на исходную.

Этот код C# демонстрирует пример операции:

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

using (Presentation pres = new Presentation("chart.pptx"))
{
    Chart chart = (Chart) pres.Slides[0].Shapes[0];
    IChartData data = chart.ChartData;

    MemoryStream stream = data.ReadWorkbookStream();

    data.Series.Clear();
    data.Categories.Clear();

    stream.Position = 0;
    data.WriteWorkbookStream(stream);
}

Проверка расположения диаграммы после изменения рабочей книги

Когда вы заменяете встроенную рабочую книгу изменённой, диаграмма сохраняет свои исходные коллекции серий и категорий. Это несоответствие может привести к ошибке IChart.ValidateChartLayout с «index-out-of-range». Очистите существующие серии и категории перед записью обновлённой рабочей книги обратно в диаграмму.

// После изменения потока рабочей книги (например, используя Aspose.Cells)
using var updatedWorkbook = chartData.ReadWorkbookStream();

// Очистить существующие ссылки на данные.
chartData.Series.Clear();
chartData.Categories.Clear();

updatedWorkbook.Position = 0;
chartData.WriteWorkbookStream(updatedWorkbook);

chart.ValidateChartLayout();

Очистка коллекций гарантирует согласованность структуры данных диаграммы с новой рабочей книгой, позволяя ValidateChartLayout завершиться без ошибок.

Установка ячейки рабочей книги в качестве подписи данных диаграммы

  1. Создайте экземпляр класса Presentation .
  2. Получите ссылку на слайд по его индексу.
  3. Добавьте пузырьковую диаграмму с некоторыми данными.
  4. Получите доступ к сериям диаграммы.
  5. Установите ячейку рабочей книги в качестве подписи данных.
  6. Сохраните презентацию.

Этот код C# показывает, как установить ячейку рабочей книги в качестве подписи данных диаграммы:

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

string lbl0 = "Label 0 cell value";
string lbl1 = "Label 1 cell value";
string lbl2 = "Label 2 cell value";

// Создаёт экземпляр класса презентации, представляющего файл презентации 

using (Presentation pres = new Presentation("chart2.pptx"))
{
    ISlide slide = pres.Slides[0];


    IChart chart = pres.Slides[0].Shapes.AddChart(ChartType.Bubble, 50, 50, 600, 400, true);

    IChartSeriesCollection series = chart.ChartData.Series;

    series[0].Labels.DefaultDataLabelFormat.ShowLabelValueFromCell = true;

    IChartDataWorkbook wb = chart.ChartData.ChartDataWorkbook;

    series[0].Labels[0].ValueFromCell = wb.GetCell(0, "A10", lbl0);
    series[0].Labels[1].ValueFromCell = wb.GetCell(0, "A11", lbl1);
    series[0].Labels[2].ValueFromCell = wb.GetCell(0, "A12", lbl2);

    pres.Save("resultchart.pptx", Aspose.Slides.Export.SaveFormat.Pptx);
}

Управление листами

Этот код C# демонстрирует операцию, где используется свойство IChartDataWorkbook.Worksheets для доступа к коллекции листов:

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

using (Presentation pres = new Presentation())
{
   IChart chart = pres.Slides[0].Shapes.AddChart(ChartType.Pie, 50, 50, 400, 500);
   IChartDataWorkbook wb =  chart.ChartData.ChartDataWorkbook;
   for (int i = 0; i < wb.Worksheets.Count; i++)
      Console.WriteLine(wb.Worksheets[i].Name);
}

Указание типа источника данных

Этот код C# показывает, как указать тип для источника данных:

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

using (Presentation pres = new Presentation())
{
    IChart chart = pres.Slides[0].Shapes.AddChart(ChartType.Column3D, 50, 50, 600, 400, true);
    IStringChartValue val = chart.ChartData.Series[0].Name;
    
    val.DataSourceType = DataSourceType.StringLiterals;
    val.Data = "LiteralString";

    val = chart.ChartData.Series[1].Name;
    val.Data = chart.ChartData.ChartDataWorkbook.GetCell(0, "B1", "NewCell");

    pres.Save("pres.pptx", SaveFormat.Pptx);
}

Обнаружение неподдерживаемых форматов встроенных рабочих книг

Aspose.Slides не поддерживает бинарный формат рабочей книги Excel (.xlsb), который может быть встроен в некоторые диаграммы. Вы можете использовать свойство EmbeddedWorkbookType на IChartData вместе с перечислением WorkbookType для обнаружения неподдерживаемых форматов и пропуска таких диаграмм.

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

using (var presentation = new Presentation("sample.pptx"))
{
    var slide = presentation.Slides[0];

    foreach (var shape in slide.Shapes)
    {
        if (shape is not IChart chart) continue;

        var chartData = chart.ChartData;

        if (chartData.DataSourceType == ChartDataSourceType.InternalWorkbook &&
            chartData.EmbeddedWorkbookType == WorkbookType.WorkbookBinaryMacro)
        {
            // Встроенная рабочая книга в формате .xlsb, который не поддерживается.
            continue;
        }

        // Читайте или изменяйте данные рабочей книги диаграммы здесь.
    }
}

Внешняя рабочая книга

Aspose.Slides поддерживает использование внешних рабочих книг в качестве источника данных для диаграмм.

Создание внешней рабочей книги

С помощью методов ReadWorkbookStream и SetExternalWorkbook вы можете либо создать внешнюю рабочую книгу с нуля, либо сделать внутреннюю рабочую книгу внешней.

Этот код C# демонстрирует процесс создания внешней рабочей книги:

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

using (Presentation pres = new Presentation())
{
    const string workbookPath = "externalWorkbook1.xlsx";

    IChart chart = pres.Slides[0].Shapes.AddChart(ChartType.Pie, 50, 50, 400, 600);
    using (FileStream fileStream = new FileStream(workbookPath, FileMode.Create))
    {
        byte[] workbookData = chart.ChartData.ReadWorkbookStream().ToArray();
        fileStream.Write(workbookData, 0, workbookData.Length);
    }
    
    chart.ChartData.SetExternalWorkbook(Path.GetFullPath(workbookPath));

    pres.Save("externalWorkbook.pptx", SaveFormat.Pptx);
}

Назначение внешней рабочей книги

С помощью метода SetExternalWorkbook вы можете назначить внешнюю рабочую книгу диаграмме в качестве её источника данных. Этот метод также можно использовать для обновления пути к внешней рабочей книге (если она была перемещена).

Хотя вы не можете редактировать данные в рабочих книгах, хранящихся в удалённых местах или ресурсах, их всё равно можно использовать как внешний источник данных. Если указан относительный путь к внешней рабочей книге, он автоматически преобразуется в полный путь.

Этот код C# показывает, как задать внешнюю рабочую книгу:

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

// Путь к каталогу документов.
using (Presentation pres = new Presentation())
{
    IChart chart = pres.Slides[0].Shapes.AddChart(ChartType.Pie, 50, 50, 400, 600, false);
    IChartData chartData = chart.ChartData;
                    
    chartData.SetExternalWorkbook(Path.GetFullPath("externalWorkbook.xlsx"));
                  

    chartData.Series.Add(chartData.ChartDataWorkbook.GetCell(0, "B1"), ChartType.Pie);
    chartData.Series[0].DataPoints.AddDataPointForPieSeries(chartData.ChartDataWorkbook.GetCell(0, "B2"));
    chartData.Series[0].DataPoints.AddDataPointForPieSeries(chartData.ChartDataWorkbook.GetCell(0, "B3"));
    chartData.Series[0].DataPoints.AddDataPointForPieSeries(chartData.ChartDataWorkbook.GetCell(0, "B4"));

    chartData.Categories.Add(chartData.ChartDataWorkbook.GetCell(0, "A2"));
    chartData.Categories.Add(chartData.ChartDataWorkbook.GetCell(0, "A3"));
    chartData.Categories.Add(chartData.ChartDataWorkbook.GetCell(0, "A4"));
    pres.Save("Presentation_with_externalWorkbook.pptx", SaveFormat.Pptx);
}

Параметр ChartData (в методе SetExternalWorkbook) используется для указания, будет ли загружена рабочая книга Excel.

  • Когда значение ChartData установлено в false, обновляется только путь к рабочей книге — данные диаграммы не загружаются и не обновляются из целевой рабочей книги. Этот параметр полезен, когда целевая рабочая книга отсутствует или недоступна.
  • Когда значение ChartData установлено в true, данные диаграммы обновляются из целевой рабочей книги.
using Aspose.Slides;
using Aspose.Slides.Charts;
using Aspose.Slides.Export;

using (Presentation pres = new Presentation())
{
	IChart chart = pres.Slides[0].Shapes.AddChart(ChartType.Pie, 50, 50, 400, 600, true);
	IChartData chartData = chart.ChartData;

	(chartData as ChartData).SetExternalWorkbook("http://path/doesnt/exists", false);

	pres.Save("SetExternalWorkbookWithUpdateChartData.pptx", SaveFormat.Pptx);
}

Получение пути к внешней рабочей книге, используемой диаграммой

  1. Создайте экземпляр класса Presentation .
  2. Получите ссылку на слайд по его индексу.
  3. Создайте объект для формы диаграммы.
  4. Создайте объект типа источника (ChartDataSourceType), представляющего источник данных диаграммы.
  5. Укажите соответствующее условие в зависимости от того, совпадает ли тип источника с типом внешней рабочей книги.

Этот код C# демонстрирует операцию:

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

using (Presentation pres = new Presentation("pres.pptx"))
{
    ISlide slide = pres.Slides[1];
    IChart chart = (IChart)slide.Shapes[0];
    ChartDataSourceType sourceType = chart.ChartData.DataSourceType;
    if (sourceType == ChartDataSourceType.ExternalWorkbook)
    {
        string path = chart.ChartData.ExternalWorkbookPath;
    }
    
    // Сохраняет презентацию
    pres.Save("Result.pptx", SaveFormat.Pptx);
}

Редактировать данные диаграммы

Вы можете редактировать данные во внешних рабочих книгах так же, как вносите изменения в содержимое внутренних рабочих книг. Если внешняя рабочая книга не может быть загружена, генерируется исключение.

Этот код C# реализует описанный процесс:

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

using (Presentation pres = new Presentation("presentation.pptx"))
{
    IChart chart = pres.Slides[0].Shapes[0] as IChart;
    ChartData chartData = (ChartData)chart.ChartData;
                   

    chartData.Series[0].DataPoints[0].Value.AsCell.Value = 100;
    pres.Save("presentation_out.pptx", SaveFormat.Pptx);
}

Восстановление рабочей книги из кэша диаграммы

Если диаграмма использует внешнюю рабочую книгу, которая отсутствует или недоступна, Aspose.Slides может восстановить рабочую книгу диаграммы из данных, кэшированных в презентации. Создайте LoadOptions, настройте её SpreadsheetOptions, и установите ISpreadsheetOptions.RecoverWorkbookFromChartCache в true перед открытием презентации.

Следующий пример C# открывает презентацию, где диаграмма ссылается на недоступную внешнюю рабочую книгу, и получает восстановленные данные через IChart.ChartData и IChartData.ChartDataWorkbook:

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

var loadOptions = new LoadOptions
{
    SpreadsheetOptions = new SpreadsheetOptions
    {
        RecoverWorkbookFromChartCache = true
    }
};

using var presentation = new Presentation("presentation.pptx", loadOptions);

var chart = (IChart)presentation.Slides[0].Shapes[0];
var recoveredWorkbook = chart.ChartData.ChartDataWorkbook;

// Read or modify the recovered workbook data here.

Если внешняя рабочая книга недоступна и восстановление отключено, Aspose.Slides выбрасывает InvalidOperationException. Включайте восстановление только тогда, когда использование кэшированных данных диаграммы является приемлемой альтернативой, поскольку кэш может не содержать изменений, внесённых во внешнюю рабочую книгу после последнего обновления презентации.

FAQ

Могу ли я определить, связана ли конкретная диаграмма с внешней или встроенной рабочей книгой?
Да. У диаграммы есть data source type и path to an external workbook; если источник — внешняя рабочая книга, вы можете прочитать полный путь, чтобы убедиться, что используется внешний файл.

Поддерживаются ли относительные пути к внешним рабочим книгам и как они хранятся?
Да. При указании относительного пути он автоматически преобразуется в абсолютный. Это удобно для переносимости проекта; однако презентация сохраняет абсолютный путь в файле PPTX.

Можно ли использовать рабочие книги, находящиеся на сетевых ресурсах/общих папках?
Да, такие рабочие книги могут использоваться как внешний источник данных. Однако прямое редактирование удалённых рабочих книг из Aspose.Slides не поддерживается — они могут использоваться только в качестве источника.

Перезаписывает ли Aspose.Slides внешний XLSX при сохранении презентации?
Нет. Презентация сохраняет link to the external file и использует его только для чтения данных. Сам внешний файл не изменяется при сохранении презентации.

Что делать, если внешний файл защищён паролем?
Aspose.Slides не принимает пароль при связывании. Обычно снимают защиту заранее или подготавливают дешифрованную копию (например, с помощью Aspose.Cells) и связываются с этой копией.

Могут ли несколько диаграмм ссылаться на одну и ту же внешнюю рабочую книгу?
Да. Каждая диаграмма хранит свою собственную ссылку. Если все они указывают на один файл, изменение этого файла отразится в каждой диаграмме при следующей загрузке данных.