Správa datových sérií grafu v prezentacích na Androidu

Přehled

Graf ukládá svá vykreslená data do sešitu s daty grafu. IChartSeries představuje jeden soubor souvisejících hodnot a každý IChartDataPoint v sérii odkazuje na jednu nebo více buněk sešitu. Objekt IChartCategory poskytuje štítky nebo hodnoty seskupení sdílené sériemi. Název série, kategorie a hodnoty bodů jsou tedy propojeny s objekty IChartDataCell, místo aby byly uloženy pouze jako zobrazovaný text.

Pro typický kategoriový graf výchozí sešit používá řádek 0 pro názvy sérií, sloupec 0 pro názvy kategorií a zbytek buněk pro hodnoty sérií. Indexy listu, řádku a sloupce předávané do IChartDataWorkbook.getCell jsou nulové. Toto uspořádání je užitečné, když vytváříte graf s výchozími daty, ale nepředpokládejte, že každý existující graf jej používá. Pro načtenou prezentaci si před změnou hodnot sešitu prohlédněte buňky, na které odkazují série, kategorie a datové body.

Nastavení grafu mají tři různé úrovně:

Když není explicitně nastaveno vyplnění bodu nebo série, určuje vzhled styl a motiv grafu. Když jsou přítomna jak nastavení série, tak bodu, vítězí formátování bodu.

graf-serií-powerpoint

Nastavení překrytí sérií v grafu

IChartSeries.getOverlap udává, jak moc se sloupce nebo pruhy překrývají v 2D grafu, v rozmezí -100 až 100 %. Jedná se o jen‑čtení projekce nastavení na nadřazené skupině sérií. K aktualizaci všech kompatibilních sérií ve skupině použijte IChartSeriesGroup.setOverlap. Tato možnost se vztahuje na typy grafů, které zobrazují seskupené sloupce nebo pruhy; neovlivní nesouvisející skupiny sérií v kombinovaném grafu.

Následující příklad nastaví překrytí pro skupinu, která obsahuje první sérii:

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);

    // Nový graf obsahuje ukázkové série, kategorie a hodnoty.
    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();
}

Výsledek:

Překrytí sérií

Změna barvy výplně série

Použijte IChartSeries.getFormat k nastavení výchozí výplně celé série. Pokud má bod již explicitně nastavenou výplň, přepíše jeho nastavení IChartDataPoint.getFormat výplň série pro tento bod.

Následující příklad použije pevnou modrou výplň na první sérii:

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();
}

Výsledek:

Barva série

Změna názvu série

Název série je uložen v sešitu dat grafu a normálně se zobrazuje v legendě. Ve výchozím sešitu vytvořeném pro grupovaný sloupcový graf je buňka B1 na řádku 0, sloupci 1 a obsahuje název první série. Pojmenované konstanty v následujícím příkladu tuto strukturu explicitně vymezují:

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();
}

Můžete také aktualizovat buňku, na kterou již odkazuje IChartSeries.getName. Tento přístup se vyhne předpokladu konkrétního řádku a sloupce v existujícím grafu:

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();
}

Výsledek:

Název série

Vytvoření série s názvem z více buněk

Kompozitní název série je užitečný, když jsou název produktu a období výkazu uloženy v oddělených buňkách sešitu. Například můžete kombinovat Product A v B1 a 2026 v C1 do jednoho názvu série a přitom zachovat propojení obou částí na jejich zdrojové buňky.

Použijte IChartDataWorkbook.getCellCollection k načtení rozsahu názvu a tento kolekci předáte metodě IChartSeriesCollection.add. Argument skipHiddenCells určuje, zda jsou skryté buňky zahrnuty: true je vyloučí, false zahrne. Tento příklad používá false, aby zahrnul každou buňku v rozsahu názvu.

Následující příklad vytvoří prezentaci s jednou sérií a dvěma datovými body. Buňky B1:C1 poskytují pouze název série; A2:A3 poskytují štítky kategorií a B2:B3 číselné hodnoty.

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);

    // Tyto dvě buňky poskytují název série.
    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);

    // Samostatné buňky poskytují kategorie a číselné datové body.
    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();
}

Výsledný název série je Product A 2026 s mezerou mezi dvěma hodnotami buněk. Legenda zobrazuje tento název jako jeden položku pro oba sloupce. Obrázek níže ilustruje výsledek:

Sloupcový graf s hodnotami Sever a Jižní a kompozitním názvem série Product A 2026 v legendě

Získání automatické barvy výplně série

