颜色条形图条取决于使用 Apache POI 的数据

Color BarChart bars depending on data using Apache POI

我正在尝试将图表中每个单独的条形图的填充颜色设置为单独的自定义颜色,但我还没有找到具体方法。

到目前为止,这是我的代码。布局很好,但图表条都是相同的颜色(矢车菊蓝色)。我知道我可以使用 XDDFChartData:setVaryColors 选项来使用不同的颜色,但我找不到指定要使用的颜色的方法(比如在我的示例中 'Books' 为红色,'DVDs' 蓝色等)。

final Workbook workbook = new XSSFWorkbook();
final Sheet sheet = workbook.createSheet("MySheet");

Row row = sheet.createRow(1);

Cell cell = row.createCell(1);
cell.setCellValue("Product");

cell = row.createCell(2);
cell.setCellValue("Orders");

row = sheet.createRow(2);

cell = row.createCell(1);
cell.setCellValue("Books");

cell = row.createCell(2);
cell.setCellValue(50);

row = sheet.createRow(3);

cell = row.createCell(1);
cell.setCellValue("DVDs");

cell = row.createCell(2);
cell.setCellValue(25);

row = sheet.createRow(4);

cell = row.createCell(1);
cell.setCellValue("CDs");

cell = row.createCell(2);
cell.setCellValue(140);

XSSFDrawing drawing = ((XSSFSheet) sheet).createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 4, 1, 12, 15 );

XSSFChart chart = drawing.createChart(anchor);
chart.setTitleText("Products");
chart.setTitleOverlay(false);

CTBoolean FALSE = CTBoolean.Factory.newInstance();
FALSE.setVal(false);
chart.getCTChartSpace().setRoundedCorners(FALSE);

XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setMajorTickMark(AxisTickMark.NONE);

XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

XDDFDataSource<String> compliances = XDDFDataSourcesFactory.fromStringCellRange((XSSFSheet) sheet, new CellRangeAddress(2, 4, 1, 1));

XDDFNumericalDataSource<Double> components = XDDFDataSourcesFactory.fromNumericCellRange((XSSFSheet) sheet, new CellRangeAddress(2, 4, 2, 2));

XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);

XDDFChartData.Series series1 = data.addSeries(compliances, components);
series1.setTitle("Components by Compliance", null);

chart.plot(data);

XDDFBarChartData bar = (XDDFBarChartData) data;
bar.setBarDirection(BarDirection.BAR);

CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();

Color col1 = new Color(100, 149, 237);
rgb.setVal(new byte[]{(byte) col1.getRed(), (byte) col1.getGreen(), (byte) col1.getBlue()});

CTSolidColorFillProperties fillProp = CTSolidColorFillProperties.Factory.newInstance();
fillProp.setSrgbClr(rgb);

CTShapeProperties ctShapeProperties = CTShapeProperties.Factory.newInstance();
ctShapeProperties.setSolidFill(fillProp);
        chart.getCTChart().getPlotArea().getBarChartList().get(0).getSerList().get(0).setSpPr(ctShapeProperties);

IntStream.range(0, 10).forEach(sheet::autoSizeColumn);

有什么想法吗?

干杯!

您似乎想要为每个数据点而不是条形系列着色。如果是这样,那么这就是与 how to set custom colors in pie 3D Chart using Apache poi 4.1.2 相同的问题。区别仅在于图表类型。

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

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

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

import org.openxmlformats.schemas.drawingml.x2006.chart.*;

public class BarChartOneSeries {

  public static void main(String[] args) throws IOException {
    final Workbook workbook = new XSSFWorkbook();
    final Sheet sheet = workbook.createSheet("MySheet");

    Row row = sheet.createRow(1);

    Cell cell = row.createCell(1);
    cell.setCellValue("Product");

    cell = row.createCell(2);
    cell.setCellValue("Orders");

    row = sheet.createRow(2);

    cell = row.createCell(1);
    cell.setCellValue("Books");

    cell = row.createCell(2);
    cell.setCellValue(50);

    row = sheet.createRow(3);

    cell = row.createCell(1);
    cell.setCellValue("DVDs");

    cell = row.createCell(2);
    cell.setCellValue(25);

    row = sheet.createRow(4);

    cell = row.createCell(1);
    cell.setCellValue("CDs");

    cell = row.createCell(2);
    cell.setCellValue(140);

    XSSFDrawing drawing = ((XSSFSheet) sheet).createDrawingPatriarch();
    XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 4, 1, 12, 15 );

    XSSFChart chart = drawing.createChart(anchor);
    chart.setTitleText("Products");
    chart.setTitleOverlay(false);

    CTBoolean FALSE = CTBoolean.Factory.newInstance();
    FALSE.setVal(false);
    chart.getCTChartSpace().setRoundedCorners(FALSE);

    XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
    bottomAxis.setMajorTickMark(AxisTickMark.NONE);

    XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
    leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
    leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

    XDDFDataSource<String> compliances = XDDFDataSourcesFactory.fromStringCellRange((XSSFSheet) sheet, new CellRangeAddress(2, 4, 1, 1));

    XDDFNumericalDataSource<Double> components = XDDFDataSourcesFactory.fromNumericCellRange((XSSFSheet) sheet, new CellRangeAddress(2, 4, 2, 2));

    XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);

    XDDFChartData.Series series = data.addSeries(compliances, components);
    series.setTitle("Components by Compliance", null);

    chart.plot(data);

    XDDFBarChartData bar = (XDDFBarChartData) data;
    bar.setBarDirection(BarDirection.BAR);


    // 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().getBarChartArray(0).getSerArray(0).addNewDPt().addNewIdx().setVal(p);
      chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(0).getDPtArray(p)
        .addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(colors[p]);
    }
    // write the output to a file
    try (FileOutputStream fileOut = new FileOutputStream("ooxml-bar-chart.xlsx")) {
      workbook.write(fileOut);
    }
    workbook.close();
  }
}