0

1I want to plot three lines in a graph using Apache POI with OpenXmlFormats in excel,however i can plot two lines, but not able to plot third line i don,t know why. so kindly help me to plot three lines in single graph. i am sharing code for ploting 2-lines.. [2] i have add a picture that i want in result. [3] how to plot multiple chart in single excel file.

public class LineChart {

    public static void main(String[] args) throws Exception {
        String filename = "e:/Graph_5.xlsx";
        if(filename!=null && !filename.equals("")){
            try{
                FileInputStream fis = new FileInputStream(filename);
                XSSFWorkbook wb = new XSSFWorkbook(fis);
                XSSFSheet sheet = wb.getSheetAt(0);
                XSSFDrawing drawing = sheet.createDrawingPatriarch();
                XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 4, 0, 25, 15);
                XSSFChart chart = drawing.createChart(anchor);

                CTChart ctChart = ((XSSFChart)chart).getCTChart();  
                CTPlotArea ctPlotArea = ctChart.getPlotArea();
                //the line chart
                CTLineChart ctLineChart_1 = ctPlotArea.addNewLineChart();
                CTBoolean ctBoolean_1 = ctLineChart_1.addNewVaryColors();
                ctBoolean_1.setVal(false);
                //the line series
                CTLineSer ctLineSer_1 = ctLineChart_1.addNewSer();
                CTSerTx ctSerTx_1 = ctLineSer_1.addNewTx();
                CTStrRef ctStrRef_1 = ctSerTx_1.addNewStrRef();
                ctStrRef_1.setF("Sheet1!$B$1");

                ctLineSer_1.addNewIdx().setVal(0);  
                CTAxDataSource cttAxDataSource_1 = ctLineSer_1.addNewCat();
                ctStrRef_1 = cttAxDataSource_1.addNewStrRef();
                ctStrRef_1.setF("Sheet1!$A$2:$A$65"); 

                CTNumDataSource ctNumDataSource_1 = ctLineSer_1.addNewVal();
                CTNumRef ctNumRef_1 = ctNumDataSource_1.addNewNumRef();
                ctNumRef_1.setF("Sheet1!$B$2:$B$65");
                //at least the border lines in Libreoffice Calc ;-)
                ctLineSer_1.addNewSpPr().addNewLn().addNewSolidFill().addNewSrgbClr().setVal(new byte[] {0,0,0});   
                //telling the BarChart that it has axes and giving them Ids
                ctLineChart_1.addNewAxId().setVal(123456); //cat axis 1 (line)
                ctLineChart_1.addNewAxId().setVal(123457); //val axis 1 (left)

                // Line-2
                CTLineChart ctLineChart_2 = ctPlotArea.addNewLineChart();
                CTBoolean ctBoolean_2 = ctLineChart_2.addNewVaryColors();
                ctBoolean_2.setVal(false);

                CTLineSer ctLineSer_2 = ctLineChart_2.addNewSer();
                CTSerTx ctSerTx_2 = ctLineSer_2.addNewTx();
                CTStrRef ctStrRef_2 = ctSerTx_2.addNewStrRef();
                ctStrRef_2.setF("Sheet1!$C$1");

                ctLineSer_2.addNewIdx().setVal(1);
                CTAxDataSource cttAxDataSource_2 = ctLineSer_2.addNewCat();
                ctStrRef_2 = cttAxDataSource_2.addNewStrRef();
                ctStrRef_2.setF("Sheet1!$A$2:$A$65");

                CTNumDataSource ctNumDataSource_2 = ctLineSer_2.addNewVal();
                CTNumRef ctNumRef_2 = ctNumDataSource_2.addNewNumRef();
                ctNumRef_2.setF("Sheet1!$C$2:$C$65");

                ctLineSer_2.addNewSpPr().addNewLn().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{0,0,0});
                ctLineChart_2.addNewAxId().setVal(123458);
                ctLineChart_2.addNewAxId().setVal(123459);

                /*line-1 cat axis(X-axis) 1 (line)*/
                CTCatAx ctCatAx_1 = ctPlotArea.addNewCatAx(); 
                ctCatAx_1.addNewAxId().setVal(123456); //id of the cat axis
                CTScaling ctScaling_1 = ctCatAx_1.addNewScaling();
                ctScaling_1.addNewOrientation().setVal(STOrientation.MIN_MAX);
                ctCatAx_1.addNewDelete().setVal(false);
                ctCatAx_1.addNewAxPos().setVal(STAxPos.B);
                ctCatAx_1.addNewCrossAx().setVal(123457); //id of the val axis
                ctCatAx_1.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

                //val axis 1(Y-axis) (left)
                CTValAx ctValAx_1 = ctPlotArea.addNewValAx(); 
                ctValAx_1.addNewAxId().setVal(123457); //id of the val axis
                ctScaling_1 = ctValAx_1.addNewScaling();
                ctScaling_1.addNewOrientation().setVal(STOrientation.MIN_MAX);
                ctValAx_1.addNewDelete().setVal(false);
                ctValAx_1.addNewAxPos().setVal(STAxPos.L);
                ctValAx_1.addNewCrossAx().setVal(123456); //id of the cat axis
                ctValAx_1.addNewCrosses().setVal(STCrosses.AUTO_ZERO); //this val axis crosses the cat axis at zero
                ctValAx_1.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

                //line-2 cat axis(X-axis) 1 (line)

                CTCatAx ctCatAx_2 = ctPlotArea.addNewCatAx(); 
                ctCatAx_2.addNewAxId().setVal(123458); //id of the cat axis
                CTScaling ctScaling_2 = ctCatAx_2.addNewScaling();
                ctScaling_2.addNewOrientation().setVal(STOrientation.MIN_MAX);
                ctCatAx_2.addNewDelete().setVal(true);
                ctCatAx_2.addNewAxPos().setVal(STAxPos.B);
                ctCatAx_2.addNewCrossAx().setVal(123459); //id of the val axis
                ctCatAx_2.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

                //val axis 1(Y-axis) (left)
                CTValAx ctValAx_2 = ctPlotArea.addNewValAx(); 
                ctValAx_2.addNewAxId().setVal(123459); //id of the val axis
                ctScaling_2 = ctValAx_2.addNewScaling();
                ctScaling_2.addNewOrientation().setVal(STOrientation.MIN_MAX);
                ctValAx_2.addNewDelete().setVal(true);
                ctValAx_2.addNewAxPos().setVal(STAxPos.L);
                ctValAx_2.addNewCrossAx().setVal(123458); //id of the cat axis
                ctValAx_2.addNewCrosses().setVal(STCrosses.AUTO_ZERO); //this val axis crosses the cat axis at zero
                ctValAx_2.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);


                /legend
                CTLegend ctLegend = ctChart.addNewLegend();
                ctLegend.addNewLegendPos().setVal(STLegendPos.B);
                ctLegend.addNewOverlay().setVal(false);

                FileOutputStream fileOut = new FileOutputStream("SingleLineChart.xlsx");
                wb.write(fileOut);
                fileOut.close();
                wb.close();
            }catch(Exception e){}
        }
    }
}

the above code takes an input excel file and plot 2-lines perfectly but when i plot 3rd-line it doesn't give any error. when i open excel file it not get opened.

i have share the link of the output i want.kindly check it and help me to achive the same. i shall be very grateful to you. multiple chart in excel multiplecharts.png

*plotting multiple chart with 3 lines *

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

}
Fatmajk
  • 1,770
  • 1
  • 13
  • 22
sachin
  • 11
  • 4
  • 1
    Good question! Please also [edit] and __provide the code__ that *worked* (2-lines chart) and where *you tried* (3-lines chart). The title could be as simple as `plot 3 lines in a graph using Apache POI`. – hc_dev Mar 11 '19 at 12:42
  • @hc_dev - i have added 2-lines chart code. but when i am writtng code for 3rd line it s not working. kindly help me. – sachin Mar 12 '19 at 07:02
  • Why are you creating new charts having new axes for each series? Charts can have two separate axes but not three or more. So if you are trying creating a third axes pair for your third series too, then it fails. See https://stackoverflow.com/questions/38913412/create-bar-chart-in-excel-with-apache-poi/38920290#38920290 where I create a bar chart having three series in **one** chart having **one** axes pair. – Axel Richter Mar 13 '19 at 04:52
  • Also note that `apache poi 4.0.1` now provides better methods for creating a line chart. See https://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/xssf/usermodel/examples/. – Axel Richter Mar 13 '19 at 04:53
  • @AxelRichter I have incorporated your valuable notes into my answer using `apache poi 4.0.1` for creating a __line chart__ with __3 series__ on a simple __axes pair__. Your improvements are welcome! – hc_dev Mar 13 '19 at 20:17
  • @AxelRichter: Thank you so much for your clarification about plotting three lines and your provided solutions. – sachin Mar 14 '19 at 05:18
  • @AxelRichter: i have added the output image link in above question that i want to achieve. kindly help me to plot multiple charts in single excel file. – sachin Mar 14 '19 at 11:32
  • Not clear where the new problem is with this. You simply needs creating two different `XSSFChart`s having their own`XSSFClientAnchor` each. And the anchors should not overlap each other. – Axel Richter Mar 14 '19 at 15:58
  • @AxelRichter: sir, I have attached the code for multiple chart in one excel file.according to you i have created separate chart and XSSFClientAnchor in the above code but it fails to plot two different charts, i didn't got the result. so please guide me where i am doing wrong in the above code.please provide the code example to plot the multiple charts. i shall be very grateful to you. – sachin Mar 15 '19 at 05:56
  • If you are looking at your question, will this be helpful for others as it is now? The question's title has nothing to do with your current question and your current problem any more. That's why SO works as: **One** question -> answers. The originally question here is answered already. So please ask a new question describing your new problem. – Axel Richter Mar 15 '19 at 07:11
  • @AxelRichter: Ok sir – sachin Mar 15 '19 at 08:49