IChartSeries.getAutomaticSeriesColor vrací barvu vypočítanou z indexu série a stylu grafu jako celočíslo Android ARGB. Jedná se o barvu použité, když výplň série není explicitně definována. Volání metody pouze načte vypočítanou barvu; nepřiřazuje novou výplň.

Následující příklad vypíše automatické celočíselné hodnoty barvy pro každou výchozí sérii:

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();
}

Přesné celočíselné hodnoty závisí na stylu a motivu grafu.

Nastavení inverzní barvy výplně pro sérii grafu

Pro pruhové, sloupcové a bublinové série může IChartSeries.setInvertIfNegative zobrazit záporné hodnoty jinou výplní. Nastavte běžnou výplň série na pevnou, povolte invertování a přiřaďte barvu záporných hodnot pomocí IChartSeries.getInvertedSolidFillColor. Záporná čísla zůstávají v sešitu beze změny; mění se pouze jejich zobrazovaná barva.

Následující příklad nahradí výchozí data grafu jednou sérií. Řádek 0 listu obsahuje název série, sloupec 0 názvy kategorií a sloupec 1 hodnoty:

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();
}

Výsledek:

Inverzní barva pevné výplně

Invertování pro jeden bod můžete povolit pomocí IChartDataPoint.setInvertIfNegative. V následujícím příkladu je invertování zakázáno pro sérii a povoleno jen pro vybraný bod. Bod má také přiřazenou zápornou hodnotu, aby byl efekt viditelný:

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();
}

Vymazání konkrétní hodnoty datového bodu

Chcete‑li učinit jeden bod prázdným, aniž byste odstranili ostatní body, nastavte jeho podporující buňku sešitu na null. U sloupcového grafu je vykreslená hodnota dostupná přes IChartDataPoint.getValue. Datový bod zůstane na stejné pozici kategorie, ale graf jej bude považovat za prázdný podle nastavení zobrazení prázdných hodnot.

Následující příklad vymaže pouze druhý bod v první sérii:

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();
}

Grafy rozptylu používají oddělené buňky X a Y a bublinové grafy také buňku velikosti. Vymažte jen buňku, která představuje hodnotu, kterou chcete odstranit. Neukazujte IChartDataPointCollection.clear pokud chcete zachovat ostatní body, protože tato metoda odstraní všechny datové body ze sbírky.

Řízení zobrazení prázdných buněk

Skryté buňky, které obsahují hodnoty, jsou samostatný případ od prázdných buněk. Pro zahrnutí nebo vyloučení dat ze skrytých řádků a sloupců listu viz Include Data from Hidden Rows and Columns.

Prázdná buňka sešitu představuje chybějící data; buňka obsahující 0 představuje známou číselnou hodnotu. Voláním IChartDataCell.setValue s null buňku vyprázdníte. Číselná nula zůstane nulou bez ohledu na nastavení prázdných buněk.

Pomocí IChart.setDisplayBlanksAs vyberte, jak má graf zobrazovat prázdné buňky. Toto nastavení se vztahuje na celý graf. Mění způsob, jakým jsou prázdné body vykresleny, aniž by se prázdná buňka sešitu vyplnila nulou nebo interpolovanou hodnotou.

Následující samostatný příklad vytvoří čárový graf s jednou sérií, vymaže hodnotu pro den 3 a uloží graf ve všech třech režimech. Vstupní soubor není potřeba. IChartDataWorkbook používá list 0, sloupec 0 pro štítky kategorií a sloupec 1 pro hodnoty; řádek 0 obsahuje název série. Konečná data jsou 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);
    }

    // Nechte den 3 skutečně prázdný, přičemž zachovejte jeho kategorii a datový bod.
    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();
}

Každý výstupní soubor ukládá režim přiřazený před uložením: empty_cells_Gap.pptx, empty_cells_Zero.pptx a empty_cells_Span.pptx. Pro uložení jen jedné verze přiřaďte požadovaný režim a prezentaci uložte jednou místo iterace přes režimy.

Porovnání níže ukazuje stejná data ve všech třech souborech. Den 3 je v sešitu prázdný ve všech případech:

Čárové grafy se stejnými daty: Mezery přeruší čáru v den 3, Nula snižuje čáru na nulu a Spojení (Span) spojuje den 2 s dnem 4.

Viditelný efekt závisí na typu grafu. Čárový graf umožňuje snadno porovnat všechny tři režimy. Pruhové a sloupcové grafy nemají čáru, která by se spojila přes chybějící kategorii, takže Span nemůže vytvořit spojující úsek ukázaný výše; chybějící sloupec a sloupec o výšce nula mohou vypadat podobně. Podobně u grafu rozptylu s pouze značkami neexistuje spojovací čára. Neočekávejte tři odlišné výsledky u každého typu grafu; ověřte výstup pro použitý typ.

