Создание гистограммы в Excel с помощью Apache POI
Я пытаюсь создать гистограмму в таблице XLSX с помощью 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");
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:$D");
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:$D");
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();
}
может кто-нибудь помочь мне найти (и, ну, решить) проблему? Заранее спасибо!
1 ответов
Фух, тяжелые роды ;-). Для пользователей без знания фона Апач пои поддерживает только ScatterCharts и LineCharts почему?. Там описано, как действовать в принципе.
как я уже сказал. Взять простой возможная гистограмма для тестирования первой. Это один ряд с двумя значениями. Тогда вы бы увидели, что вы полностью забыли оси в своем коде. Круговая диаграмма не имеет осей. Вот почему там они не нужны. Но гистограмма не будет работать без оси.
вместо этого вы можете бессовестно забыть все, что называется "кэш".
нужны ли другие вещи определяется методом проб и ошибок. Также можно было прочитать рекомендация Office OpenXML. Вероятно, отсутствует все элементы, имеющие 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:$D");
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();
}
}
этот пример должен полная банка всех схем ooxml-schemas-1.3.jar
как говорится в часто задаваемые вопросы-N10025.