我有一个docx文件,其中仅包含两个图表,一个是饼图,另一个是甜甜圈图,如下所示:
我将按照以下answer中的说明修改那些图表数据:
问题是:
pieChart.getChartSeries ().size (); // give me 1
doughnutChart.getChartSeries ().size (); // give me 0
我认为oughnutChart系列应该可用,因为我已经检查了doughnutChart工作簿(
doughnutChart.getWorkbook ();
)是否有效(显示正确的数据),并且甜甜圈图表也正确显示在Word应用程序上。问题是为什么
doughnutChart.getChartSeries ().size ();
在我期望给我1时给我零。是一个错误,还是我应该区别对待饼图和甜甜圈图?如果是这样,如何从甜甜圈图中获取序列并对其进行修改?===更新===
我放弃获得甜甜圈图系列,因为它没有得到图书馆的直接支持。
我试图使用一段代码将环形数据全部替换为一个新的代码:
private void replacePiasChartData (
String title,
XWPFChart chart, // the doughnut chart get from XWPFDocument
SourceData data)
{
XSSFWorkbook workbook = new XSSFWorkbook ();
XSSFSheet sheet = workbook.createSheet ("sheet");
chart.setWorkbook (workbook);
chart.setTitleText (title);
int rowNum = 1;
sheet.createRow (rowNum).createCell (0).setCellValue ("1st Qtr");
sheet.getRow (rowNum).createCell (1).setCellValue (data.getChartValue ());
rowNum++;
sheet.createRow (rowNum).createCell (0).setCellValue ("2nd Qtr");
sheet.getRow (rowNum).createCell (1).setCellValue (100d - data.getChartValue ());
XDDFDataSource<String> category = XDDFDataSourcesFactory
.fromStringCellRange (sheet, new CellRangeAddress (1, 2, 0, 0));
XDDFNumericalDataSource<Double> value = XDDFDataSourcesFactory
.fromNumericCellRange (sheet, new CellRangeAddress (1, 2, 1, 1));
XDDFChartData chartData =
new XDDFPieChartData (chart.getCTChart ().getPlotArea ().addNewPieChart ());
chartData.addSeries (category, value);
chart.plot (chartData);
}
该图表将使用新数据进行更新,但是初始图表仍然存在(作为内部甜甜圈图),是否有任何方法可以删除它,从而使替换过程正确完成?我认为我应该删除初始图表数据,但是我找不到任何方法。
当前的图表如下所示:
===更新II ===
通过使用行为与饼图非常相似的其他类来获取甜甜圈图系列,可以解决该问题。
最佳答案
明确的方法是提供XDDFDoughnutChartData
。这很简单,因为它与XDDFPieChartData
并没有太大区别。唯一的区别是使用CTDoughnutChart
而不是CTPieChart
。
以下是从https://svn.apache.org/viewvc/poi/tags/REL_4_1_0/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFPieChartData.java?view=markup派生的实现:
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.util.Beta;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDoughnutChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
@Beta
public class XDDFDoughnutChartData extends XDDFChartData {
private CTDoughnutChart chart;
public XDDFDoughnutChartData(CTDoughnutChart chart) {
this.chart = chart;
for (CTPieSer series : chart.getSerList()) {
this.series.add(new Series(series, series.getCat(), series.getVal()));
}
}
@Override
public void setVaryColors(boolean varyColors) {
if (chart.isSetVaryColors()) {
chart.getVaryColors().setVal(varyColors);
} else {
chart.addNewVaryColors().setVal(varyColors);
}
}
@Override
public XDDFChartData.Series addSeries(XDDFDataSource<?> category,
XDDFNumericalDataSource<? extends Number> values) {
final int index = this.series.size();
final CTPieSer ctSer = this.chart.addNewSer();
ctSer.addNewCat();
ctSer.addNewVal();
ctSer.addNewIdx().setVal(index);
ctSer.addNewOrder().setVal(index);
final Series added = new Series(ctSer, category, values);
this.series.add(added);
return added;
}
public class Series extends XDDFChartData.Series {
private CTPieSer series;
protected Series(CTPieSer series, XDDFDataSource<?> category,
XDDFNumericalDataSource<? extends Number> values) {
super(category, values);
this.series = series;
}
protected Series(CTPieSer series, CTAxDataSource category, CTNumDataSource values) {
super(XDDFDataSourcesFactory.fromDataSource(category), XDDFDataSourcesFactory.fromDataSource(values));
this.series = series;
}
@Override
protected CTSerTx getSeriesText() {
if (series.isSetTx()) {
return series.getTx();
} else {
return series.addNewTx();
}
}
@Override
public void setShowLeaderLines(boolean showLeaderLines) {
if (!series.isSetDLbls()) {
series.addNewDLbls();
}
if (series.getDLbls().isSetShowLeaderLines()) {
series.getDLbls().getShowLeaderLines().setVal(showLeaderLines);
} else {
series.getDLbls().addNewShowLeaderLines().setVal(showLeaderLines);
}
}
@Override
public XDDFShapeProperties getShapeProperties() {
if (series.isSetSpPr()) {
return new XDDFShapeProperties(series.getSpPr());
} else {
return null;
}
}
@Override
public void setShapeProperties(XDDFShapeProperties properties) {
if (properties == null) {
if (series.isSetSpPr()) {
series.unsetSpPr();
}
} else {
if (series.isSetSpPr()) {
series.setSpPr(properties.getXmlObject());
} else {
series.addNewSpPr().set(properties.getXmlObject());
}
}
}
public long getExplosion() {
if (series.isSetExplosion()) {
return series.getExplosion().getVal();
} else {
return 0;
}
}
public void setExplosion(long explosion) {
if (series.isSetExplosion()) {
series.getExplosion().setVal(explosion);
} else {
series.addNewExplosion().setVal(explosion);
}
}
@Override
protected CTAxDataSource getAxDS() {
return series.getCat();
}
@Override
protected CTNumDataSource getNumDS() {
return series.getVal();
}
}
}
现在,在代码中使用以下代码将适用于饼图和fpr甜甜圈图:
Word模板:
码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.CellRangeAddress;
public class WordChangeChartDataPieOrDoughnut {
public static void main(String[] args) throws Exception {
String filePath = "TEMP_Chart_Simple.docx"; // has template chart having 1 series, 4 categories
String filePathNew = "New_Chart_Simple.docx";
Object[][] data = new Object[][] { // 1 series, 4 categories
{"", "Clothing sales"}, // series titles
{"Trousers", 123d}, // category 1
{"Shirt", 345d}, // category 2
{"Skirt", 180d}, // category 3
{"Blouse", 180d} // category 4
};
XWPFDocument document = new XWPFDocument(new FileInputStream(filePath));
XWPFChart chart = document.getCharts().get(0);
XSSFWorkbook chartDataWorkbook = chart.getWorkbook();
String sheetName = chartDataWorkbook.getSheetName(0);
XSSFSheet chartDataSheet = chartDataWorkbook.getSheet(sheetName);
XDDFChartData chartData = null;
if (chart.getChartSeries().size() == 1) { // only one chart data
chartData = chart.getChartSeries().get(0); // pie chart or other supported chart
} else if (chart.getCTChart().getPlotArea().getDoughnutChartList().size() == 1) { // only one doughnut chart data
chartData = new XDDFDoughnutChartData(chart.getCTChart().getPlotArea().getDoughnutChartList().get(0)); //doughnut chart
}
if (chartData != null) {
if (chartData.getSeries().size() == 1) { // exact one series
int rMin = 1;
int rMax = 4;
// set new category data
XDDFCategoryDataSource category = null;
int c = 0;
for (int r = rMin; r < rMax+1; r++) {
chartDataSheet.getRow(r).getCell(c).setCellValue((String)data[r][c]); // in sheet
}
category = XDDFDataSourcesFactory.fromStringCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); // in chart
// series 1
XDDFChartData.Series series1 = chartData.getSeries().get(0);
c = 1;
// set new title
String series1Title = (String)data[0][c];
chartDataSheet.getRow(0).getCell(c).setCellValue(series1Title); // in sheet
chartDataSheet.getTables().get(0).getCTTable().getTableColumns().getTableColumnList().get(c).setName(series1Title);
if (chartDataSheet.getTables().size() > 0) {
if (chartDataSheet.getTables().get(0).getCTTable().getTableColumns().getTableColumnList().size() > c)
chartDataSheet.getTables().get(0).getCTTable().getTableColumns().getTableColumnList().get(c).setName(series1Title);
}
series1.setTitle(series1Title, new CellReference(sheetName, 0, c, true, true)); // in chart
// set new values
XDDFNumericalDataSource<Double> values = null;
for (int r = rMin; r < rMax+1; r++) {
chartDataSheet.getRow(r).getCell(c).setCellValue((Double)data[r][c]); // in sheet
}
values = XDDFDataSourcesFactory.fromNumericCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c));
series1.replaceData(category, values);
series1.plot(); //in chart
}
}
FileOutputStream out = new FileOutputStream(filePathNew);
document.write(out);
out.close();
document.close();
}
}
结果:
关于java - 获取甜甜圈图系列在可用时给出零结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57783332/