Nastavení šířky mezery mezi sériemi

Šířka mezery je prostor mezi sousedními shluky pruhů nebo sloupců, vyjádřený v procentech šířky pruhu nebo sloupce. Stejně jako překrytí patří skupině nadřazené sérií, nikoli jednotlivé sérii. Zavolejte IChartSeriesGroup.setGapWidth jednou pro skupinu. Větší hodnota vytvoří více prostoru mezi shluky; menší hodnota je učiní hustšími.

Následující příklad změní šířku mezery a uloží pouze konečnou prezentaci:

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();
}

Výsledek:

Šířka mezery

Často kladené otázky

Které typy grafů podporují datové série?

Všechny typy grafů reprezentované výčtem ChartType používají data grafu, ale jejich série nemají vždy stejnou strukturu hodnot ani nastavení. Například kategoriové grafy používají kategorie a hodnoty, grafy rozptylu používají X a Y hodnoty a bublinové grafy přidávají velikosti bublin. Použijte metodu tvorby datových bodů, která odpovídá typu série. Možnosti jako překrytí a šířka mezery platí jen pro kompatibilní pruhové nebo sloupcové skupiny.

Co je skupina sérií grafu?

IChartSeriesGroup obsahuje kompatibilní série, které sdílejí nastavení na úrovni skupiny. Kombinovaný graf může obsahovat více než jednu skupinu, takže změna skupiny dosažená přes jednu sérii nemusí nutně změnit všechny série v grafu.

Obsahuje nově vytvořený graf výchozí data?

Ano. Ve výchozím nastavení IShapeCollection.addChart vytvoří ukázkové série, kategorie a hodnoty. Můžete tyto buňky upravit nebo před přidáním zcela vlastního datového souboru vymazat jak série, tak kolekce kategorií. Přetížení může také vytvořit graf bez výchozích dat.

Jak jsou objekty grafu propojeny s buňkami sešitu?

Názvy sérií, štítky kategorií a hodnoty datových bodů odkazují na buňky v IChartDataWorkbook. Změna odkazované buňky aktualizuje odpovídající prvek grafu. Při vytváření vlastních dat udržujte řádky kategorií a řádky hodnot sérií zarovnané, aby každý bod byl vykreslen pod zamýšlenou kategorií.

Jak vymazat jeden bod místo celé série?

Nastavte odpovídající buňku hodnoty na null, aby bod zůstal na své pozici kategorie jako prázdný bod. Použijte IChartDataPointCollection.clear pouze v případě, že chcete odstranit všechny body ze série. Pokud také odstraňujete kategorie, aktualizujte všechny série tak, aby jejich hodnoty zůstaly zarovnané s kolekcí kategorií.

Jak jsou prázdné body zobrazovány?

Výsledek závisí na typu grafu a hodnotě nastavené pomocí IChart.setDisplayBlanksAs. Podporované grafy mohou zobrazovat prázdné body jako mezery, jako nulové hodnoty nebo propojením sousedních bodů. Zvolte nastavení, které odpovídá významu chybějících dat ve vaší prezentaci. Viz Řízení zobrazení prázdných buněk pro kompletní příklad a vizuální srovnání.

Jak jsou formátovány záporné hodnoty?

U podporovaných pruhových, sloupcových a bublinových sérií zavolejte IChartSeries.setInvertIfNegative a nastavte barvu vrácenou metodou IChartSeries.getInvertedSolidFillColor. Chování můžete přepsat pro jednotlivý bod pomocí IChartDataPoint.setInvertIfNegative. Tyto metody ovlivňují formátování, ne uložené číselné hodnoty.

Které formátování vyhrává, když je formátována i série i bod?

Explicitní formátování datového bodu má přednost pro daný bod. Ostatní body nadále používají explicitní formát série nebo, pokud formát série není definován, automatický styl a motiv grafu. Skupinová nastavení jako překrytí a šířka mezery řídí rozvržení a nejsou přepisovány na úrovni bodu.

Existuje limit počtu sérií, které graf může obsahovat?

Aspose.Slides neukládá samostatný pevný limit počtu sérií. V praxi omezují souborové limity prezentace, dostupná paměť, doba vykreslování a čitelnost grafu.

Co změnit, když jsou sloupce příliš blízko nebo příliš daleko od sebe?

Zavolejte IChartSeriesGroup.setGapWidth na příslušné nadřazené skupině sérií. Zvýšením hodnoty rozšíříte prostor mezi shluky, snížením jej přiblížíte.