簡體   English   中英

使用 Apache poi 在一張 Excel 表格中繪制多個折線圖

[英]Plot multiple line charts in one excel sheet using Apache poi

我想在一張 Excel 表格中生成多個不同系列的圖表。 但是,我可以使用以下代碼繪制一個圖表,但是當我在以下代碼中創建第二個 XSSFChart 圖表和 XSSFClientAnchor 錨點時,它無法在 Excel 中繪制圖表。 如何在一個 Excel 中繪制兩個或多個折線圖。 以下代碼有什么問題?

想要的結果 .

public class MultipleChartWithThreeLines {
    private static XDDFLineChartData.Series addLineSeriesToChartData(XDDFChartData chartData, XSSFSheet sheet, String categoryDataRef, String valueDataRef, String seriesTitleRef, PresetColor lineColor) {

        XDDFDataSource<Double> categoryData = XDDFDataSourcesFactory.fromNumericCellRange(sheet, CellRangeAddress.valueOf(categoryDataRef));
        XDDFNumericalDataSource<Double> valueData = XDDFDataSourcesFactory.fromNumericCellRange(sheet, CellRangeAddress.valueOf(valueDataRef));

        XDDFLineChartData.Series series = (XDDFLineChartData.Series) chartData.addSeries(categoryData, valueData);
        series.setTitle("", new CellReference(seriesTitleRef)); // https://stackoverflow.com/questions/21855842
        series.setSmooth(false); // https://stackoverflow.com/questions/29014848

        // define data-point marker
        series.setMarkerStyle(MarkerStyle.CIRCLE); // https://stackoverflow.com/questions/39636138

        // define line color
        // https://stackoverflow.com/questions/24676460
        XDDFShapeProperties shapeProperties = series.getShapeProperties();
        if (shapeProperties == null) {
            shapeProperties = new XDDFShapeProperties();
        }
        shapeProperties.setLineProperties(solidLineWithColor(lineColor));
        series.setShapeProperties(shapeProperties);

        // if your series have missing values like https://stackoverflow.com/questions/29014848
        // chart.displayBlanksAs(DisplayBlanks.GAP);

        return series;
    }

    private static XDDFLineProperties solidLineWithColor(PresetColor color) {
        XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
        XDDFLineProperties line = new XDDFLineProperties();
        line.setFillProperties(fill);
        return line;
    }

    private static XDDFChartLegend addLegendToChart(XSSFChart chart) {
        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(LegendPosition.BOTTOM);

        return legend;
    }

    private static XSSFChart createChartOnSheet(XSSFSheet sheet, int col1, int row1, int col2, int row2) {
        XSSFDrawing drawing = sheet.createDrawingPatriarch();
        XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, col1, row1, col2, row2);
        XSSFChart chart = drawing.createChart(anchor);

