Excel Generation [Java]-BarChart-启用多类别标签

问题描述 投票:0回答:1

我使用org.apache.poi库生成了Excel。在这里,我需要生成一个条形图,该条形图应如下所示:

enter image description here和我的Excel看起来像:

enter image description here

代码:

    //CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol)
    XDDFDataSource<String> department = XDDFDataSourcesFactory.fromStringCellRange(sheet,
            new CellRangeAddress(7, 17, 1, 1));

如果我将CellRangeAddress设置为firstCol-0和lastCol-1,则它不起作用?

是否可以在Java中启用此选项:

enter image description here

java excel apache-poi bar-chart xssf
1个回答
0
投票

ap-poi的XDDF内容无法使用多级类别标签。 XDDF始终将StrRef用作图表数据源的参考。要创建多级类别标签,必须使用MultiLvlStrRef。因此,仅可以使用低级org.openxmlformats.schemas.drawingml.x2006.chart.*类直接解决任务。

这就是为什么下面的代码需要类路径中所有ooxml-schemas的完整jar,对于当前ooxml-schemas-1.4.jar来说,其为apache poi 4.1.2poi-ooxml-schemas-4.1.2.jar不包含org.openxmlformats.schemas.drawingml.x2006.chart.CTMultiLvlStrRef

并且由于Microsoft的粗略逻辑,它使用设置NoMultiLvlLbl-true作为类别轴的默认值,现在必须告诉类别轴它not没有多级标签。因此,如果轴应具有多级类别标签,则必须将NoMultiLvlLbl设置为false。好吧,似乎Microsoft想检查程序员是否很好地学习了逻辑课;-)。

完整示例:

import java.io.FileOutputStream;

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

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

public class BarChartMultiLevelCategories {

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

  String[] series = new String[]{"January","February","March"};
  String[] charges = new String[]{"Charges not Tally","Deposit","High Charges", "Quotation"};
  String[] treatment = new String[]{"Diagnosis","Explanation","Procedure"};
  String[] behaviour = new String[]{"Miscommunication","Not Attentive","Not Friendly", "Rude"};
  Double[][] values = new Double[][]{
   new Double[]{1d, 2d, 3d},
   new Double[]{1d, 3d, 2d},
   new Double[]{2d, 1d, 3d},
   new Double[]{2d, 3d, 1d},
   new Double[]{3d, 1d, 2d},
   new Double[]{3d, 2d, 1d},
   new Double[]{1d, 2d, 3d},
   new Double[]{1d, 3d, 2d},
   new Double[]{2d, 1d, 3d},
   new Double[]{2d, 3d, 1d},
   new Double[]{3d, 1d, 2d},
  };

  try (XSSFWorkbook wb = new XSSFWorkbook()) {
   //the sheet for the chart
   XSSFSheet chartSheet = wb.createSheet("barchart");
   //the sheet for the data
   XSSFSheet dataSheet = wb.createSheet("data");

   Row row;
   Cell cell;
   row = dataSheet.createRow(0);
   for (int i = 0; i < series.length; i++) {
    cell = row.createCell(i+2); cell.setCellValue(series[i]);
   }
   for (int i = 0; i < charges.length; i++) {
    row = dataSheet.createRow(i+1);
    if (i == 0) { cell = row.createCell(0); cell.setCellValue("Charges"); }
    cell = row.createCell(1); cell.setCellValue(charges[i]);
   }
   dataSheet.addMergedRegion(new CellRangeAddress(1, charges.length, 0, 0));
   for (int i = 0; i < treatment.length; i++) {
    row = dataSheet.createRow(i+1+charges.length);
    if (i == 0) { cell = row.createCell(0); cell.setCellValue("Treatment"); }
    cell = row.createCell(1); cell.setCellValue(treatment[i]);
   }
   dataSheet.addMergedRegion(new CellRangeAddress(1+charges.length, charges.length+treatment.length, 0, 0));
   for (int i = 0; i < behaviour.length; i++) {
    row = dataSheet.createRow(i+1+charges.length+treatment.length);
    if (i == 0) { cell = row.createCell(0); cell.setCellValue("Behaviour"); }
    cell = row.createCell(1); cell.setCellValue(behaviour[i]);
   }
   dataSheet.addMergedRegion(
   new CellRangeAddress(1+charges.length+treatment.length, charges.length+treatment.length+behaviour.length, 0, 0));
   for (int i = 0; i < values.length; i++) {
    Double[] valuesRow = values[i];
    row = dataSheet.getRow(i+1);
    for (int j = 0; j < valuesRow.length; j++) {
     cell = row.createCell(j+2); cell.setCellValue(valuesRow[j]);
    }
   }

   XSSFDrawing drawing = chartSheet.createDrawingPatriarch();
   XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 0, 10, 20);

