2016-08-12 122 views
5

我试图在使用Apache POI的XLSX Spreadsheet中创建条形图,但Excel一直说当我尝试打开文件时存在内容问题并删除图表。这里是我想要做的全部代码:使用Apache POI在Excel中创建条形图

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(); 
    } 

任何人都可以帮我找到(而且,解决)这个问题吗?提前致谢!

回答

12

P,难孕育;-)。适用于不知道背景的用户Apache POI supports only ScatterCharts and LineCharts why?。原则上介绍如何进行。

正如我所说。先拿最简单的可能的条形图进行测试。这是一个有两个值的系列。然后你会看到你完全忘记了你的代码中的轴。饼图没有轴。这就是为什么他们没有必要。但是如果没有坐标轴,条形图将不起作用。

相反,您可以不加思索地忘记所有名为“缓存”的东西。

是否需要其他东西取决于尝试和错误。也可以阅读Office OpenXML recommendation。可能缺少所有具有minOccurs <>“0”的元素导致在打开工作簿时删除图形。

为条形图简单的例子:

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(); 
    } 
} 

此示例需要所有如在FAQ-N10025提到的模式ooxml-schemas-1.3.jar的充分广口瓶中。

+3

不要假设您想使用此代码+知识将BarChart功能贡献给XSSF,对吗? :) – Gagravarr

+0

工作就像一个魅力:)惊人的工作,非常感谢你! – LuTHieR

+0

我尝试用poi 3-15,但有缺失的类(CTBarChart,STBarDir ...)。此示例中使用的是什么版本? –