        return chart;
    }

    private static XDDFChartAxis[] addAxesToChart(XSSFChart chart, String titleCategoryBottom, String titleValueLeft) {
        XDDFChartAxis[] axesCatVal = new XDDFChartAxis[4];

        // category axis at the bottom
        XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        bottomAxis.setTitle(titleCategoryBottom); // https://stackoverflow.com/questions/32010765
        axesCatVal[0] = bottomAxis;

        // value axis at the left
        XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
        leftAxis.setTitle(titleValueLeft);
        leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
        axesCatVal[1] = leftAxis;

        return axesCatVal;
    }


    private static void writeWorkbookToFile(XSSFWorkbook wb, String filename) throws IOException {
        FileOutputStream fileOut = new FileOutputStream(filename);
        wb.write(fileOut);
        fileOut.close();
    }

    public static void main(String[] args) throws Exception {

        String workbookFilename = "e:/Graph_5.xlsx"; //"e:/Graph_5.xlsx";

        // open workbook with data
        XSSFWorkbook wb = new XSSFWorkbook(workbookFilename);

        // draw chart with 3 lines
        XSSFSheet sheet = wb.getSheetAt(0);
        String sheetName = sheet.getSheetName();

        System.out.println("Drawing line-chart on sheet: " + sheetName);

        // create chart
        XSSFChart chart = createChartOnSheet(sheet, 6, 0, 25, 15);
        XSSFChart medianAngleChart = createChartOnSheet(sheet,10,17,25,15);

        // add legend to chart
        addLegendToChart(chart);
        addLegendToChart(medianAngleChart);


        // add value (left) and category (bottom) axes
        XDDFChartAxis[] axesCatVal = addAxesToChart(chart, "", "Inscribed Angle");       // Add data (as Line Chart)
        XDDFChartAxis[] axesCatVal_1 = addAxesToChart(medianAngleChart, "", "Median Angle");       // Add data (as Line Chart)

        // add line-chart data-collection to chart
        XDDFLineChartData chartData = (XDDFLineChartData) chart.createData(ChartTypes.LINE, axesCatVal[0], (XDDFValueAxis) axesCatVal[1]);
        XDDFLineChartData chartData_1 = (XDDFLineChartData) medianAngleChart.createData(ChartTypes.LINE, axesCatVal_1[0], (XDDFValueAxis) axesCatVal_1[1]);

        // Line-1
        XDDFLineChartData.Series series1 = addLineSeriesToChartData(chartData
                , sheet
                ,sheetName + "!$B$3:$B$66"
                , sheetName + "!$D$3:$D$66"
                , sheetName + "!$D$2"
                ,  PresetColor.RED
        );
        System.out.println("added line 1: \n" + series1);

        // Line-2
        XDDFLineChartData.Series series2 = addLineSeriesToChartData(chartData
                , sheet
                ,sheetName+"!$B$3:$B$66"
                , sheetName+"!$E$3:$E$66"
                , sheetName+"!$E$2"
                ,  PresetColor.GREEN
        );
        System.out.println("added line 2: \n" + series2);

        // Line-3
        XDDFLineChartData.Series series3 = addLineSeriesToChartData(chartData
                , sheet
                , sheetName+"!$B$3:$B$66"
                , sheetName+"!$F$3:$F$66"
                , sheetName+"!$F$2"
                ,  PresetColor.BLUE
        );
        System.out.println("added line 3: \n" + series3);

        //second chart Line-1
        XDDFLineChartData.Series series4 = addLineSeriesToChartData(chartData_1
                , sheet
                , sheetName+"!$B$3:$B$66"
                , sheetName+"!$G$3:$G$66"
                , sheetName+"!$G$2"
                ,  PresetColor.BLUE
        );
        System.out.println("added line 4: \n" + series4);

        chart.plot(chartData);
        medianAngleChart.plot(chartData_1);

        // save workbook

       writeWorkbookToFile(wb,"ChartWithThreeLines.xlsx");

        // close workbook
        wb.close();
    }
}

不太清楚您顯示的代碼在哪里出錯。 拆分成多種方法真的很難。

但這里有一個完整的例子,它可能展示了做你想做的最簡單的方法。

代碼:

import java.io.*;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.xddf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;

public class CreateExcelTwoLineCharts {

 public static void main(String[] args) throws IOException {
  try (XSSFWorkbook wb = new XSSFWorkbook()) {

   // create the data
   XSSFSheet sheet = wb.createSheet("Sheet1");
   Row row;
   Cell cell;
   row = sheet.createRow(0);
   row.createCell(0).setCellValue("Months");
   row.createCell(1).setCellValue("Mountain View");
   row.createCell(2).setCellValue("New York");
   row.createCell(3).setCellValue("Washington");
   row.createCell(4).setCellValue("England");
   row.createCell(5).setCellValue("New Zeland");
   row.createCell(6).setCellValue("Australia");
    for (int r = 1; r < 13; r++) {
    row = sheet.createRow(r);
    for (int c = 0; c < 7; c++) {
     cell = row.createCell(c);
     if (c == 0) cell.setCellValue(r);
     else cell.setCellFormula("RANDBETWEEN(50, 99)");
    }
   }

   // create data sources
   XDDFDataSource<Double> months = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 12, 0, 0));
   int c = 1;
   XDDFNumericalDataSource<Double> mView = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 12, c, c++));
   XDDFNumericalDataSource<Double> nYork = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 12, c, c++));
   XDDFNumericalDataSource<Double> washingt = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 12, c, c++));
   XDDFNumericalDataSource<Double> engl = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 12, c, c++));
   XDDFNumericalDataSource<Double> nZeal = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 12, c, c++));
   XDDFNumericalDataSource<Double> austral = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 12, c, c++));

   // create sheets drawing
   XSSFDrawing drawing = sheet.createDrawingPatriarch();

   // needed objeccts for the charts
   XSSFClientAnchor anchor;
   XSSFChart chart;
   XDDFChartLegend legend;
   XDDFCategoryAxis bottomAxis;
   XDDFValueAxis leftAxis;
   XDDFChartData data;
   XDDFChartData.Series series;