   XSSFChart chart = drawing.createChart(anchor);
   chart.setTitleText("Chart title");
   chart.setTitleOverlay(false);
   //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);

   XDDFChartLegend legend = chart.getOrAddLegend();
   legend.setPosition(LegendPosition.RIGHT);

   CTChart ctChart = chart.getCTChart();
   CTPlotArea ctPlotArea = ctChart.getPlotArea();
   CTBarChart ctBarChart = ctPlotArea.addNewBarChart();
   CTBoolean ctBoolean = ctBarChart.addNewVaryColors();
   ctBoolean.setVal(true);
   ctBarChart.addNewBarDir().setVal(STBarDir.COL);

   //telling the BarChart that it has axes and giving them Ids
   ctBarChart.addNewAxId().setVal(123456);
   ctBarChart.addNewAxId().setVal(123457);

   //cat axis
   CTCatAx ctCatAx = ctPlotArea.addNewCatAx(); 
   ctCatAx.addNewAxId().setVal(123456); //id of the cat axis
   CTScaling ctScaling = ctCatAx.addNewScaling();
   ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
   ctCatAx.addNewDelete().setVal(false);
   ctCatAx.addNewAxPos().setVal(STAxPos.B);
   ctCatAx.addNewCrossAx().setVal(123457); //id of the val axis
   ctCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

   //telling the category axis that it not has no multi level labels ;-)
   ctCatAx.addNewNoMultiLvlLbl().setVal(false);

   //val axis
   CTValAx ctValAx = ctPlotArea.addNewValAx(); 
   ctValAx.addNewAxId().setVal(123457); //id of the val axis
   ctScaling = ctValAx.addNewScaling();
   ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
   ctValAx.addNewDelete().setVal(false);
   ctValAx.addNewAxPos().setVal(STAxPos.L);
   ctValAx.addNewCrossAx().setVal(123456); //id of the cat axis
   ctValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

   //series
   byte[][] seriesColors = new byte[][] {
    new byte[]{(byte)255, 0, 0}, //red
    new byte[]{0, (byte)255, 0}, //green
    new byte[]{0, 0, (byte)255}  //blue
   };
   for (int i = 0; i < series.length; i++) {
    CTBarSer ctBarSer = ctBarChart.addNewSer();
    CTSerTx ctSerTx = ctBarSer.addNewTx();
    CTStrRef ctStrRef = ctSerTx.addNewStrRef();
    ctStrRef.setF(
     new CellRangeAddress(0, 0, i+2, i+2)
          .formatAsString(dataSheet.getSheetName(), true)); //data!R1C(i+2)
    ctBarSer.addNewIdx().setVal(i);  

    CTAxDataSource cttAxDataSource = ctBarSer.addNewCat();
    //do using MultiLvlStrRef instead of StrRef 
    CTMultiLvlStrRef ctMultiLvlStrRef = cttAxDataSource.addNewMultiLvlStrRef();
    ctMultiLvlStrRef.setF(
     new CellRangeAddress(1, charges.length+treatment.length+behaviour.length, 0, 1)
          .formatAsString(dataSheet.getSheetName(), true)); //data!$A$2:$B$12

    CTNumDataSource ctNumDataSource = ctBarSer.addNewVal();
    CTNumRef ctNumRef = ctNumDataSource.addNewNumRef();
    ctNumRef.setF(
     new CellRangeAddress(1, charges.length+treatment.length+behaviour.length, i+2, i+2)
          .formatAsString(dataSheet.getSheetName(), true)); //data!R2C(i+2):R12C(i+2)

    ctBarSer.addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(seriesColors[i]);   

   } 

   try (FileOutputStream fileOut = new FileOutputStream("ooxml-bar-chart.xlsx")) {
    wb.write(fileOut);
   }
  }
 }
}
© www.soinside.com 2019 - 2024. All rights reserved.