1 Answers1

1

Remarks

Since you did not provide any test-data (i.e XLS or CSV file), I have chosen 3 known cities from the US with their average monthly temperature.

You also did not provide the wished output (i.e. what your preferred chart should look like in the end). So I have chosen a simple line-chart with a single value-axis and 3 different series (which belong to the same value-system).

The resulting chart looks like this (in LibreOffice): Screenshot of Chart in LibreOffice

Solution

public class ChartWith3Lines {

    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[2];

        // 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 = "SampleData.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, 4, 0, 10, 15);

        // add legend to chart
        addLegendToChart(chart);

        // add value (left) and category (bottom) axes
        XDDFChartAxis[] axesCatVal = addAxesToChart(chart, "Month", "Avg. Temp. (Fahrenheit)");       // Add data (as Line Chart)
        // add line-chart data-collection to chart
        XDDFLineChartData chartData = (XDDFLineChartData) chart.createData(ChartTypes.LINE, axesCatVal[0], (XDDFValueAxis) axesCatVal[1]);

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

        // Line-2
        XDDFLineChartData.Series series2 = addLineSeriesToChartData(chartData
                , sheet
                ,sheetName+"!$A$2:$A$13"
                , sheetName+"!$C$2:$C$13"
                , sheetName+"!$C$1"
                ,  PresetColor.GREEN
        );
        System.out.println("added line 2: \n" + series2);

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

        chart.plot(chartData);

        // save workbook
        writeWorkbookToFile(wb,"LineChart.xlsx");

        // close workbook
        wb.close();
    }

}

Explanation

follows ..

hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • @AxelRichter:Thank you so much for your clarification about plotting three lines and your provided solutions. now i have added the output image link in above question that i want to achieve. kindly help me to plot multiple charts in single excel file. – sachin Mar 14 '19 at 11:34
  • Good to hear your feedback, although I am __not__ _AxelRichter_ ;-) If this answered your first question of __plotting a 3-line-chart__, then please __mark as accepted__. – hc_dev Mar 16 '19 at 18:55
  • Thank you so much...-@hc_dev – sachin Mar 18 '19 at 06:03