如何使用 Apache poi 4.1.2 在饼图 3D 图表中设置自定义颜色

问题描述:

我使用 POI 4.1.2 创建了 PIE 3D 图表.并且需要为每个图例条目使用特定的颜色预计是这样

I have created PIE 3D chart using POI 4.1.2. and need to have specific colors for each legend entry expected like this

我使用的代码在这里,

final XSSFDrawing drawing = sheet2.createDrawingPatriarch();
            final XSSFClientAnchor anchor =
                    drawing.createAnchor(0, 0, 0, 0, 0, 4, 7, 20);
            

            final XSSFChart chart = drawing.createChart(anchor);
            chart.setTitleText("Unit Build Procurement");
            chart.setTitleOverlay(false);

            final XDDFChartLegend legend = chart.getOrAddLegend();
            legend.setPosition(LegendPosition.TOP_RIGHT);

            final XDDFDataSource<String> dataSource =
                    XDDFDataSourcesFactory.fromStringCellRange(sheet2,
                            new CellRangeAddress(0, 0, 0, 3));

            final XDDFNumericalDataSource<Double> values =
                    XDDFDataSourcesFactory.fromNumericCellRange(sheet2,
                            new CellRangeAddress(1, sheet2.getLastRowNum(), 0,
                                    3));

            final XDDFChartData data =
                    chart.createData(ChartTypes.PIE3D, null, null);
            data.setVaryColors(true);
            data.addSeries(dataSource, values);
            chart.plot(data);

它使用随机颜色创建图表.

It creates chart with random colors.

预先感谢您的帮助.

直到现在还没有 XDDF 方法来设置数据点颜色.使用 XDDF 方法只能设置系列颜色.所以必须使用底层的 org.openxmlformats.schemas.drawingml.x2006.chart.* 类.以下完整示例显示了这一点.它从一堆以前设置的 rgb 字节数组中设置数据点颜色.

There is no XDDF method to set data point colors until now. Only series colors can be set using XDDF methods. So one must use the underlying org.openxmlformats.schemas.drawingml.x2006.chart.* classes. Following complete example shows this. It sets data point colors from a bunch of formerly set rgb byte arrays.

import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.chart.ChartTypes;
import org.apache.poi.xddf.usermodel.chart.LegendPosition;
import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFPieChartData;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class Pie3DChart {

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

    Object[][] data = new Object[][] {
     new Object[] {"Country", "Count"},
     new Object[] {"India", 13d},
     new Object[] {"USA", 5d},
     new Object[] {"England", 12d},
     new Object[] {"South Africa", 10d}
    };
    
    try (XSSFWorkbook wb = new XSSFWorkbook()) {
      XSSFSheet sheet = wb.createSheet("piechart");
      final int NUM_OF_ROWS = data.length;
      final int NUM_OF_COLUMNS = 2;

      // create sheet data
      Row row;
      Cell cell;
      for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
        row = sheet.createRow((short) rowIndex);
        for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
          cell = row.createCell((short) colIndex);
          Object cellValue = data[rowIndex][colIndex];
          if (cellValue instanceof String) {
            cell.setCellValue((String)cellValue);
          } else if (cellValue instanceof Double) {
            cell.setCellValue((Double)cellValue);
          }
        }
      }

      // create drawing and anchor
      XSSFDrawing drawing = sheet.createDrawingPatriarch();
      XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 3, 1, 12, 15);

      // create chart
      XSSFChart chart = drawing.createChart(anchor);
      chart.setTitleText("Countries");
      chart.setTitleOverlay(false);
      XDDFChartLegend legend = chart.getOrAddLegend();
      legend.setPosition(LegendPosition.TOP_RIGHT);

      XDDFDataSource<String> cat = XDDFDataSourcesFactory.fromStringCellRange(sheet,
          new CellRangeAddress(1, NUM_OF_ROWS - 1, 0, 0));
      XDDFNumericalDataSource<Double> val = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
          new CellRangeAddress(1, NUM_OF_ROWS - 1, 1, 1));

      XDDFChartData chartData = chart.createData(ChartTypes.PIE3D, null, null);
      chartData.setVaryColors(true);
      XDDFChartData.Series series = chartData.addSeries(cat, val);
      chart.plot(chartData);

      // do not auto delete the title; is necessary for showing title in Calc
      if (chart.getCTChart().getAutoTitleDeleted() == null) chart.getCTChart().addNewAutoTitleDeleted();
      chart.getCTChart().getAutoTitleDeleted().setVal(false);

      // data point colors; is necessary for showing data points in Calc
      // some rgb colors to choose
      byte[][] colors = new byte[][] {
        new byte[] {127,(byte)255, 127},
        new byte[] {(byte)200, (byte)200, (byte)200},
        new byte[] {(byte)255,(byte)255, 127},
        new byte[] {(byte)255, 127, 127},
        new byte[] {(byte)255, 0, 0},
        new byte[] {0, (byte)255, 0},
        new byte[] {0, 0, (byte)255},
        new byte[] {80, 80, 80}
      };
      // set data point colors
      int pointCount = series.getCategoryData().getPointCount();
      for (int p = 0; p < pointCount; p++) {
        chart.getCTChart().getPlotArea().getPie3DChartArray(0).getSerArray(0).addNewDPt().addNewIdx().setVal(p);
        chart.getCTChart().getPlotArea().getPie3DChartArray(0).getSerArray(0).getDPtArray(p)
          .addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(colors[p]);
      }
 
      // write the output to a file
      try (FileOutputStream fileOut = new FileOutputStream("ooxml-pie-chart.xlsx")) {
        wb.write(fileOut);
      }
    }
  }
}