//======first line chart============================================================
   // create anchor
   anchor = drawing.createAnchor(0, 0, 0, 0, 8, 0, 14, 12); // anchor col8,row0 to col14,row12
   // create chart
   chart = drawing.createChart(anchor);
   legend = chart.getOrAddLegend();
   legend.setPosition(LegendPosition.BOTTOM);

   // create the axes
   bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
   leftAxis = chart.createValueAxis(AxisPosition.LEFT);
   leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);

   // create chart data
   data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
   // create series
   series = data.addSeries(months, mView);
   series.setTitle("Mountain View", new CellReference(sheet.getSheetName(), 0, 1, true, true));
   series = data.addSeries(months, nYork);
   series.setTitle("New York", new CellReference(sheet.getSheetName(), 0, 2, true, true));
   series = data.addSeries(months, washingt);
   series.setTitle("Washington", new CellReference(sheet.getSheetName(), 0, 3, true, true));
   chart.plot(data);

   solidLineSeries(data, 0, PresetColor.BLUE);            
   solidLineSeries(data, 1, PresetColor.RED);            
   solidLineSeries(data, 2, PresetColor.GREEN); 

//======second line chart============================================================
   // create anchor
   anchor = drawing.createAnchor(0, 0, 0, 0, 8, 13, 14, 25); // anchor col8,row13 to col14,row25
   // create chart
   chart = drawing.createChart(anchor);
   legend = chart.getOrAddLegend();
   legend.setPosition(LegendPosition.BOTTOM);

   // create the axes
   bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
   leftAxis = chart.createValueAxis(AxisPosition.LEFT);
   leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);

   // create chart data
   data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
   // create series
   series = data.addSeries(months, engl);
   series.setTitle("England", new CellReference(sheet.getSheetName(), 0, 4, true, true));
   series = data.addSeries(months, nZeal);
   series.setTitle("New Zeland", new CellReference(sheet.getSheetName(), 0, 5, true, true));
   series = data.addSeries(months, austral);
   series.setTitle("Australia", new CellReference(sheet.getSheetName(), 0, 6, true, true));
   chart.plot(data);

   solidLineSeries(data, 0, PresetColor.BLUE);            
   solidLineSeries(data, 1, PresetColor.RED);            
   solidLineSeries(data, 2, PresetColor.GREEN);            

   // write the output to a file
   try (FileOutputStream fileOut = new FileOutputStream("CreateExcelTwoLineCharts.xlsx")) {
    wb.write(fileOut);
   }
  }
 }

 private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
  XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
  XDDFLineProperties line = new XDDFLineProperties();
  line.setFillProperties(fill);
  XDDFChartData.Series series = data.getSeries().get(index);
  XDDFShapeProperties properties = series.getShapeProperties();
  if (properties == null) {
   properties = new XDDFShapeProperties();
  }
  properties.setLineProperties(line);
  series.setShapeProperties(properties);
 }
}

結果:

在此處輸入圖片說明

為每個圖表創建一個單獨的錨點。 在我在 main 中聲明每個錨點之前,我的繪圖程序不會繪制多個折線圖

public static void main(String[] args) throws IOException, FileNotFoundException, InvalidFormatException {
    String file = "OriginalWindData - pract2.xlsx";
    XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(file));
    XSSFSheet sh = wb.getSheetAt(0);
    int[] anchor1 = {8,13,14,25};
    int[] anchor2 = {anchor1[2]+1,anchor1[1],anchor1[2]+1+6,anchor1[3]};
    XSSFClientAnchor anchr1 = sh.createDrawingPatriarch().createAnchor(0, 0, 0, 0, anchor1[0] , anchor1[1], anchor1[2], anchor1[3]);
    XSSFClientAnchor anchr2 = sh.createDrawingPatriarch().createAnchor(0, 0, 0, 0, anchor2[0] , anchor2[1], anchor2[2], anchor2[3]);
    //left,top,right,bottom
    int[][] dcoords1= {
            {4,0,4,52129},
            {6,0,6,52129},
            {8,0,8,52129}
    };
    int[][] dcoords2= {
            {4,0,4,52129},
            {6,0,6,52129}
    };
    //left top,right bottom
    //makeChart(sh,4,0,6,52129);
    makeChartv2(sh,dcoords1,anchr1);
    makeChartv2(sh,dcoords2,anchr2);
    try (FileOutputStream fileOut = new FileOutputStream("chartout.xlsx")) {
        wb.write(fileOut);
    }
    wb.close();
}

... 希望這可以幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM