Search code examples
javaapache-poipowerpoint

How to change the color of the text in barChart ApachePoi


my problem is that I need to change the color of the text/font in barchart. By the text I mean a value printed on the particular bar (the 2 top most series) (see image - red circles). In order to be more visible, I want to set the color to white.

Also I need them to be Bold.

How can I achieve this? (I tried to google, but couldn't find anything, that would lead me to the solution)

enter image description here

To give more overview about my code, this is how i set bar background color:

    private void setColorsForMainChart(XSLFChart chart) {
        chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(0).addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{(byte) 210, (byte) 38, (byte) 48});
        chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(1).addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{(byte) 81, (byte) 174, (byte) 48});
        chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(2).addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{(byte) 113, (byte) 238, (byte) 50});
        chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(3).addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{(byte) 192, (byte) 192, (byte) 192});
        chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(4).addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{(byte) 127, (byte) 127, (byte) 127});
        chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(5).addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{(byte) 64, (byte) 64, (byte) 64});
    }

and my chart is created like so:

private void addBarChart(XSLFChart chart, int numOfPoints, List<Double[]> values, XDDFDataSource<String> categoriesData) {
        int subBarLevel = 1;
        List<XDDFNumericalDataSource<Double>> valuesData = getValuesData(chart, values, numOfPoints, subBarLevel);

        // create axis
        XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        bottomAxis.getOrAddTextProperties().setFontSize(7.0);
        bottomAxis.getOrAddTextProperties().setBold(true);
        XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
        leftAxis.getOrAddTextProperties().setFontSize(9.0);
        leftAxis.getOrAddTextProperties().setBold(true);
        leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
        leftAxis.setMaximum(getYAxisMaximum());
        leftAxis.setMinimum(0);
        // Set AxisCrossBetween, so the left axis crosses the category axis between the categories.
        // Else first and last category is exactly on cross points and the bars are only half visible.
        leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

        // create chart data
        XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
        ((XDDFBarChartData) data).setBarDirection(BarDirection.COL);
        // stacked bar chart
        ((XDDFBarChartData) data).setBarGrouping(BarGrouping.STACKED);
        ((XDDFBarChartData) data).setOverlap((byte) 100);

        // create series
        createSeriesBarChart(chart, valuesData, data, categoriesData);

        // plot chart data
        chart.plot(data);

        // add data labels
        for (int s = 0; s < valuesData.size(); s++) {
            chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).addNewDLbls();
            chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls()
                    .addNewDLblPos().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STDLblPos.CTR);

            chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewNumFmt();
            chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().getNumFmt()
                    .setSourceLinked(false);
            chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().getNumFmt()
                    .setFormatCode("0;-0;");

            chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowVal().setVal(true);
            chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowLegendKey().setVal(false);
            chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowCatName().setVal(false);
            chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowSerName().setVal(false);
            chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowPercent().setVal(false);
            chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowBubbleSize().setVal(false);
        }

        setColorsForMainChart(chart);
    }

Thank you for your help!


Solution

  • To fulfill such requirements one needs to know the internals of Office Open XML. But at least one should know the correct terms. What you wants changing is font of data labels of some of the series. Your code creates the data labels for each series in this loop:

    // add data labels
    for (int s = 0; s < valuesData.size(); s++) {
     ...
    }
    

    The code seems to come from this answer: Show SUM Value above Stacked bar with Apache poi.

    How to go further? Create the chart using your code. Then open /ppt/charts/chart1.xml from the *.pptx ZIP archive. Now do changing what is needed using PowerPoint and save. Now open /ppt/charts/chart1.xml from the *.pptx ZIP archive again and compare what has changed.

    If you had changed the font of data labels of one of the series, then you will find the XML

    <c:txPr>
     <a:bodyPr/>
     <a:p>
      <a:pPr>
       <a:defRPr b="true">
        <a:solidFill>
         <a:srgbClr val="FFFFFF"/>
        </a:solidFill>
       </a:defRPr>
      </a:pPr>
     </a:p>
    </c:txPr>
    

    added between tags <c:dLbls>...</c:dLbls> of that series.

    Now the need is to rebuild this using apache poi.

    Following example changes font of data labels of fourth series. It fits to the complete example in my answer in Show SUM Value above Stacked bar with Apache poi.

       // add data labels
       for (int s = 0 ; s < valuesData.size(); s++) {
        ...
        
        if (s==3) {
         chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewTxPr();
         chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().getTxPr().addNewBodyPr();
         chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().getTxPr().addNewP();
         chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().getTxPr().getPArray(0).addNewPPr();
         chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().getTxPr().getPArray(0).getPPr().addNewDefRPr();
         chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().getTxPr().getPArray(0).getPPr().getDefRPr().setB(true);
         chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().getTxPr().getPArray(0).getPPr().getDefRPr().addNewSolidFill();
         chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().getTxPr().getPArray(0).getPPr().getDefRPr().getSolidFill().addNewSrgbClr()
          .setVal(new byte[]{(byte) 255, (byte) 255, (byte) 255});
        }
    
       }