使用Apache POI在Excel中创建条形图 [英] Create Bar Chart in Excel with Apache POI

查看:1406
本文介绍了使用Apache POI在Excel中创建条形图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Apache POI在XLSX电子表格中创建条形图,但是,当我尝试打开该文件时,Excel会一直说内容有问题并删除图表。以下是我要做的完整代码:

I'm trying to create a Bar Chart in an XLSX Spreadsheet using Apache POI, but Excel keeps saying that there's a problem with the content and deleting the chart when I try to open the file. Here's the full code of what I'm trying to do:

public static void createBarChart() {

        Workbook wb = new XSSFWorkbook();
        Sheet sheet = wb.createSheet("Sheet2");
        Row row;
        Cell cell;

        row = sheet.createRow(0);
        row.createCell(0);
        row.createCell(1).setCellValue("HEADER 1");
        row.createCell(2).setCellValue("HEADER 2");
        row.createCell(3).setCellValue("HEADER 3");

        for (int r = 1; r < 5; r++) {
            row = sheet.createRow(r);
            cell = row.createCell(0);
            cell.setCellValue("Serie " + r);
            cell = row.createCell(1);
            cell.setCellValue(123);
            cell = row.createCell(2);
            cell.setCellValue(456);
            cell = row.createCell(3);
            cell.setCellValue(789);
        }

        Drawing drawing = sheet.createDrawingPatriarch();
        ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 5, 20);

        Chart chart = drawing.createChart(anchor);

        CTChart ctChart = ((XSSFChart) chart).getCTChart();

        ctChart.addNewTitle();

        CTPlotArea ctPlotArea = ctChart.getPlotArea();
        CTBarChart ctBarChart = ctPlotArea.addNewBarChart();

        ctBarChart.addNewBarDir().setVal(STBarDir.COL);
        ctBarChart.addNewGrouping().setVal(STBarGrouping.CLUSTERED);
        ctBarChart.addNewVaryColors().setVal(false);

        // First series
        CTBarSer ctBarSer = ctBarChart.addNewSer();

        ctBarSer.addNewIdx().setVal(0);
        ctBarSer.addNewOrder().setVal(0);

        // [01] Title
        CTSerTx ctSerTx = ctBarSer.addNewTx();
        CTStrRef ctSerTxStrRef = ctSerTx.addNewStrRef();
        ctSerTxStrRef.setF("Sheet2!$A$2");

        CTStrData strCache = ctSerTxStrRef.addNewStrCache();
        strCache.addNewPtCount().setVal(1);
        CTStrVal newPt = strCache.addNewPt();
        newPt.setV("Serie 1");
        newPt.setIdx(0);

        // [01] SpPr
        CTShapeProperties spPr = ctBarSer.addNewSpPr();
        CTSolidColorFillProperties solidFill = spPr.addNewSolidFill();
        solidFill.addNewSchemeClr().setVal(STSchemeColorValImpl.ACCENT_1);
        spPr.addNewLn().addNewNoFill();
        spPr.addNewEffectLst();

        // [01] Invert if negative
        ctBarSer.addNewInvertIfNegative().setVal(false);

        // [01] Series titles
        CTAxDataSource newCat = ctBarSer.addNewCat();
        CTStrRef addNewStrRef = newCat.addNewStrRef();
        addNewStrRef.setF("Sheet2!$B$1:$D$1");

        CTStrData addNewStrCache = addNewStrRef.addNewStrCache();
        addNewStrCache.addNewPtCount().setVal(3);

        CTStrVal pt1 = addNewStrCache.addNewPt();
        pt1.setIdx(0);
        pt1.setV(sheet.getRow(0).getCell(1).getStringCellValue());

        CTStrVal pt2 = addNewStrCache.addNewPt();
        pt2.setIdx(1);
        pt2.setV(sheet.getRow(0).getCell(2).getStringCellValue());

        CTStrVal pt3 = addNewStrCache.addNewPt();
        pt3.setIdx(2);
        pt3.setV(sheet.getRow(0).getCell(3).getStringCellValue());

        // [01] Series values
        CTNumDataSource newVal = ctBarSer.addNewVal();
        CTNumRef numRef = newVal.addNewNumRef();
        numRef.setF("Sheet2!$B$2:$D$2");
        CTNumData numCache = numRef.addNewNumCache();
        numCache.addNewPtCount().setVal(3);

        CTNumVal numpt1 = numCache.addNewPt();
        numpt1.setIdx(0);
        numpt1.setV(String.valueOf(sheet.getRow(1).getCell(1).getNumericCellValue()));

        CTNumVal numpt2 = numCache.addNewPt();
        numpt2.setIdx(1);
        numpt2.setV(String.valueOf(sheet.getRow(1).getCell(2).getNumericCellValue()));

        CTNumVal numpt3 = numCache.addNewPt();
        numpt3.setIdx(2);
        numpt3.setV(String.valueOf(sheet.getRow(1).getCell(3).getNumericCellValue()));

        // dLbls
        CTDLbls dLbls = ctBarChart.addNewDLbls();
        dLbls.addNewShowBubbleSize().setVal(false);
        dLbls.addNewShowLegendKey().setVal(false);
        dLbls.addNewShowCatName().setVal(false);
        dLbls.addNewShowSerName().setVal(false);
        dLbls.addNewShowPercent().setVal(false);
        dLbls.addNewShowVal().setVal(false);

        FileOutputStream fileOut = new FileOutputStream("barchart.xlsx");
        wb.write(fileOut);
        wb.close();
        fileOut.close();
    }

