我使用JDK8和POI-4.1.0在此处使用它们的示例a link
将图表导出到Word。创建两个系列就可以了two series img, 但我只创建一个系列。系列one series img
的图表错误类别 “ lang1”,“ lang2”,“ lang3”是类别名称,但它们成为系列名称。 我没有理想。我也发现使用折线图有同样的问题 我的代码 public static void main(String[] args) throws Exception {
List<String> listLanguages = new ArrayList<>(3);
listLanguages.add("lang1");listLanguages.add("lang2");listLanguages.add("lang3");
List<Double> listCountries = new ArrayList<>(3);
listCountries.add(10d);listCountries.add(20d);listCountries.add(30d);
List<Double> listSpeakers = new ArrayList<>(3);
listSpeakers.add(14d);listSpeakers.add(25d);listSpeakers.add(33d);
String[] categories = listLanguages.toArray(new String[listLanguages.size()]);
Double[] values1 = listCountries.toArray(new Double[listCountries.size()]);
Double[] values2 = listSpeakers.toArray(new Double[listSpeakers.size()]);
try (XWPFDocument doc = new XWPFDocument()) {
XWPFChart chart = doc.createChart(5000000, 4000000);
XDDFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
final int numOfPoints = categories.length;
final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, 1);
final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2);
XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData);
series1.setTitle("a",chart.setSheetTitle("a", 1));
//XDDFBarChartData.Series series2 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData2);
//series2.setTitle("b",chart.setSheetTitle("b", 2));
bar.setVaryColors(true);
bar.setBarDirection(BarDirection.COL);
chart.plot(bar);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.LEFT);
// legend.setOverlay(false);
try (OutputStream out = new FileOutputStream("C:/Users/lyf/Desktop/barExample.docx")) {
doc.write(out);
}
}
catch(Exception e)
{
}
}
答案 0 :(得分:0)
主要问题是将setVaryColors
设置为true
意味着:
如果仅一个系列,则为该系列的每个数据点改变颜色。然后,图例显示了变化的数据点而不是序列。如果有多个系列,请为每个系列改变颜色。然后,图例显示了变化的序列。
因此,如果仅存在一个系列,则需要将setVaryColors
设置为false
。
但是另外我们需要设置AxisCrossBetween
,所以左轴与类别之间的类别轴交叉。其他的第一个和最后一个类别恰好在交叉点上,条形图只有一半可见。
最后,XDDF
目前仅准备就绪一半,并且存在许多错误。例如XDDFChart.setSheetTitle
是越野车。它创建一个表,但只有一半且不完整。创建该不完整的表后,Excel无法打开工作簿。因此无法在Word中更新图表数据。
以下代码对我有用,并且可以创建只有一个系列以及两个系列的图表。另外,我尝试在单个步骤中使代码更结构化。每个步骤都会对其操作进行评论。
import java.io.*;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;
public class CreateWordXDDFChart {
// Methode to set title in the data sheet without creating a Table but using the sheet data only.
// Creating a Table is not really necessary.
static CellReference setTitleInDataSheet(XWPFChart chart, String title, int column) throws Exception {
XSSFWorkbook workbook = chart.getWorkbook();
XSSFSheet sheet = workbook.getSheetAt(0);
XSSFRow row = sheet.getRow(0); if (row == null) row = sheet.createRow(0);
XSSFCell cell = row.getCell(column); if (cell == null) cell = row.createCell(column);
cell.setCellValue(title);
return new CellReference(sheet.getSheetName(), 0, column, true, true);
}
public static void main(String[] args) throws Exception {
try (XWPFDocument document = new XWPFDocument()) {
// create the data
String[] categories = new String[]{"Lang 1", "Lang 2", "Lang 3"};
Double[] valuesA = new Double[]{10d, 20d, 30d};
Double[] valuesB = new Double[]{15d, 25d, 35d};
// create the chart
XWPFChart chart = document.createChart(15*Units.EMU_PER_CENTIMETER, 10*Units.EMU_PER_CENTIMETER);
// create data sources
int numOfPoints = categories.length;
String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
String valuesDataRangeA = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
String valuesDataRangeB = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
XDDFDataSource<String> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
XDDFNumericalDataSource<Double> valuesDataA = XDDFDataSourcesFactory.fromArray(valuesA, valuesDataRangeA, 1);
XDDFNumericalDataSource<Double> valuesDataB = XDDFDataSourcesFactory.fromArray(valuesB, valuesDataRangeB, 2);
// create axis
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
// Set AxisCrossBetween, so the left axis crosses the category axis between the categories.
// Else first and last category is exactly on cross points and the bars are only half visible.
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
// create chart data
XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
((XDDFBarChartData)data).setBarDirection(BarDirection.COL);
// create series
// if only one series do not vary colors for each bar
((XDDFBarChartData)data).setVaryColors(false);
XDDFChartData.Series series = data.addSeries(categoriesData, valuesDataA);
// XDDFChart.setSheetTitle is buggy. It creates a Table but only half way and incomplete.
// Excel cannot opening the workbook after creatingg that incomplete Table.
// So updating the chart data in Word is not possible.
//series.setTitle("a", chart.setSheetTitle("a", 1));
series.setTitle("a", setTitleInDataSheet(chart, "a", 1));
/*
// if more than one series do vary colors of the series
((XDDFBarChartData)data).setVaryColors(true);
series = data.addSeries(categoriesData, valuesDataB);
//series.setTitle("b", chart.setSheetTitle("b", 2));
series.setTitle("b", setTitleInDataSheet(chart, "b", 2));
*/
// plot chart data
chart.plot(data);
// create legend
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.LEFT);
legend.setOverlay(false);
// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("CreateWordXDDFChart.docx")) {
document.write(fileOut);
}
}
}
}