任何人都可以帮助我找到(并且解决)问题?感谢提前!

Can anyone help me find (and, well, solve) the issue? Thanks in advance!

推荐答案

hew,难生;-)。对于不了解背景知识的用户, Apache POI仅支持ScatterCharts和LineCharts为什么? 。描述了原则上如何进行。

Phew, difficult birth ;-). For users without knowledge of the background Apache POI supports only ScatterCharts and LineCharts why?. There is described how to proceed in principle.

正如我所说。采取最简单的可能的条形图进行测试。这是一个有两个值的系列。那么你会看到你完全忘记了代码中的轴。饼图没有轴。这就是为什么他们没有必要。但是,如果没有轴,条形图将无法正常工作。

As I said. Take the simplest possible bar chart for testing first. That is one series with two values. Then you would have seen that you have completely forgotten the axes in your code. A pie chart has no axes. Thats why there they are not necessary. But a bar chart will not work without axes.

相反,您可以无耻地忘记所有名为缓存的内容。

Instead you can unscrupulously forget all things what is named "cache".

是否需要其他事情是由尝试和错误决定的。还可以阅读 Office OpenXML推荐。可能缺少所有元素的 minOccurs <>0`导致在打开工作簿时删除图形。

Whether other things are needed is determined by try and error. Also one could read the Office OpenXML recommendation. Probably the missing of all elements having minOccurs <> "0"` leads to deleting the Drawing while opening the Workbook.

简单的条形图示例:

import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.ss.usermodel.charts.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFChart;

import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBoolean;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumRef;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTStrRef;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTCatAx;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTScaling;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTLegend;
import org.openxmlformats.schemas.drawingml.x2006.chart.STAxPos;
import org.openxmlformats.schemas.drawingml.x2006.chart.STBarDir;
import org.openxmlformats.schemas.drawingml.x2006.chart.STOrientation;
import org.openxmlformats.schemas.drawingml.x2006.chart.STLegendPos;
import org.openxmlformats.schemas.drawingml.x2006.chart.STTickLblPos;

public class BarChart {

    public static void main(String[] args) throws Exception {
        Workbook wb = new XSSFWorkbook();
        Sheet sheet = wb.createSheet("Sheet1");

        Row row;
        Cell cell;

        row = sheet.createRow(0);
        row.createCell(0);
        row.createCell(1).setCellValue("HEADER 1");
        row.createCell(2).setCellValue("HEADER 2");
        row.createCell(3).setCellValue("HEADER 3");

        for (int r = 1; r < 5; r++) {
            row = sheet.createRow(r);
            cell = row.createCell(0);
            cell.setCellValue("Serie " + r);
            cell = row.createCell(1);
            cell.setCellValue(new java.util.Random().nextDouble());
            cell = row.createCell(2);
            cell.setCellValue(new java.util.Random().nextDouble());
            cell = row.createCell(3);
            cell.setCellValue(new java.util.Random().nextDouble());
        }

        Drawing drawing = sheet.createDrawingPatriarch();
        ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 8, 20);

        Chart chart = drawing.createChart(anchor);

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

        for (int r = 2; r < 6; r++) {
           CTBarSer ctBarSer = ctBarChart.addNewSer();
           CTSerTx ctSerTx = ctBarSer.addNewTx();
           CTStrRef ctStrRef = ctSerTx.addNewStrRef();
           ctStrRef.setF("Sheet1!$A$" + r);
           ctBarSer.addNewIdx().setVal(r-2);  
           CTAxDataSource cttAxDataSource = ctBarSer.addNewCat();
           ctStrRef = cttAxDataSource.addNewStrRef();
           ctStrRef.setF("Sheet1!$B$1:$D$1"); 
           CTNumDataSource ctNumDataSource = ctBarSer.addNewVal();
           CTNumRef ctNumRef = ctNumDataSource.addNewNumRef();
           ctNumRef.setF("Sheet1!$B$" + r + ":$D$" + r);

           //at least the border lines in Libreoffice Calc ;-)
           ctBarSer.addNewSpPr().addNewLn().addNewSolidFill().addNewSrgbClr().setVal(new byte[] {0,0,0});   

        } 

        //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);

        //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);

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

System.out.println(ctChart);

        FileOutputStream fileOut = new FileOutputStream("BarChart.xlsx");
        wb.write(fileOut);
        fileOut.close();
    }
}

此示例需要所有模式的完整jar ooxml-schemas-1.3.jar FAQ-N10025

This example needs the full jar of all of the schemas ooxml-schemas-1.3.jar as mentioned in the FAQ-N10025.

这篇关于使用Apache POI在Excel中创建条形图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